feature: Add EVDI display initialization
This commit is contained in:
parent
6d5444a31c
commit
a9156f7ec2
3 changed files with 73 additions and 14 deletions
74
app/main.go
74
app/main.go
|
@ -5,20 +5,36 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
"os/signal"
|
||||||
"path"
|
"path"
|
||||||
|
"syscall"
|
||||||
|
|
||||||
libconfig "git.terah.dev/UnrealXR/unrealxr/app/config"
|
libconfig "git.terah.dev/UnrealXR/unrealxr/app/config"
|
||||||
"git.terah.dev/UnrealXR/unrealxr/app/edidtools"
|
"git.terah.dev/UnrealXR/unrealxr/app/edidtools"
|
||||||
|
"git.terah.dev/UnrealXR/unrealxr/app/renderer"
|
||||||
"git.terah.dev/UnrealXR/unrealxr/edidpatcher"
|
"git.terah.dev/UnrealXR/unrealxr/edidpatcher"
|
||||||
|
"git.terah.dev/imterah/goevdi/libevdi"
|
||||||
"github.com/charmbracelet/log"
|
"github.com/charmbracelet/log"
|
||||||
"github.com/goccy/go-yaml"
|
"github.com/goccy/go-yaml"
|
||||||
"github.com/kirsle/configdir"
|
"github.com/kirsle/configdir"
|
||||||
|
"github.com/tebeka/atexit"
|
||||||
"github.com/urfave/cli/v3"
|
"github.com/urfave/cli/v3"
|
||||||
|
|
||||||
rl "git.terah.dev/UnrealXR/raylib-go/raylib"
|
rl "git.terah.dev/UnrealXR/raylib-go/raylib"
|
||||||
)
|
)
|
||||||
|
|
||||||
func mainEntrypoint(context.Context, *cli.Command) error {
|
func mainEntrypoint(context.Context, *cli.Command) error {
|
||||||
|
// Allow for clean exits
|
||||||
|
c := make(chan os.Signal, 1)
|
||||||
|
signal.Notify(c, os.Interrupt, syscall.SIGTERM)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
<-c
|
||||||
|
log.Info("Exiting...")
|
||||||
|
atexit.Exit(1)
|
||||||
|
}()
|
||||||
|
|
||||||
|
// TODO: add built-in privesc
|
||||||
if os.Geteuid() != 0 {
|
if os.Geteuid() != 0 {
|
||||||
return fmt.Errorf("this program must be run as root")
|
return fmt.Errorf("this program must be run as root")
|
||||||
}
|
}
|
||||||
|
@ -63,7 +79,7 @@ func mainEntrypoint(context.Context, *cli.Command) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
libconfig.InitializePotentiallyMissingConfigValues(config)
|
libconfig.InitializePotentiallyMissingConfigValues(config)
|
||||||
log.Info("Attempting to read display EDID file and fetch metadata")
|
log.Debug("Attempting to read display EDID file and fetch metadata")
|
||||||
|
|
||||||
displayMetadata, err := edidtools.FetchXRGlassEDID(*config.Overrides.AllowUnsupportedDevices)
|
displayMetadata, err := edidtools.FetchXRGlassEDID(*config.Overrides.AllowUnsupportedDevices)
|
||||||
|
|
||||||
|
@ -71,8 +87,8 @@ func mainEntrypoint(context.Context, *cli.Command) error {
|
||||||
return fmt.Errorf("failed to fetch EDID or get metadata: %w", err)
|
return fmt.Errorf("failed to fetch EDID or get metadata: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Info("Got EDID file and metadata")
|
log.Debug("Got EDID file and metadata")
|
||||||
log.Info("Patching EDID firmware to be specialized")
|
log.Debug("Patching EDID firmware to be specialized")
|
||||||
|
|
||||||
patchedFirmware, err := edidpatcher.PatchEDIDToBeSpecialized(displayMetadata.EDID)
|
patchedFirmware, err := edidpatcher.PatchEDIDToBeSpecialized(displayMetadata.EDID)
|
||||||
|
|
||||||
|
@ -87,7 +103,7 @@ func mainEntrypoint(context.Context, *cli.Command) error {
|
||||||
return fmt.Errorf("failed to upload patched EDID firmware: %w", err)
|
return fmt.Errorf("failed to upload patched EDID firmware: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
defer func() {
|
atexit.Register(func() {
|
||||||
err := edidtools.UnloadCustomEDIDFirmware(displayMetadata)
|
err := edidtools.UnloadCustomEDIDFirmware(displayMetadata)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -95,27 +111,59 @@ func mainEntrypoint(context.Context, *cli.Command) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Info("Please unplug and plug in your XR device to restore it back to normal settings.")
|
log.Info("Please unplug and plug in your XR device to restore it back to normal settings.")
|
||||||
}()
|
})
|
||||||
|
|
||||||
fmt.Print("Press the Enter key to continue loading after you unplug and plug in your XR device.")
|
fmt.Print("Press the Enter key to continue loading after you unplug and plug in your XR device.")
|
||||||
bufio.NewReader(os.Stdin).ReadBytes('\n') // Wait for Enter key press before continuing
|
bufio.NewReader(os.Stdin).ReadBytes('\n') // Wait for Enter key press before continuing
|
||||||
|
|
||||||
log.Info("Initializing XR headset")
|
log.Info("Initializing XR headset")
|
||||||
|
rl.SetTargetFPS(int32(displayMetadata.MaxRefreshRate * 2))
|
||||||
|
rl.InitWindow(int32(displayMetadata.MaxWidth), int32(displayMetadata.MaxHeight), "UnrealXR")
|
||||||
|
|
||||||
rl.InitWindow(800, 450, "raylib [core] example - basic window")
|
atexit.Register(func() {
|
||||||
defer rl.CloseWindow()
|
rl.CloseWindow()
|
||||||
|
})
|
||||||
|
|
||||||
rl.SetTargetFPS(60)
|
log.Info("Initializing virtual displays")
|
||||||
|
|
||||||
for !rl.WindowShouldClose() {
|
libevdi.SetupLogger(&libevdi.EvdiLogger{
|
||||||
rl.BeginDrawing()
|
Log: func(msg string) {
|
||||||
|
log.Debugf("EVDI: %s", msg)
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
rl.ClearBackground(rl.RayWhite)
|
displayMetadataBlock := make([]*renderer.EvdiDisplayMetadata, *config.DisplayConfig.Count)
|
||||||
rl.DrawText("Congrats! You created your first window!", 190, 200, 20, rl.LightGray)
|
|
||||||
|
|
||||||
rl.EndDrawing()
|
for currentDisplay := range *config.DisplayConfig.Count {
|
||||||
|
openedDevice, err := libevdi.Open(nil)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("Failed to open EVDI device: %s", err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
openedDevice.Connect(displayMetadata.EDID, uint(displayMetadata.MaxWidth), uint(displayMetadata.MaxHeight), uint(displayMetadata.MaxRefreshRate))
|
||||||
|
|
||||||
|
atexit.Register(func() {
|
||||||
|
openedDevice.Disconnect()
|
||||||
|
})
|
||||||
|
|
||||||
|
displayRect := &libevdi.EvdiDisplayRect{
|
||||||
|
X1: 0,
|
||||||
|
Y1: 0,
|
||||||
|
X2: displayMetadata.MaxWidth,
|
||||||
|
Y2: displayMetadata.MaxHeight,
|
||||||
|
}
|
||||||
|
|
||||||
|
displayBuffer := openedDevice.CreateBuffer(displayMetadata.MaxWidth, displayMetadata.MaxHeight, 4, displayRect)
|
||||||
|
|
||||||
|
displayMetadataBlock[currentDisplay] = &renderer.EvdiDisplayMetadata{
|
||||||
|
EvdiNode: openedDevice,
|
||||||
|
Rect: displayRect,
|
||||||
|
Buffer: displayBuffer,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
atexit.Exit(0)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
3
go.mod
3
go.mod
|
@ -4,7 +4,7 @@ go 1.24.3
|
||||||
|
|
||||||
require (
|
require (
|
||||||
git.terah.dev/UnrealXR/raylib-go/raylib v0.55.2-0.20250623002739-1468af2636e1 // indirect
|
git.terah.dev/UnrealXR/raylib-go/raylib v0.55.2-0.20250623002739-1468af2636e1 // indirect
|
||||||
git.terah.dev/imterah/goevdi v0.0.0-20250211014657-96d98ad0735c // indirect
|
git.terah.dev/imterah/goevdi v1.14.10 // indirect
|
||||||
github.com/anoopengineer/edidparser v0.0.0-20240602223913-86ca9ed3d2b0 // indirect
|
github.com/anoopengineer/edidparser v0.0.0-20240602223913-86ca9ed3d2b0 // indirect
|
||||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
|
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
|
||||||
github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc // indirect
|
github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc // indirect
|
||||||
|
@ -23,6 +23,7 @@ require (
|
||||||
github.com/mattn/go-runewidth v0.0.16 // indirect
|
github.com/mattn/go-runewidth v0.0.16 // indirect
|
||||||
github.com/muesli/termenv v0.16.0 // indirect
|
github.com/muesli/termenv v0.16.0 // indirect
|
||||||
github.com/rivo/uniseg v0.4.7 // indirect
|
github.com/rivo/uniseg v0.4.7 // indirect
|
||||||
|
github.com/tebeka/atexit v0.3.0 // indirect
|
||||||
github.com/urfave/cli/v3 v3.3.8 // indirect
|
github.com/urfave/cli/v3 v3.3.8 // indirect
|
||||||
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
|
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
|
||||||
golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b // indirect
|
golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b // indirect
|
||||||
|
|
10
go.sum
10
go.sum
|
@ -2,6 +2,8 @@ git.terah.dev/UnrealXR/raylib-go/raylib v0.55.2-0.20250623002739-1468af2636e1 h1
|
||||||
git.terah.dev/UnrealXR/raylib-go/raylib v0.55.2-0.20250623002739-1468af2636e1/go.mod h1:ZRirF2UuVWSbl2ux7oyHwXcinni9msejCvtIsXbT8yY=
|
git.terah.dev/UnrealXR/raylib-go/raylib v0.55.2-0.20250623002739-1468af2636e1/go.mod h1:ZRirF2UuVWSbl2ux7oyHwXcinni9msejCvtIsXbT8yY=
|
||||||
git.terah.dev/imterah/goevdi v0.0.0-20250211014657-96d98ad0735c h1:Ys33r6kjCyCs8N3ofSzCGxxL1gLIfetIiO1uL5UIsAM=
|
git.terah.dev/imterah/goevdi v0.0.0-20250211014657-96d98ad0735c h1:Ys33r6kjCyCs8N3ofSzCGxxL1gLIfetIiO1uL5UIsAM=
|
||||||
git.terah.dev/imterah/goevdi v0.0.0-20250211014657-96d98ad0735c/go.mod h1:RmxqlNaEJ+6qbHpyw6ivJhXlRYT1RcsZ9gzNOsFXfOA=
|
git.terah.dev/imterah/goevdi v0.0.0-20250211014657-96d98ad0735c/go.mod h1:RmxqlNaEJ+6qbHpyw6ivJhXlRYT1RcsZ9gzNOsFXfOA=
|
||||||
|
git.terah.dev/imterah/goevdi v1.14.10 h1:3zr3E/WRkSQ//+Gcrh0wfy0LVgm4Pcglc5K4MVcZ7n8=
|
||||||
|
git.terah.dev/imterah/goevdi v1.14.10/go.mod h1:z6GnBn2qHVV5N6fKZXPgUka8H9g5mZA5BRxCzUxLaNk=
|
||||||
github.com/anoopengineer/edidparser v0.0.0-20240602223913-86ca9ed3d2b0 h1:rTfysyBCL7LPbq9GFpQbllvKT8vEI93lQUwksMMxHMI=
|
github.com/anoopengineer/edidparser v0.0.0-20240602223913-86ca9ed3d2b0 h1:rTfysyBCL7LPbq9GFpQbllvKT8vEI93lQUwksMMxHMI=
|
||||||
github.com/anoopengineer/edidparser v0.0.0-20240602223913-86ca9ed3d2b0/go.mod h1:fEt61NePh3ZMxA+g3iC4CaGzY9lEsHRUkYJY2x0lBAw=
|
github.com/anoopengineer/edidparser v0.0.0-20240602223913-86ca9ed3d2b0/go.mod h1:fEt61NePh3ZMxA+g3iC4CaGzY9lEsHRUkYJY2x0lBAw=
|
||||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
|
github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
|
||||||
|
@ -18,6 +20,7 @@ github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd h1:vy0G
|
||||||
github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd/go.mod h1:xe0nKWGd3eJgtqZRaN9RjMtK7xUYchjzPr7q6kcvCCs=
|
github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd/go.mod h1:xe0nKWGd3eJgtqZRaN9RjMtK7xUYchjzPr7q6kcvCCs=
|
||||||
github.com/charmbracelet/x/term v0.2.1 h1:AQeHeLZ1OqSXhrAWpYUtZyX1T3zVxfpZuEQMIQaGIAQ=
|
github.com/charmbracelet/x/term v0.2.1 h1:AQeHeLZ1OqSXhrAWpYUtZyX1T3zVxfpZuEQMIQaGIAQ=
|
||||||
github.com/charmbracelet/x/term v0.2.1/go.mod h1:oQ4enTYFV7QN4m0i9mzHrViD7TQKvNEEkHUMCmsxdUg=
|
github.com/charmbracelet/x/term v0.2.1/go.mod h1:oQ4enTYFV7QN4m0i9mzHrViD7TQKvNEEkHUMCmsxdUg=
|
||||||
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/ebitengine/purego v0.8.4 h1:CF7LEKg5FFOsASUj0+QwaXf8Ht6TlFxg09+S9wz0omw=
|
github.com/ebitengine/purego v0.8.4 h1:CF7LEKg5FFOsASUj0+QwaXf8Ht6TlFxg09+S9wz0omw=
|
||||||
github.com/ebitengine/purego v0.8.4/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ=
|
github.com/ebitengine/purego v0.8.4/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ=
|
||||||
github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4=
|
github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4=
|
||||||
|
@ -36,9 +39,14 @@ github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6T
|
||||||
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||||
github.com/muesli/termenv v0.16.0 h1:S5AlUN9dENB57rsbnkPyfdGuWIlkmzJjbFf0Tf5FWUc=
|
github.com/muesli/termenv v0.16.0 h1:S5AlUN9dENB57rsbnkPyfdGuWIlkmzJjbFf0Tf5FWUc=
|
||||||
github.com/muesli/termenv v0.16.0/go.mod h1:ZRfOIKPFDYQoDFF4Olj7/QJbW60Ol/kL1pU3VfY/Cnk=
|
github.com/muesli/termenv v0.16.0/go.mod h1:ZRfOIKPFDYQoDFF4Olj7/QJbW60Ol/kL1pU3VfY/Cnk=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||||
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
|
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
|
||||||
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||||
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||||
|
github.com/tebeka/atexit v0.3.0 h1:jleL99H7Ywt80oJKR+VWmJNnezcCOG0CuzcN3CIpsdI=
|
||||||
|
github.com/tebeka/atexit v0.3.0/go.mod h1:WJmSUSmMT7WoR7etUOaGBVXk+f5/ZJ+67qwuedq7Fbs=
|
||||||
github.com/urfave/cli/v3 v3.3.8 h1:BzolUExliMdet9NlJ/u4m5vHSotJ3PzEqSAZ1oPMa/E=
|
github.com/urfave/cli/v3 v3.3.8 h1:BzolUExliMdet9NlJ/u4m5vHSotJ3PzEqSAZ1oPMa/E=
|
||||||
github.com/urfave/cli/v3 v3.3.8/go.mod h1:FJSKtM/9AiiTOJL4fJ6TbMUkxBXn7GO9guZqoZtpYpo=
|
github.com/urfave/cli/v3 v3.3.8/go.mod h1:FJSKtM/9AiiTOJL4fJ6TbMUkxBXn7GO9guZqoZtpYpo=
|
||||||
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no=
|
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no=
|
||||||
|
@ -52,3 +60,5 @@ golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
|
||||||
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
|
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
|
||||||
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue