mirror of
https://github.com/gnif/LookingGlass.git
synced 2026-07-18 05:12:03 +00:00
Compare commits
261 Commits
B7
...
gnif-hdr-e
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e8dcbddea0 | ||
|
|
1b3305e1dc | ||
|
|
ff1631da67 | ||
|
|
2f59de572b | ||
|
|
da7d1a2ead | ||
|
|
82d36a858f | ||
|
|
9047c26694 | ||
|
|
a32ba63c90 | ||
|
|
8301ec5ae5 | ||
|
|
9721fc8c7e | ||
|
|
364485ded8 | ||
|
|
28973ac4b1 | ||
|
|
0c653c1fb2 | ||
|
|
11b3ac00a8 | ||
|
|
bc96319b94 | ||
|
|
c9845d3453 | ||
|
|
1f3051e81a | ||
|
|
4bb2c58fb6 | ||
|
|
e203bca480 | ||
|
|
8d7b45e240 | ||
|
|
66d8a9691e | ||
|
|
89ddab9d57 | ||
|
|
ffffff0740 | ||
|
|
c8edf1eaf3 | ||
|
|
938a2a6c22 | ||
|
|
e406b0fee8 | ||
|
|
79784fa44d | ||
|
|
a164c02f9a | ||
|
|
3aa6492760 | ||
|
|
0664e510a2 | ||
|
|
e4e211f07a | ||
|
|
bff890f635 | ||
|
|
2317801411 | ||
|
|
140de3199b | ||
|
|
c8f4898815 | ||
|
|
462f638c12 | ||
|
|
37bb89f490 | ||
|
|
b3701992c1 | ||
|
|
7b2c60b267 | ||
|
|
708ed2cbae | ||
|
|
415a946e56 | ||
|
|
803aea0d21 | ||
|
|
cb70643fa4 | ||
|
|
e74f58afb4 | ||
|
|
29d02ddbb9 | ||
|
|
fec805fbe2 | ||
|
|
ebeb9d028e | ||
|
|
1a137f3c08 | ||
|
|
3ef8344e9f | ||
|
|
976be95177 | ||
|
|
1b7c00dc82 | ||
|
|
a59040f0be | ||
|
|
929428c273 | ||
|
|
bd88a64a98 | ||
|
|
882d531792 | ||
|
|
3211bc1d93 | ||
|
|
a10efc9e23 | ||
|
|
dbb80ebd66 | ||
|
|
65005c0dc0 | ||
|
|
c2add993ac | ||
|
|
83bebf4519 | ||
|
|
19f75dc045 | ||
|
|
fc6a728bb7 | ||
|
|
69f44a003d | ||
|
|
0743d49abe | ||
|
|
e9b7bdfea1 | ||
|
|
98602fb95e | ||
|
|
3c8f4eec90 | ||
|
|
8318046a29 | ||
|
|
01b8724cfe | ||
|
|
dba2d23eb2 | ||
|
|
7f31ecf5e5 | ||
|
|
b181859c1b | ||
|
|
53bfb6547f | ||
|
|
06c490ca72 | ||
|
|
c8de7b27fd | ||
|
|
0983e50f4d | ||
|
|
3efe47ffb2 | ||
|
|
4269b5598a | ||
|
|
af207a2fe1 | ||
|
|
3ed08ba56c | ||
|
|
70da98c1a1 | ||
|
|
ed1602fc74 | ||
|
|
f9ecddab98 | ||
|
|
fad7af7740 | ||
|
|
6c70e36cb1 | ||
|
|
dca54a79fd | ||
|
|
113199b6dd | ||
|
|
7d33b93a50 | ||
|
|
bf77128053 | ||
|
|
124b4742e0 | ||
|
|
569619384c | ||
|
|
1d7cb35de8 | ||
|
|
e082acbe44 | ||
|
|
ab6e2c89d5 | ||
|
|
7a3833782c | ||
|
|
96367e83f1 | ||
|
|
c99f516b29 | ||
|
|
2647678b0f | ||
|
|
40d606890b | ||
|
|
fddcb7f2d4 | ||
|
|
48ab317fa0 | ||
|
|
08e54fd1b1 | ||
|
|
b504627145 | ||
|
|
4585362f54 | ||
|
|
e123e02e15 | ||
|
|
85e728b59e | ||
|
|
042450a708 | ||
|
|
9009217366 | ||
|
|
d006dbb547 | ||
|
|
c4f3936d98 | ||
|
|
118e300f2f | ||
|
|
19989ce9fb | ||
|
|
e1a2fa790d | ||
|
|
daa78bcf47 | ||
|
|
e2bc1856b6 | ||
|
|
30869c1c9c | ||
|
|
9e8cb2f919 | ||
|
|
70e0c356fc | ||
|
|
8c3a2d01bc | ||
|
|
eff8555f9b | ||
|
|
c873aa4c4e | ||
|
|
5c1d604a22 | ||
|
|
67e1574d20 | ||
|
|
94550e09b4 | ||
|
|
9d48e70983 | ||
|
|
48dc7a90f9 | ||
|
|
4ff5ce02d7 | ||
|
|
b7e3ef6824 | ||
|
|
870eb8c670 | ||
|
|
d02d46283c | ||
|
|
d5ee54e23e | ||
|
|
41d3e7a981 | ||
|
|
e75c7cff46 | ||
|
|
e81462176a | ||
|
|
d00f12875c | ||
|
|
b6ceb72855 | ||
|
|
13ae3441cf | ||
|
|
b83d70a068 | ||
|
|
2d28d27e90 | ||
|
|
e6b3b7fa76 | ||
|
|
9220c85e85 | ||
|
|
2c370847e7 | ||
|
|
e1170f8e01 | ||
|
|
41d2210624 | ||
|
|
037a61a1c7 | ||
|
|
c6eda7e3a0 | ||
|
|
ff8650829c | ||
|
|
df6d22455e | ||
|
|
52849bc1d7 | ||
|
|
155540a8f7 | ||
|
|
6e00dedc2b | ||
|
|
3da40f046d | ||
|
|
e816847fb1 | ||
|
|
eec9aa3ae3 | ||
|
|
f07dd827ae | ||
|
|
08064efb7f | ||
|
|
01cae959d8 | ||
|
|
da154a5591 | ||
|
|
a85b666238 | ||
|
|
eff1e4d7ea | ||
|
|
4affd03c2d | ||
|
|
a1cc58c9f2 | ||
|
|
9a6e03114e | ||
|
|
0feaa716c5 | ||
|
|
5f9649b4a2 | ||
|
|
e40610ea77 | ||
|
|
d5839c7efd | ||
|
|
2a2250b9bd | ||
|
|
16a283717a | ||
|
|
5a4a2529af | ||
|
|
403bf87d6d | ||
|
|
e1a585ad6f | ||
|
|
7c2e0ec4e9 | ||
|
|
33600682cf | ||
|
|
60bda2befc | ||
|
|
04a55e1419 | ||
|
|
ca98b5b1fd | ||
|
|
c156044423 | ||
|
|
85ceae91bf | ||
|
|
f8f05c36b8 | ||
|
|
05bf816b45 | ||
|
|
3f35b0b0af | ||
|
|
f7e0b9746a | ||
|
|
b7d044de5d | ||
|
|
28b653b112 | ||
|
|
26848ba70a | ||
|
|
482f66ab9b | ||
|
|
8d9806bb0e | ||
|
|
fa661aed64 | ||
|
|
2c648b99ad | ||
|
|
6a6cfadbf2 | ||
|
|
11c86273d2 | ||
|
|
60d7c84972 | ||
|
|
cb304115f6 | ||
|
|
c349f704d6 | ||
|
|
add45347b5 | ||
|
|
f15d72cdfe | ||
|
|
54d811e098 | ||
|
|
9593301511 | ||
|
|
c2a19f5e76 | ||
|
|
d8baa62c6a | ||
|
|
81162b460e | ||
|
|
852eb6bf69 | ||
|
|
4b11743f18 | ||
|
|
656d01a694 | ||
|
|
a4406ac867 | ||
|
|
57a2f68931 | ||
|
|
f4df3f0ec7 | ||
|
|
4e951184f1 | ||
|
|
be4782b062 | ||
|
|
b17c66d6bb | ||
|
|
94fbbad21c | ||
|
|
63a9365377 | ||
|
|
cadcfe4b39 | ||
|
|
3b883bf9fe | ||
|
|
b58171c3e1 | ||
|
|
7afb9b93eb | ||
|
|
6396ff1e9c | ||
|
|
db1dda00c8 | ||
|
|
5b07286c65 | ||
|
|
6dad0de8b8 | ||
|
|
35c975d334 | ||
|
|
530e83e7bf | ||
|
|
40a4debfda | ||
|
|
75f07cb28c | ||
|
|
f26fa17bc1 | ||
|
|
648fca7caa | ||
|
|
868504d22d | ||
|
|
cb423730e4 | ||
|
|
86de1c9ac6 | ||
|
|
d839a45d0b | ||
|
|
9ffb800e93 | ||
|
|
91e8440c9d | ||
|
|
15eff234ec | ||
|
|
6a4edfc6b6 | ||
|
|
bf59e45118 | ||
|
|
9cc99e7db9 | ||
|
|
af5a48deca | ||
|
|
b1b6da32ce | ||
|
|
17b24cc8ff | ||
|
|
7248b666ea | ||
|
|
2084a9fee3 | ||
|
|
a2a771f94e | ||
|
|
b526eb3da0 | ||
|
|
7a88a49f1c | ||
|
|
ce23cff12e | ||
|
|
09df8c41aa | ||
|
|
0db9d3a27b | ||
|
|
4f2eb984d3 | ||
|
|
8b198091ce | ||
|
|
62c075cfb5 | ||
|
|
bea198735a | ||
|
|
a421329d9a | ||
|
|
5382a94945 | ||
|
|
4278a10fe1 | ||
|
|
35e6a6e81a | ||
|
|
afbd844be8 | ||
|
|
7c285a45fb | ||
|
|
968fd42d46 | ||
|
|
66ac453c98 |
@@ -1,3 +1,9 @@
|
|||||||
|
---
|
||||||
|
name: Bug report
|
||||||
|
about: Report bugs in Looking Glass (only confirmed bugs and feature requests please)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
### Issues are for Bug Reports and Feature Requests Only!
|
### Issues are for Bug Reports and Feature Requests Only!
|
||||||
|
|
||||||
If you are looking for help or support please use one of the following methods
|
If you are looking for help or support please use one of the following methods
|
||||||
@@ -64,3 +70,4 @@ https://www.youtube.com/watch?v=EqxxJK9Yo64
|
|||||||
```
|
```
|
||||||
PASTE FULL BACKTRACE HERE
|
PASTE FULL BACKTRACE HERE
|
||||||
```
|
```
|
||||||
|
|
||||||
9
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
9
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
blank_issues_enabled: false
|
||||||
|
contact_links:
|
||||||
|
- name: Looking Glass on Level1Tech's Forum
|
||||||
|
url: https://forum.level1techs.com/c/software/lookingGlass/142
|
||||||
|
about: Ask for help by creating a New Topic on the Level1Tech's forum
|
||||||
|
- name: Looking Glass Discord Server
|
||||||
|
url: https://discord.gg/52SMupxkvt
|
||||||
|
about: Ask for help in the Looking Glass discord server
|
||||||
|
|
||||||
54
.github/workflows/build.yml
vendored
54
.github/workflows/build.yml
vendored
@@ -120,11 +120,33 @@ jobs:
|
|||||||
makensis -DIVSHMEM platform/Windows/installer.nsi
|
makensis -DIVSHMEM platform/Windows/installer.nsi
|
||||||
|
|
||||||
host-windows-native:
|
host-windows-native:
|
||||||
runs-on: windows-latest
|
runs-on: windows-2025
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
|
- name: Install NSIS
|
||||||
|
shell: powershell
|
||||||
|
run: |
|
||||||
|
winget install -e --id NSIS.NSIS --silent --accept-source-agreements --accept-package-agreements
|
||||||
|
$paths = @(
|
||||||
|
(Join-Path ${env:ProgramFiles} 'NSIS\Bin'),
|
||||||
|
(Join-Path ${env:ProgramFiles(x86)} 'NSIS\Bin')
|
||||||
|
) | Where-Object { Test-Path $_ }
|
||||||
|
|
||||||
|
if ($paths.Count -eq 0) {
|
||||||
|
Write-Error "NSIS 'Bin' folder not found after install."
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
$paths | ForEach-Object {
|
||||||
|
Add-Content -Path $env:GITHUB_PATH -Value $_
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Host "makensis location(s): $($paths -join ', ')"
|
||||||
|
- name: Test NSIS
|
||||||
|
run: |
|
||||||
|
makensis /VERSION
|
||||||
- name: Configure Windows host for native MinGW-w64
|
- name: Configure Windows host for native MinGW-w64
|
||||||
run: |
|
run: |
|
||||||
mkdir host\build
|
mkdir host\build
|
||||||
@@ -139,6 +161,36 @@ jobs:
|
|||||||
cd host\build
|
cd host\build
|
||||||
makensis -DBUILD_32BIT platform\Windows\installer.nsi
|
makensis -DBUILD_32BIT platform\Windows\installer.nsi
|
||||||
|
|
||||||
|
idd:
|
||||||
|
runs-on: windows-2022
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
with:
|
||||||
|
submodules: recursive
|
||||||
|
- name: Add msbuild to PATH
|
||||||
|
uses: microsoft/setup-msbuild@v2
|
||||||
|
with:
|
||||||
|
msbuild-architecture: x64
|
||||||
|
- name: Install NuGet packages
|
||||||
|
run: |
|
||||||
|
cd idd
|
||||||
|
nuget restore LGIdd.sln
|
||||||
|
- name: Build IDD
|
||||||
|
run: |
|
||||||
|
cd idd
|
||||||
|
msbuild.exe LGIdd.sln /t:Build /p:Configuration=Release /p:Platform=x64
|
||||||
|
- name: Build NSIS Installer
|
||||||
|
run: |
|
||||||
|
cd idd\x64\Release\LGIdd
|
||||||
|
makensis -DBUILD_32BIT installer.nsi
|
||||||
|
- name: Build NSIS installer with IVSHMEM drivers
|
||||||
|
run: |
|
||||||
|
cd idd\x64\Release
|
||||||
|
Invoke-WebRequest https://dl.quantum2.xyz/ivshmem.tar.gz -OutFile ivshmem.tar.gz
|
||||||
|
tar -xzvf ivshmem.tar.gz
|
||||||
|
cd LGIdd
|
||||||
|
makensis -DBUILD_32BIT -DIVSHMEM installer.nsi
|
||||||
|
|
||||||
obs:
|
obs:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
strategy:
|
strategy:
|
||||||
|
|||||||
8
.gitignore
vendored
8
.gitignore
vendored
@@ -11,7 +11,11 @@ module/modules.order
|
|||||||
__pycache__
|
__pycache__
|
||||||
*.py[co]
|
*.py[co]
|
||||||
*/.vs
|
*/.vs
|
||||||
|
*.user
|
||||||
idd/Debug
|
idd/Debug
|
||||||
idd/x64
|
idd/x64
|
||||||
idd/LGIdd/x64
|
idd/*/x64
|
||||||
idd/LGIdd/Debug
|
idd/*/Debug
|
||||||
|
idd/*/VersionInfo.h
|
||||||
|
idd/*/VERSION
|
||||||
|
idd/packages
|
||||||
|
|||||||
2
.gitmodules
vendored
2
.gitmodules
vendored
@@ -9,7 +9,7 @@
|
|||||||
url = https://github.com/cimgui/cimgui.git
|
url = https://github.com/cimgui/cimgui.git
|
||||||
[submodule "repos/wayland-protocols"]
|
[submodule "repos/wayland-protocols"]
|
||||||
path = repos/wayland-protocols
|
path = repos/wayland-protocols
|
||||||
url = https://gitlab.freedesktop.org/wayland/wayland-protocols.git
|
url = https://github.com/quantum5/wayland-protocols.git
|
||||||
[submodule "repos/nanosvg"]
|
[submodule "repos/nanosvg"]
|
||||||
path = repos/nanosvg
|
path = repos/nanosvg
|
||||||
url = https://github.com/memononen/nanosvg.git
|
url = https://github.com/memononen/nanosvg.git
|
||||||
|
|||||||
34
.woodpecker/idd.yaml
Normal file
34
.woodpecker/idd.yaml
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
---
|
||||||
|
labels:
|
||||||
|
platform: windows/amd64
|
||||||
|
|
||||||
|
matrix:
|
||||||
|
BUILD_TYPE:
|
||||||
|
- Debug
|
||||||
|
- Release
|
||||||
|
|
||||||
|
when:
|
||||||
|
- event: push
|
||||||
|
branch: master
|
||||||
|
repo: gnif/LookingGlass
|
||||||
|
|
||||||
|
clone:
|
||||||
|
- name: clone
|
||||||
|
image: woodpeckerci/plugin-git
|
||||||
|
pull: false
|
||||||
|
settings:
|
||||||
|
tags: true
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: idd
|
||||||
|
image: lg-vs2022:latest
|
||||||
|
pull: true
|
||||||
|
environment:
|
||||||
|
VS_PATH: "\"C:\\\\Program Files (x86)\\\\Microsoft Visual Studio\\\\2022\\\\\""
|
||||||
|
entrypoint:
|
||||||
|
- cmd
|
||||||
|
- /C
|
||||||
|
- >
|
||||||
|
%VS_PATH%\BuildTools\Common7\Tools\VsDevCmd.bat -arch=amd64 &&
|
||||||
|
msbuild /restore idd\LGIdd.sln /p:Configuration=${BUILD_TYPE} /p:RestorePackagesConfig=true /p:Platform=x64 /p:SignMode=Off /m &&
|
||||||
|
IF EXIST C:\artifacts\build.cmd (cmd /C C:\artifacts\build.cmd)
|
||||||
3
AUTHORS
3
AUTHORS
@@ -72,3 +72,6 @@ Jacob McNamee <jacob@jacobmcnamee.com> (jacobmcnamee)
|
|||||||
Marco Antonio J. Costa <marco.antonio.costa@gmail.com> (majcosta)
|
Marco Antonio J. Costa <marco.antonio.costa@gmail.com> (majcosta)
|
||||||
rs189 <35667100+rs189@users.noreply.github.com> (rs189)
|
rs189 <35667100+rs189@users.noreply.github.com> (rs189)
|
||||||
Jérôme Poulin <jeromepoulin@gmail.com> (ticpu)
|
Jérôme Poulin <jeromepoulin@gmail.com> (ticpu)
|
||||||
|
Marco Rodolfi <marco.rodolfi@tuta.io> (RodoMa92)
|
||||||
|
Stewart Borle <stewi1014@gmail.com> (stewi1014)
|
||||||
|
Jannis Lübke <business.janrupf@gmail.com> (Janrupf)
|
||||||
|
|||||||
@@ -113,6 +113,7 @@ set(SOURCES
|
|||||||
src/main.c
|
src/main.c
|
||||||
src/core.c
|
src/core.c
|
||||||
src/app.c
|
src/app.c
|
||||||
|
src/message.c
|
||||||
src/audio.c
|
src/audio.c
|
||||||
src/config.c
|
src/config.c
|
||||||
src/keybind.c
|
src/keybind.c
|
||||||
@@ -124,6 +125,7 @@ set(SOURCES
|
|||||||
src/eglutil.c
|
src/eglutil.c
|
||||||
src/overlay_utils.c
|
src/overlay_utils.c
|
||||||
src/render_queue.c
|
src/render_queue.c
|
||||||
|
src/evdev.c
|
||||||
|
|
||||||
src/overlay/splash.c
|
src/overlay/splash.c
|
||||||
src/overlay/alert.c
|
src/overlay/alert.c
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Looking Glass
|
* Looking Glass
|
||||||
* Copyright © 2017-2025 The Looking Glass Authors
|
* Copyright © 2017-2026 The Looking Glass Authors
|
||||||
* https://looking-glass.io
|
* https://looking-glass.io
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
@@ -168,6 +168,12 @@ static bool pipewire_init(void)
|
|||||||
pw_init(NULL, NULL);
|
pw_init(NULL, NULL);
|
||||||
|
|
||||||
pw.loop = pw_loop_new(NULL);
|
pw.loop = pw_loop_new(NULL);
|
||||||
|
#if PW_CHECK_VERSION(1, 3, 81)
|
||||||
|
pw.context = pw_context_new(
|
||||||
|
pw.loop,
|
||||||
|
NULL,
|
||||||
|
0);
|
||||||
|
#else
|
||||||
pw.context = pw_context_new(
|
pw.context = pw_context_new(
|
||||||
pw.loop,
|
pw.loop,
|
||||||
pw_properties_new(
|
pw_properties_new(
|
||||||
@@ -176,6 +182,7 @@ static bool pipewire_init(void)
|
|||||||
NULL
|
NULL
|
||||||
),
|
),
|
||||||
0);
|
0);
|
||||||
|
#endif
|
||||||
if (!pw.context)
|
if (!pw.context)
|
||||||
{
|
{
|
||||||
DEBUG_ERROR("Failed to create a context");
|
DEBUG_ERROR("Failed to create a context");
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Looking Glass
|
* Looking Glass
|
||||||
* Copyright © 2017-2025 The Looking Glass Authors
|
* Copyright © 2017-2026 The Looking Glass Authors
|
||||||
* https://looking-glass.io
|
* https://looking-glass.io
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ find_program(WAYLAND_SCANNER_EXECUTABLE NAMES wayland-scanner)
|
|||||||
add_library(displayserver_Wayland STATIC
|
add_library(displayserver_Wayland STATIC
|
||||||
activation.c
|
activation.c
|
||||||
clipboard.c
|
clipboard.c
|
||||||
|
colormgmt.c
|
||||||
cursor.c
|
cursor.c
|
||||||
gl.c
|
gl.c
|
||||||
idle.c
|
idle.c
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Looking Glass
|
* Looking Glass
|
||||||
* Copyright © 2017-2025 The Looking Glass Authors
|
* Copyright © 2017-2026 The Looking Glass Authors
|
||||||
* https://looking-glass.io
|
* https://looking-glass.io
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Looking Glass
|
* Looking Glass
|
||||||
* Copyright © 2017-2025 The Looking Glass Authors
|
* Copyright © 2017-2026 The Looking Glass Authors
|
||||||
* https://looking-glass.io
|
* https://looking-glass.io
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
|||||||
110
client/displayservers/Wayland/colormgmt.c
Normal file
110
client/displayservers/Wayland/colormgmt.c
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
/**
|
||||||
|
* Looking Glass
|
||||||
|
* Copyright (C) 2017-2026 The Looking Glass Authors
|
||||||
|
* https://looking-glass.io
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the Free
|
||||||
|
* Software Foundation; either version 2 of the License, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc., 59
|
||||||
|
* Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "wayland.h"
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#include <wayland-client.h>
|
||||||
|
|
||||||
|
#include "common/debug.h"
|
||||||
|
|
||||||
|
static void cmIntent(void * data, struct wp_color_manager_v1 * cm, uint32_t intent)
|
||||||
|
{
|
||||||
|
if (intent == WP_COLOR_MANAGER_V1_RENDER_INTENT_PERCEPTUAL)
|
||||||
|
wlWm.cmHasPerceptualIntent = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cmFeature(void * data, struct wp_color_manager_v1 * cm, uint32_t feature)
|
||||||
|
{
|
||||||
|
switch (feature)
|
||||||
|
{
|
||||||
|
case WP_COLOR_MANAGER_V1_FEATURE_PARAMETRIC:
|
||||||
|
wlWm.cmHasParametric = true;
|
||||||
|
break;
|
||||||
|
case WP_COLOR_MANAGER_V1_FEATURE_SET_LUMINANCES:
|
||||||
|
wlWm.cmHasLuminances = true;
|
||||||
|
break;
|
||||||
|
case WP_COLOR_MANAGER_V1_FEATURE_SET_MASTERING_DISPLAY_PRIMARIES:
|
||||||
|
wlWm.cmHasMasteringPrimaries = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cmTFNamed(void * data, struct wp_color_manager_v1 * cm, uint32_t tf)
|
||||||
|
{
|
||||||
|
if (tf == WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_ST2084_PQ)
|
||||||
|
wlWm.cmHasTFSt2084PQ = true;
|
||||||
|
else if (tf == WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_EXT_LINEAR)
|
||||||
|
wlWm.cmHasTFExtLinear = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cmPrimariesNamed(void * data, struct wp_color_manager_v1 * cm,
|
||||||
|
uint32_t primaries)
|
||||||
|
{
|
||||||
|
if (primaries == WP_COLOR_MANAGER_V1_PRIMARIES_BT2020)
|
||||||
|
wlWm.cmHasPrimariesBT2020 = true;
|
||||||
|
else if (primaries == WP_COLOR_MANAGER_V1_PRIMARIES_SRGB)
|
||||||
|
wlWm.cmHasPrimariesSRGB = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cmDone(void * data, struct wp_color_manager_v1 * cm)
|
||||||
|
{
|
||||||
|
wlWm.cmFeaturesDone = true;
|
||||||
|
wlWm.cmCanDoHDR = wlWm.cmHasParametric &&
|
||||||
|
((wlWm.cmHasTFSt2084PQ && wlWm.cmHasPrimariesBT2020) ||
|
||||||
|
(wlWm.cmHasTFExtLinear && wlWm.cmHasPrimariesSRGB));
|
||||||
|
DEBUG_INFO("Color management features: parametric:%d luminances:%d "
|
||||||
|
"mastering_primaries:%d st2084_pq:%d ext_linear:%d bt2020:%d srgb:%d "
|
||||||
|
"can_do_hdr:%d",
|
||||||
|
wlWm.cmHasParametric, wlWm.cmHasLuminances,
|
||||||
|
wlWm.cmHasMasteringPrimaries,
|
||||||
|
wlWm.cmHasTFSt2084PQ, wlWm.cmHasTFExtLinear,
|
||||||
|
wlWm.cmHasPrimariesBT2020, wlWm.cmHasPrimariesSRGB,
|
||||||
|
wlWm.cmCanDoHDR);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct wp_color_manager_v1_listener cmListener = {
|
||||||
|
.supported_intent = cmIntent,
|
||||||
|
.supported_feature = cmFeature,
|
||||||
|
.supported_tf_named = cmTFNamed,
|
||||||
|
.supported_primaries_named = cmPrimariesNamed,
|
||||||
|
.done = cmDone,
|
||||||
|
};
|
||||||
|
|
||||||
|
bool waylandColorMgmtInit(void)
|
||||||
|
{
|
||||||
|
if (!wlWm.colorManager)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
wp_color_manager_v1_add_listener(wlWm.colorManager, &cmListener, NULL);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void waylandColorMgmtFree(void)
|
||||||
|
{
|
||||||
|
if (!wlWm.colorManager)
|
||||||
|
return;
|
||||||
|
|
||||||
|
wp_color_manager_v1_destroy(wlWm.colorManager);
|
||||||
|
wlWm.colorManager = NULL;
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Looking Glass
|
* Looking Glass
|
||||||
* Copyright © 2017-2025 The Looking Glass Authors
|
* Copyright © 2017-2026 The Looking Glass Authors
|
||||||
* https://looking-glass.io
|
* https://looking-glass.io
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
@@ -183,7 +183,7 @@ void waylandCursorFree(void)
|
|||||||
|
|
||||||
void waylandCursorScaleChange(void)
|
void waylandCursorScaleChange(void)
|
||||||
{
|
{
|
||||||
int newScale = ceil(wl_fixed_to_double(wlWm.scale));
|
int newScale = waylandScaleCeil(wlWm.scale);
|
||||||
if (newScale == wlWm.cursorScale)
|
if (newScale == wlWm.cursorScale)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Looking Glass
|
* Looking Glass
|
||||||
* Copyright © 2017-2025 The Looking Glass Authors
|
* Copyright © 2017-2026 The Looking Glass Authors
|
||||||
* https://looking-glass.io
|
* https://looking-glass.io
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
@@ -46,6 +46,7 @@ typedef struct LibDecorState
|
|||||||
int32_t width, height;
|
int32_t width, height;
|
||||||
bool needsResize;
|
bool needsResize;
|
||||||
bool fullscreen;
|
bool fullscreen;
|
||||||
|
bool borderless;
|
||||||
uint32_t resizeSerial;
|
uint32_t resizeSerial;
|
||||||
}
|
}
|
||||||
LibDecorState;
|
LibDecorState;
|
||||||
@@ -147,6 +148,10 @@ static bool libdecor_shellInit(
|
|||||||
if (maximize)
|
if (maximize)
|
||||||
libdecor_frame_set_maximized(state.libdecorFrame);
|
libdecor_frame_set_maximized(state.libdecorFrame);
|
||||||
|
|
||||||
|
if (borderless)
|
||||||
|
libdecor_frame_set_visibility(state.libdecorFrame, false);
|
||||||
|
state.borderless = borderless;
|
||||||
|
|
||||||
if (resizable)
|
if (resizable)
|
||||||
libdecor_frame_set_capabilities(state.libdecorFrame,
|
libdecor_frame_set_capabilities(state.libdecorFrame,
|
||||||
LIBDECOR_ACTION_RESIZE);
|
LIBDECOR_ACTION_RESIZE);
|
||||||
@@ -183,6 +188,7 @@ static void libdecor_setFullscreen(bool fs)
|
|||||||
else
|
else
|
||||||
libdecor_frame_unset_fullscreen(state.libdecorFrame);
|
libdecor_frame_unset_fullscreen(state.libdecorFrame);
|
||||||
|
|
||||||
|
if (!state.borderless)
|
||||||
libdecor_frame_set_visibility(state.libdecorFrame, !fs);
|
libdecor_frame_set_visibility(state.libdecorFrame, !fs);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -257,6 +263,11 @@ void libdecor_pollWait(struct wl_display * display, int epollFd,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool libdecor_configured(void)
|
||||||
|
{
|
||||||
|
return state.configured;
|
||||||
|
}
|
||||||
|
|
||||||
WL_DesktopOps WLD_libdecor =
|
WL_DesktopOps WLD_libdecor =
|
||||||
{
|
{
|
||||||
.name = "libdecor",
|
.name = "libdecor",
|
||||||
@@ -271,5 +282,6 @@ WL_DesktopOps WLD_libdecor =
|
|||||||
.getSize = libdecor_getSize,
|
.getSize = libdecor_getSize,
|
||||||
.registryGlobalHandler = libdecor_registryGlobalHandler,
|
.registryGlobalHandler = libdecor_registryGlobalHandler,
|
||||||
.pollInit = libdecor_pollInit,
|
.pollInit = libdecor_pollInit,
|
||||||
.pollWait = libdecor_pollWait
|
.pollWait = libdecor_pollWait,
|
||||||
|
.configured = libdecor_configured
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Looking Glass
|
* Looking Glass
|
||||||
* Copyright © 2017-2025 The Looking Glass Authors
|
* Copyright © 2017-2026 The Looking Glass Authors
|
||||||
* https://looking-glass.io
|
* https://looking-glass.io
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
@@ -49,6 +49,7 @@ typedef struct XDGState
|
|||||||
uint32_t resizeSerial;
|
uint32_t resizeSerial;
|
||||||
bool fullscreen;
|
bool fullscreen;
|
||||||
bool floating;
|
bool floating;
|
||||||
|
bool resizable;
|
||||||
int displayFd;
|
int displayFd;
|
||||||
}
|
}
|
||||||
XDGState;
|
XDGState;
|
||||||
@@ -155,6 +156,13 @@ bool xdg_shellInit(struct wl_display * display, struct wl_surface * surface,
|
|||||||
if (maximize)
|
if (maximize)
|
||||||
xdg_toplevel_set_maximized(state.toplevel);
|
xdg_toplevel_set_maximized(state.toplevel);
|
||||||
|
|
||||||
|
if (!resizable)
|
||||||
|
{
|
||||||
|
xdg_toplevel_set_min_size(state.toplevel, state.width, state.height);
|
||||||
|
xdg_toplevel_set_max_size(state.toplevel, state.width, state.height);
|
||||||
|
}
|
||||||
|
state.resizable = resizable;
|
||||||
|
|
||||||
if (state.decorationManager)
|
if (state.decorationManager)
|
||||||
{
|
{
|
||||||
state.toplevelDecoration = zxdg_decoration_manager_v1_get_toplevel_decoration(
|
state.toplevelDecoration = zxdg_decoration_manager_v1_get_toplevel_decoration(
|
||||||
@@ -200,7 +208,7 @@ static void xdg_minimize(void)
|
|||||||
|
|
||||||
static void xdg_shellResize(int w, int h)
|
static void xdg_shellResize(int w, int h)
|
||||||
{
|
{
|
||||||
if (!state.floating)
|
if (!state.floating || !state.resizable)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
state.width = w;
|
state.width = w;
|
||||||
@@ -296,6 +304,11 @@ void xdg_pollWait(struct wl_display * display, int epollFd,
|
|||||||
wl_display_cancel_read(display);
|
wl_display_cancel_read(display);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool xdg_configured(void)
|
||||||
|
{
|
||||||
|
return state.configured;
|
||||||
|
}
|
||||||
|
|
||||||
WL_DesktopOps WLD_xdg =
|
WL_DesktopOps WLD_xdg =
|
||||||
{
|
{
|
||||||
.name = "xdg",
|
.name = "xdg",
|
||||||
@@ -310,5 +323,6 @@ WL_DesktopOps WLD_xdg =
|
|||||||
.getSize = xdg_getSize,
|
.getSize = xdg_getSize,
|
||||||
.registryGlobalHandler = xdg_registryGlobalHandler,
|
.registryGlobalHandler = xdg_registryGlobalHandler,
|
||||||
.pollInit = xdg_pollInit,
|
.pollInit = xdg_pollInit,
|
||||||
.pollWait = xdg_pollWait
|
.pollWait = xdg_pollWait,
|
||||||
|
.configured = xdg_configured
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Looking Glass
|
* Looking Glass
|
||||||
* Copyright © 2017-2025 The Looking Glass Authors
|
* Copyright © 2017-2026 The Looking Glass Authors
|
||||||
* https://looking-glass.io
|
* https://looking-glass.io
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
@@ -70,6 +70,52 @@ EGLDisplay waylandGetEGLDisplay(void)
|
|||||||
return eglGetDisplay(native);
|
return eglGetDisplay(native);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void applyHDRPending(void)
|
||||||
|
{
|
||||||
|
if (wlWm.pendingHDRApply)
|
||||||
|
{
|
||||||
|
wlWm.pendingHDRApply = false;
|
||||||
|
atomic_thread_fence(memory_order_acquire);
|
||||||
|
waylandSetHDRImageDescription(
|
||||||
|
wlWm.pendingHDRDisplayPrimary, wlWm.pendingHDRWhitePoint,
|
||||||
|
wlWm.pendingHDRMaxDisplayLuminance,
|
||||||
|
wlWm.pendingHDRMinDisplayLuminance,
|
||||||
|
wlWm.pendingHDRMaxCLL,
|
||||||
|
wlWm.pendingHDRMaxFALL,
|
||||||
|
wlWm.pendingHDRPQ);
|
||||||
|
}
|
||||||
|
else if (wlWm.pendingHDRClear)
|
||||||
|
{
|
||||||
|
wlWm.pendingHDRClear = false;
|
||||||
|
waylandClearHDRImageDescription();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void waylandClearHDRImageDescription(void)
|
||||||
|
{
|
||||||
|
if (!wlWm.hdrActive)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (wlWm.hdrImageCreator)
|
||||||
|
{
|
||||||
|
wp_image_description_creator_params_v1_destroy(wlWm.hdrImageCreator);
|
||||||
|
wlWm.hdrImageCreator = NULL;
|
||||||
|
}
|
||||||
|
if (wlWm.hdrImageDesc)
|
||||||
|
{
|
||||||
|
wp_image_description_v1_destroy(wlWm.hdrImageDesc);
|
||||||
|
wlWm.hdrImageDesc = NULL;
|
||||||
|
}
|
||||||
|
if (wlWm.colorSurface)
|
||||||
|
{
|
||||||
|
wp_color_management_surface_v1_destroy(wlWm.colorSurface);
|
||||||
|
wlWm.colorSurface = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
wlWm.hdrActive = false;
|
||||||
|
DEBUG_INFO("HDR image description cleared");
|
||||||
|
}
|
||||||
|
|
||||||
void waylandEGLSwapBuffers(EGLDisplay display, EGLSurface surface, const struct Rect * damage, int count)
|
void waylandEGLSwapBuffers(EGLDisplay display, EGLSurface surface, const struct Rect * damage, int count)
|
||||||
{
|
{
|
||||||
if (!wlWm.swapWithDamage.init)
|
if (!wlWm.swapWithDamage.init)
|
||||||
@@ -84,6 +130,7 @@ void waylandEGLSwapBuffers(EGLDisplay display, EGLSurface surface, const struct
|
|||||||
}
|
}
|
||||||
|
|
||||||
waylandPresentationFrame();
|
waylandPresentationFrame();
|
||||||
|
applyHDRPending();
|
||||||
swapWithDamage(&wlWm.swapWithDamage, display, surface, damage, count);
|
swapWithDamage(&wlWm.swapWithDamage, display, surface, damage, count);
|
||||||
|
|
||||||
if (wlWm.needsResize)
|
if (wlWm.needsResize)
|
||||||
@@ -92,8 +139,8 @@ void waylandEGLSwapBuffers(EGLDisplay display, EGLSurface surface, const struct
|
|||||||
|
|
||||||
int width, height;
|
int width, height;
|
||||||
wlWm.desktop->getSize(&width, &height);
|
wlWm.desktop->getSize(&width, &height);
|
||||||
wl_egl_window_resize(wlWm.eglWindow, wl_fixed_to_int(width * wlWm.scale),
|
wl_egl_window_resize(wlWm.eglWindow, waylandScaleMulInt(wlWm.scale, width),
|
||||||
wl_fixed_to_int(height * wlWm.scale), 0, 0);
|
waylandScaleMulInt(wlWm.scale, height), 0, 0);
|
||||||
|
|
||||||
if (width == 0 || height == 0)
|
if (width == 0 || height == 0)
|
||||||
skipResize = true;
|
skipResize = true;
|
||||||
@@ -123,7 +170,7 @@ void waylandEGLSwapBuffers(EGLDisplay display, EGLSurface surface, const struct
|
|||||||
wp_viewport_destroy(wlWm.viewport);
|
wp_viewport_destroy(wlWm.viewport);
|
||||||
wlWm.viewport = NULL;
|
wlWm.viewport = NULL;
|
||||||
}
|
}
|
||||||
wl_surface_set_buffer_scale(wlWm.surface, wl_fixed_to_int(wlWm.scale));
|
wl_surface_set_buffer_scale(wlWm.surface, waylandScaleFloor(wlWm.scale));
|
||||||
}
|
}
|
||||||
|
|
||||||
struct wl_region * region = wl_compositor_create_region(wlWm.compositor);
|
struct wl_region * region = wl_compositor_create_region(wlWm.compositor);
|
||||||
@@ -131,7 +178,7 @@ void waylandEGLSwapBuffers(EGLDisplay display, EGLSurface surface, const struct
|
|||||||
wl_surface_set_opaque_region(wlWm.surface, region);
|
wl_surface_set_opaque_region(wlWm.surface, region);
|
||||||
wl_region_destroy(region);
|
wl_region_destroy(region);
|
||||||
|
|
||||||
app_handleResizeEvent(width, height, wl_fixed_to_double(wlWm.scale),
|
app_handleResizeEvent(width, height, waylandScaleToDouble(wlWm.scale),
|
||||||
(struct Border) {0, 0, 0, 0});
|
(struct Border) {0, 0, 0, 0});
|
||||||
app_invalidateWindow(true);
|
app_invalidateWindow(true);
|
||||||
waylandStopWaitFrame();
|
waylandStopWaitFrame();
|
||||||
@@ -149,23 +196,239 @@ EGLNativeWindowType waylandGetEGLNativeWindow(void)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// HDR color management support
|
||||||
|
void waylandSetHDRImageDescription(const uint16_t displayPrimary[3][2],
|
||||||
|
const uint16_t whitePoint[2], uint32_t maxDisplayLuminance,
|
||||||
|
uint32_t minDisplayLuminance, uint32_t maxCLL, uint32_t maxFALL,
|
||||||
|
bool hdrPQ)
|
||||||
|
{
|
||||||
|
if (!wlWm.colorManager)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!wlWm.cmFeaturesDone)
|
||||||
|
{
|
||||||
|
DEBUG_WARN("Color management features not yet advertised, deferring HDR");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!wlWm.cmHasParametric)
|
||||||
|
{
|
||||||
|
DEBUG_WARN("Compositor does not support parametric image descriptions");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify the compositor supports the transfer function we need
|
||||||
|
if (hdrPQ && !wlWm.cmHasTFSt2084PQ)
|
||||||
|
{
|
||||||
|
DEBUG_WARN("Compositor does not support ST2084_PQ transfer function");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!hdrPQ && !wlWm.cmHasTFExtLinear)
|
||||||
|
{
|
||||||
|
DEBUG_WARN("Compositor does not support EXT_LINEAR transfer function");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify primaries support for the target color space
|
||||||
|
if (hdrPQ && !wlWm.cmHasPrimariesBT2020)
|
||||||
|
{
|
||||||
|
DEBUG_WARN("Compositor does not support BT.2020 primaries");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!hdrPQ && !wlWm.cmHasPrimariesSRGB)
|
||||||
|
{
|
||||||
|
DEBUG_WARN("Compositor does not support sRGB primaries");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clean up any previous description (allows re-application with updated metadata)
|
||||||
|
if (wlWm.hdrImageCreator)
|
||||||
|
{
|
||||||
|
wp_image_description_creator_params_v1_destroy(wlWm.hdrImageCreator);
|
||||||
|
wlWm.hdrImageCreator = NULL;
|
||||||
|
}
|
||||||
|
if (wlWm.hdrImageDesc)
|
||||||
|
{
|
||||||
|
wp_image_description_v1_destroy(wlWm.hdrImageDesc);
|
||||||
|
wlWm.hdrImageDesc = NULL;
|
||||||
|
}
|
||||||
|
if (wlWm.colorSurface)
|
||||||
|
{
|
||||||
|
wp_color_management_surface_v1_destroy(wlWm.colorSurface);
|
||||||
|
wlWm.colorSurface = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
wlWm.hdrActive = false;
|
||||||
|
|
||||||
|
wlWm.hdrImageCreator =
|
||||||
|
wp_color_manager_v1_create_parametric_creator(wlWm.colorManager);
|
||||||
|
if (!wlWm.hdrImageCreator)
|
||||||
|
{
|
||||||
|
DEBUG_WARN("Failed to create parametric image description creator");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set primaries: BT.2020 for PQ HDR10, sRGB for scRGB/FP16
|
||||||
|
wp_image_description_creator_params_v1_set_primaries_named(
|
||||||
|
wlWm.hdrImageCreator,
|
||||||
|
hdrPQ ? WP_COLOR_MANAGER_V1_PRIMARIES_BT2020
|
||||||
|
: WP_COLOR_MANAGER_V1_PRIMARIES_SRGB);
|
||||||
|
|
||||||
|
// Select transfer function: PQ for PQ-encoded content, linear for scRGB/FP16
|
||||||
|
wp_image_description_creator_params_v1_set_tf_named(
|
||||||
|
wlWm.hdrImageCreator,
|
||||||
|
hdrPQ ? WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_ST2084_PQ
|
||||||
|
: WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_EXT_LINEAR);
|
||||||
|
|
||||||
|
// Set luminance range from metadata.
|
||||||
|
// min_lum is in 0.0001 cd/m² units (multiplied by 10000 as per protocol).
|
||||||
|
// max_lum and reference_lum are in unscaled cd/m² units.
|
||||||
|
if (wlWm.cmHasLuminances)
|
||||||
|
wp_image_description_creator_params_v1_set_luminances(
|
||||||
|
wlWm.hdrImageCreator,
|
||||||
|
minDisplayLuminance > 0 ? minDisplayLuminance : 50,
|
||||||
|
maxDisplayLuminance > 0 ? maxDisplayLuminance / 10000 : 1000,
|
||||||
|
hdrPQ ? 203 : 80);
|
||||||
|
|
||||||
|
// Set mastering display primaries from frame HDR metadata.
|
||||||
|
// Always set when the compositor supports it, falling back to the
|
||||||
|
// primaries from the metadata (even if zero, in which case the
|
||||||
|
// compositor uses its own defaults).
|
||||||
|
if (wlWm.cmHasMasteringPrimaries)
|
||||||
|
{
|
||||||
|
wp_image_description_creator_params_v1_set_mastering_display_primaries(
|
||||||
|
wlWm.hdrImageCreator,
|
||||||
|
displayPrimary[0][0], displayPrimary[0][1],
|
||||||
|
displayPrimary[1][0], displayPrimary[1][1],
|
||||||
|
displayPrimary[2][0], displayPrimary[2][1],
|
||||||
|
whitePoint[0], whitePoint[1]);
|
||||||
|
|
||||||
|
// Set mastering luminance range so the compositor knows the target
|
||||||
|
// color volume for tone mapping. min_lum is in ×10000 units (0.0001 cd/m²),
|
||||||
|
// max_lum is in unscaled cd/m².
|
||||||
|
wp_image_description_creator_params_v1_set_mastering_luminance(
|
||||||
|
wlWm.hdrImageCreator,
|
||||||
|
minDisplayLuminance > 0 ? minDisplayLuminance : 50,
|
||||||
|
maxDisplayLuminance > 0 ? maxDisplayLuminance / 10000 : 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (maxCLL > 0)
|
||||||
|
wp_image_description_creator_params_v1_set_max_cll(wlWm.hdrImageCreator, maxCLL);
|
||||||
|
if (maxFALL > 0)
|
||||||
|
wp_image_description_creator_params_v1_set_max_fall(wlWm.hdrImageCreator, maxFALL);
|
||||||
|
|
||||||
|
wlWm.hdrImageDesc =
|
||||||
|
wp_image_description_creator_params_v1_create(wlWm.hdrImageCreator);
|
||||||
|
wlWm.hdrImageCreator = NULL; // consumed by create
|
||||||
|
|
||||||
|
if (!wlWm.hdrImageDesc)
|
||||||
|
{
|
||||||
|
DEBUG_WARN("Failed to create HDR image description");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
wlWm.colorSurface =
|
||||||
|
wp_color_manager_v1_get_surface(wlWm.colorManager, wlWm.surface);
|
||||||
|
if (!wlWm.colorSurface)
|
||||||
|
{
|
||||||
|
DEBUG_WARN("Failed to get color management surface");
|
||||||
|
wp_image_description_v1_destroy(wlWm.hdrImageDesc);
|
||||||
|
wlWm.hdrImageDesc = NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
wp_color_management_surface_v1_set_image_description(
|
||||||
|
wlWm.colorSurface, wlWm.hdrImageDesc,
|
||||||
|
WP_COLOR_MANAGER_V1_RENDER_INTENT_PERCEPTUAL);
|
||||||
|
|
||||||
|
wlWm.hdrActive = true;
|
||||||
|
DEBUG_INFO("HDR image description set on surface (%s, %s, %u nits)",
|
||||||
|
hdrPQ ? "PQ" : "scRGB", hdrPQ ? "BT.2020" : "sRGB", maxDisplayLuminance);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool waylandRequestHDR(const uint16_t displayPrimary[3][2],
|
||||||
|
const uint16_t whitePoint[2], uint32_t maxDisplayLuminance,
|
||||||
|
uint32_t minDisplayLuminance, uint32_t maxCLL, uint32_t maxFALL,
|
||||||
|
bool hdrPQ)
|
||||||
|
{
|
||||||
|
if (!wlWm.cmFeaturesDone || !wlWm.cmHasParametric)
|
||||||
|
return false;
|
||||||
|
if (hdrPQ && !wlWm.cmHasTFSt2084PQ)
|
||||||
|
return false;
|
||||||
|
if (!hdrPQ && !wlWm.cmHasTFExtLinear)
|
||||||
|
return false;
|
||||||
|
if (hdrPQ && !wlWm.cmHasPrimariesBT2020)
|
||||||
|
return false;
|
||||||
|
if (!hdrPQ && !wlWm.cmHasPrimariesSRGB)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
wlWm.pendingHDRPQ = hdrPQ;
|
||||||
|
|
||||||
|
// Write all metadata before setting the apply flag to ensure the
|
||||||
|
// render thread sees the complete HDR metadata when it observes
|
||||||
|
// pendingHDRApply == true.
|
||||||
|
memcpy(wlWm.pendingHDRDisplayPrimary, displayPrimary,
|
||||||
|
sizeof(wlWm.pendingHDRDisplayPrimary));
|
||||||
|
memcpy(wlWm.pendingHDRWhitePoint, whitePoint,
|
||||||
|
sizeof(wlWm.pendingHDRWhitePoint));
|
||||||
|
wlWm.pendingHDRMaxDisplayLuminance = maxDisplayLuminance;
|
||||||
|
wlWm.pendingHDRMinDisplayLuminance = minDisplayLuminance;
|
||||||
|
wlWm.pendingHDRMaxCLL = maxCLL;
|
||||||
|
wlWm.pendingHDRMaxFALL = maxFALL;
|
||||||
|
|
||||||
|
wlWm.pendingHDRClear = false;
|
||||||
|
atomic_thread_fence(memory_order_release);
|
||||||
|
wlWm.pendingHDRApply = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void waylandRequestClearHDR(void)
|
||||||
|
{
|
||||||
|
wlWm.pendingHDRClear = true;
|
||||||
|
wlWm.pendingHDRApply = false;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef ENABLE_OPENGL
|
#ifdef ENABLE_OPENGL
|
||||||
bool waylandOpenGLInit(void)
|
|
||||||
|
static const EGLint eglBaseAttrs[] =
|
||||||
{
|
{
|
||||||
EGLint attr[] =
|
|
||||||
{
|
|
||||||
EGL_BUFFER_SIZE , 24,
|
|
||||||
EGL_CONFORMANT , EGL_OPENGL_BIT,
|
EGL_CONFORMANT , EGL_OPENGL_BIT,
|
||||||
EGL_RENDERABLE_TYPE , EGL_OPENGL_BIT,
|
EGL_RENDERABLE_TYPE , EGL_OPENGL_BIT,
|
||||||
EGL_COLOR_BUFFER_TYPE, EGL_RGB_BUFFER,
|
EGL_COLOR_BUFFER_TYPE, EGL_RGB_BUFFER,
|
||||||
EGL_RED_SIZE , 8,
|
|
||||||
EGL_GREEN_SIZE , 8,
|
|
||||||
EGL_BLUE_SIZE , 8,
|
|
||||||
EGL_SAMPLE_BUFFERS , 0,
|
EGL_SAMPLE_BUFFERS , 0,
|
||||||
EGL_SAMPLES , 0,
|
EGL_SAMPLES , 0,
|
||||||
EGL_NONE
|
EGL_NONE
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static bool eglChooseConfigWithDepth(EGLDisplay display, EGLint red,
|
||||||
|
EGLint green, EGLint blue, EGLint alpha, EGLint depth,
|
||||||
|
EGLConfig * config, const char ** desc)
|
||||||
|
{
|
||||||
|
// Build attr array with the base attrs plus color depth
|
||||||
|
EGLint attr[32];
|
||||||
|
int ai = 0;
|
||||||
|
attr[ai++] = EGL_RED_SIZE ; attr[ai++] = red;
|
||||||
|
attr[ai++] = EGL_GREEN_SIZE; attr[ai++] = green;
|
||||||
|
attr[ai++] = EGL_BLUE_SIZE ; attr[ai++] = blue;
|
||||||
|
attr[ai++] = EGL_ALPHA_SIZE; attr[ai++] = alpha;
|
||||||
|
attr[ai++] = EGL_BUFFER_SIZE; attr[ai++] = depth;
|
||||||
|
for (int i = 0; eglBaseAttrs[i] != EGL_NONE; ++i)
|
||||||
|
attr[ai++] = eglBaseAttrs[i];
|
||||||
|
attr[ai] = EGL_NONE;
|
||||||
|
|
||||||
|
EGLint num_config;
|
||||||
|
if (eglChooseConfig(display, attr, config, 1, &num_config) && num_config > 0)
|
||||||
|
{
|
||||||
|
if (desc)
|
||||||
|
*desc = red >= 16 ? "FP16 (RGBA16F)" :
|
||||||
|
red >= 10 ? "10-bit (RGBA10)" : "8-bit (RGBA8)";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool waylandOpenGLInit(void)
|
||||||
|
{
|
||||||
wlWm.glDisplay = waylandGetEGLDisplay();
|
wlWm.glDisplay = waylandGetEGLDisplay();
|
||||||
|
|
||||||
int maj, min;
|
int maj, min;
|
||||||
@@ -181,13 +444,31 @@ bool waylandOpenGLInit(void)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
EGLint num_config;
|
EGLConfig config;
|
||||||
if (!eglChooseConfig(wlWm.glDisplay, attr, &wlWm.glConfig, 1, &num_config))
|
const char * configDesc = NULL;
|
||||||
|
|
||||||
|
// Probe for best available color depth: FP16 → 10-bit → 8-bit
|
||||||
|
if (!eglChooseConfigWithDepth(wlWm.glDisplay,
|
||||||
|
16, 16, 16, 0, 48, &config, &configDesc) &&
|
||||||
|
!eglChooseConfigWithDepth(wlWm.glDisplay,
|
||||||
|
10, 10, 10, 2, 32, &config, &configDesc) &&
|
||||||
|
!eglChooseConfigWithDepth(wlWm.glDisplay,
|
||||||
|
8, 8, 8, 0, 24, &config, &configDesc))
|
||||||
{
|
{
|
||||||
DEBUG_ERROR("Failed to choose config (eglError: 0x%x)", eglGetError());
|
DEBUG_ERROR("Failed to choose any EGL config");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wlWm.glConfig = config;
|
||||||
|
DEBUG_INFO("EGL config: %s", configDesc);
|
||||||
|
|
||||||
|
// Also store the 8-bit fallback for SDR contexts
|
||||||
|
if (configDesc && strcmp(configDesc, "8-bit (RGBA8)") != 0)
|
||||||
|
eglChooseConfigWithDepth(wlWm.glDisplay,
|
||||||
|
8, 8, 8, 0, 24, &wlWm.glConfigSDR, NULL);
|
||||||
|
else
|
||||||
|
wlWm.glConfigSDR = wlWm.glConfig;
|
||||||
|
|
||||||
wlWm.glSurface = eglCreateWindowSurface(wlWm.glDisplay, wlWm.glConfig, wlWm.eglWindow, NULL);
|
wlWm.glSurface = eglCreateWindowSurface(wlWm.glDisplay, wlWm.glConfig, wlWm.eglWindow, NULL);
|
||||||
if (wlWm.glSurface == EGL_NO_SURFACE)
|
if (wlWm.glSurface == EGL_NO_SURFACE)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Looking Glass
|
* Looking Glass
|
||||||
* Copyright © 2017-2025 The Looking Glass Authors
|
* Copyright © 2017-2026 The Looking Glass Authors
|
||||||
* https://looking-glass.io
|
* https://looking-glass.io
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Looking Glass
|
* Looking Glass
|
||||||
* Copyright © 2017-2025 The Looking Glass Authors
|
* Copyright © 2017-2026 The Looking Glass Authors
|
||||||
* https://looking-glass.io
|
* https://looking-glass.io
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
@@ -32,6 +32,9 @@
|
|||||||
#include "app.h"
|
#include "app.h"
|
||||||
#include "common/debug.h"
|
#include "common/debug.h"
|
||||||
|
|
||||||
|
const double WL_SCROLL_STEP = 15.0;
|
||||||
|
const double WL_HALF_SCROLL_STEP = WL_SCROLL_STEP / 2.0;
|
||||||
|
|
||||||
// Mouse-handling listeners.
|
// Mouse-handling listeners.
|
||||||
|
|
||||||
static void pointerMotionHandler(void * data, struct wl_pointer * pointer,
|
static void pointerMotionHandler(void * data, struct wl_pointer * pointer,
|
||||||
@@ -91,12 +94,25 @@ static void pointerAxisHandler(void * data, struct wl_pointer * pointer,
|
|||||||
if (axis != WL_POINTER_AXIS_VERTICAL_SCROLL)
|
if (axis != WL_POINTER_AXIS_VERTICAL_SCROLL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
int button = value > 0 ?
|
double delta = wl_fixed_to_double(value);
|
||||||
5 /* SPICE_MOUSE_BUTTON_DOWN */ :
|
|
||||||
4 /* SPICE_MOUSE_BUTTON_UP */;
|
wlWm.scrollState += delta;
|
||||||
app_handleButtonPress(button);
|
|
||||||
app_handleButtonRelease(button);
|
while (wlWm.scrollState > WL_HALF_SCROLL_STEP)
|
||||||
app_handleWheelMotion(wl_fixed_to_double(value) / 15.0);
|
{
|
||||||
|
app_handleButtonPress(5 /* SPICE_MOUSE_BUTTON_DOWN */);
|
||||||
|
app_handleButtonRelease(5 /* SPICE_MOUSE_BUTTON_DOWN */);
|
||||||
|
wlWm.scrollState -= WL_SCROLL_STEP;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (wlWm.scrollState < -WL_HALF_SCROLL_STEP)
|
||||||
|
{
|
||||||
|
app_handleButtonPress(4 /* SPICE_MOUSE_BUTTON_UP */);
|
||||||
|
app_handleButtonRelease(4 /* SPICE_MOUSE_BUTTON_UP */);
|
||||||
|
wlWm.scrollState += WL_SCROLL_STEP;
|
||||||
|
}
|
||||||
|
|
||||||
|
app_handleWheelMotion(delta / WL_SCROLL_STEP);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mapWaylandToSpiceButton(uint32_t button)
|
static int mapWaylandToSpiceButton(uint32_t button)
|
||||||
@@ -209,7 +225,7 @@ done:
|
|||||||
close(fd);
|
close(fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int getCharcode(uint32_t key)
|
int waylandGetCharCode(int key)
|
||||||
{
|
{
|
||||||
key += 8; // xkb scancode is evdev scancode + 8
|
key += 8; // xkb scancode is evdev scancode + 8
|
||||||
xkb_keysym_t sym = xkb_state_key_get_one_sym(wlWm.xkbState, key);
|
xkb_keysym_t sym = xkb_state_key_get_one_sym(wlWm.xkbState, key);
|
||||||
@@ -232,7 +248,7 @@ static void keyboardEnterHandler(void * data, struct wl_keyboard * keyboard,
|
|||||||
|
|
||||||
uint32_t * key;
|
uint32_t * key;
|
||||||
wl_array_for_each(key, keys)
|
wl_array_for_each(key, keys)
|
||||||
app_handleKeyPress(*key, getCharcode(*key));
|
app_handleKeyPress(*key);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void keyboardLeaveHandler(void * data, struct wl_keyboard * keyboard,
|
static void keyboardLeaveHandler(void * data, struct wl_keyboard * keyboard,
|
||||||
@@ -253,9 +269,9 @@ static void keyboardKeyHandler(void * data, struct wl_keyboard * keyboard,
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (state == WL_KEYBOARD_KEY_STATE_PRESSED)
|
if (state == WL_KEYBOARD_KEY_STATE_PRESSED)
|
||||||
app_handleKeyPress(key, getCharcode(key));
|
app_handleKeyPress(key);
|
||||||
else
|
else
|
||||||
app_handleKeyRelease(key, getCharcode(key));
|
app_handleKeyRelease(key);
|
||||||
|
|
||||||
if (!wlWm.xkbState || !app_isOverlayMode() || state != WL_KEYBOARD_KEY_STATE_PRESSED)
|
if (!wlWm.xkbState || !app_isOverlayMode() || state != WL_KEYBOARD_KEY_STATE_PRESSED)
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Looking Glass
|
* Looking Glass
|
||||||
* Copyright © 2017-2025 The Looking Glass Authors
|
* Copyright © 2017-2026 The Looking Glass Authors
|
||||||
* https://looking-glass.io
|
* https://looking-glass.io
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
@@ -58,6 +58,8 @@ typedef struct WL_DesktopOps
|
|||||||
bool (*pollInit)(struct wl_display * display);
|
bool (*pollInit)(struct wl_display * display);
|
||||||
|
|
||||||
void (*pollWait)(struct wl_display * display, int epollFd, unsigned int time);
|
void (*pollWait)(struct wl_display * display, int epollFd, unsigned int time);
|
||||||
|
|
||||||
|
bool (*configured)(void);
|
||||||
}
|
}
|
||||||
WL_DesktopOps;
|
WL_DesktopOps;
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Looking Glass
|
* Looking Glass
|
||||||
* Copyright © 2017-2025 The Looking Glass Authors
|
* Copyright © 2017-2026 The Looking Glass Authors
|
||||||
* https://looking-glass.io
|
* https://looking-glass.io
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
@@ -29,17 +29,17 @@
|
|||||||
|
|
||||||
static void outputUpdateScale(struct WaylandOutput * node)
|
static void outputUpdateScale(struct WaylandOutput * node)
|
||||||
{
|
{
|
||||||
wl_fixed_t original = node->scale;
|
struct WaylandScale original = node->scale;
|
||||||
|
|
||||||
if (!wlWm.useFractionalScale || !wlWm.viewporter || !node->logicalWidth)
|
if (!wlWm.useFractionalScale || !wlWm.viewporter || !node->logicalWidth)
|
||||||
node->scale = wl_fixed_from_int(node->scaleInt);
|
node->scale = waylandScaleFromInt(node->scaleInt);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int32_t modeWidth = node->modeRotate ? node->modeHeight : node->modeWidth;
|
int32_t modeWidth = node->modeRotate ? node->modeHeight : node->modeWidth;
|
||||||
node->scale = wl_fixed_from_double(1.0 * modeWidth / node->logicalWidth);
|
node->scale = waylandScaleFromRatio(modeWidth, node->logicalWidth);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (original != node->scale)
|
if (!waylandScaleEqual(original, node->scale))
|
||||||
waylandWindowUpdateScale();
|
waylandWindowUpdateScale();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -167,7 +167,7 @@ void waylandOutputBind(uint32_t name, uint32_t version)
|
|||||||
}
|
}
|
||||||
|
|
||||||
node->name = name;
|
node->name = name;
|
||||||
node->scale = 0;
|
node->scale = waylandScaleFromInt(0);
|
||||||
node->version = version;
|
node->version = version;
|
||||||
node->output = wl_registry_bind(wlWm.registry, name,
|
node->output = wl_registry_bind(wlWm.registry, name,
|
||||||
&wl_output_interface, version >= 3 ? 3 : 2);
|
&wl_output_interface, version >= 3 ? 3 : 2);
|
||||||
@@ -209,12 +209,12 @@ void waylandOutputTryUnbind(uint32_t name)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
wl_fixed_t waylandOutputGetScale(struct wl_output * output)
|
struct WaylandScale waylandOutputGetScale(struct wl_output * output)
|
||||||
{
|
{
|
||||||
struct WaylandOutput * node;
|
struct WaylandOutput * node;
|
||||||
|
|
||||||
wl_list_for_each(node, &wlWm.outputs, link)
|
wl_list_for_each(node, &wlWm.outputs, link)
|
||||||
if (node->output == output)
|
if (node->output == output)
|
||||||
return node->scale;
|
return node->scale;
|
||||||
return 0;
|
return waylandScaleFromInt(0);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Looking Glass
|
* Looking Glass
|
||||||
* Copyright © 2017-2025 The Looking Glass Authors
|
* Copyright © 2017-2026 The Looking Glass Authors
|
||||||
* https://looking-glass.io
|
* https://looking-glass.io
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Looking Glass
|
* Looking Glass
|
||||||
* Copyright © 2017-2025 The Looking Glass Authors
|
* Copyright © 2017-2026 The Looking Glass Authors
|
||||||
* https://looking-glass.io
|
* https://looking-glass.io
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
|||||||
@@ -60,6 +60,15 @@ wayland_generate(
|
|||||||
wayland_generate(
|
wayland_generate(
|
||||||
"${WAYLAND_PROTOCOLS_BASE}/staging/xdg-activation/xdg-activation-v1.xml"
|
"${WAYLAND_PROTOCOLS_BASE}/staging/xdg-activation/xdg-activation-v1.xml"
|
||||||
"${CMAKE_BINARY_DIR}/wayland/wayland-xdg-activation-v1-client-protocol")
|
"${CMAKE_BINARY_DIR}/wayland/wayland-xdg-activation-v1-client-protocol")
|
||||||
|
wayland_generate(
|
||||||
|
"${WAYLAND_PROTOCOLS_BASE}/staging/fractional-scale/fractional-scale-v1.xml"
|
||||||
|
"${CMAKE_BINARY_DIR}/wayland/wayland-fractional-scale-v1-client-protocol")
|
||||||
|
wayland_generate(
|
||||||
|
"${WAYLAND_PROTOCOLS_BASE}/staging/content-type/content-type-v1.xml"
|
||||||
|
"${CMAKE_BINARY_DIR}/wayland/wayland-content-type-v1-client-protocol")
|
||||||
|
wayland_generate(
|
||||||
|
"${WAYLAND_PROTOCOLS_BASE}/staging/color-management/color-management-v1.xml"
|
||||||
|
"${CMAKE_BINARY_DIR}/wayland/wayland-color-management-v1-client-protocol")
|
||||||
|
|
||||||
target_link_libraries(wayland_protocol
|
target_link_libraries(wayland_protocol
|
||||||
PkgConfig::WAYLAND
|
PkgConfig::WAYLAND
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Looking Glass
|
* Looking Glass
|
||||||
* Copyright © 2017-2025 The Looking Glass Authors
|
* Copyright © 2017-2026 The Looking Glass Authors
|
||||||
* https://looking-glass.io
|
* https://looking-glass.io
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
@@ -46,6 +46,9 @@ static void registryGlobalHandler(void * data, struct wl_registry * registry,
|
|||||||
else if (!strcmp(interface, wp_viewporter_interface.name))
|
else if (!strcmp(interface, wp_viewporter_interface.name))
|
||||||
wlWm.viewporter = wl_registry_bind(wlWm.registry, name,
|
wlWm.viewporter = wl_registry_bind(wlWm.registry, name,
|
||||||
&wp_viewporter_interface, 1);
|
&wp_viewporter_interface, 1);
|
||||||
|
else if (!strcmp(interface, wp_fractional_scale_manager_v1_interface.name))
|
||||||
|
wlWm.fractionalScaleManager = wl_registry_bind(wlWm.registry, name,
|
||||||
|
&wp_fractional_scale_manager_v1_interface, 1);
|
||||||
else if (!strcmp(interface, zwp_relative_pointer_manager_v1_interface.name))
|
else if (!strcmp(interface, zwp_relative_pointer_manager_v1_interface.name))
|
||||||
wlWm.relativePointerManager = wl_registry_bind(wlWm.registry, name,
|
wlWm.relativePointerManager = wl_registry_bind(wlWm.registry, name,
|
||||||
&zwp_relative_pointer_manager_v1_interface, 1);
|
&zwp_relative_pointer_manager_v1_interface, 1);
|
||||||
@@ -68,6 +71,12 @@ static void registryGlobalHandler(void * data, struct wl_registry * registry,
|
|||||||
else if (!strcmp(interface, xdg_activation_v1_interface.name))
|
else if (!strcmp(interface, xdg_activation_v1_interface.name))
|
||||||
wlWm.xdgActivation = wl_registry_bind(wlWm.registry, name,
|
wlWm.xdgActivation = wl_registry_bind(wlWm.registry, name,
|
||||||
&xdg_activation_v1_interface, 1);
|
&xdg_activation_v1_interface, 1);
|
||||||
|
else if (!strcmp(interface, wp_content_type_manager_v1_interface.name))
|
||||||
|
wlWm.contentTypeManager = wl_registry_bind(wlWm.registry, name,
|
||||||
|
&wp_content_type_manager_v1_interface, 1);
|
||||||
|
else if (!strcmp(interface, wp_color_manager_v1_interface.name))
|
||||||
|
wlWm.colorManager = wl_registry_bind(wlWm.registry, name,
|
||||||
|
&wp_color_manager_v1_interface, 1);
|
||||||
else if (wlWm.desktop->registryGlobalHandler(
|
else if (wlWm.desktop->registryGlobalHandler(
|
||||||
data, registry, name, interface, version))
|
data, registry, name, interface, version))
|
||||||
return;
|
return;
|
||||||
|
|||||||
80
client/displayservers/Wayland/scale.h
Normal file
80
client/displayservers/Wayland/scale.h
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
/**
|
||||||
|
* Looking Glass
|
||||||
|
* Copyright © 2017-2026 The Looking Glass Authors
|
||||||
|
* https://looking-glass.io
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the Free
|
||||||
|
* Software Foundation; either version 2 of the License, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc., 59
|
||||||
|
* Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
struct WaylandScale
|
||||||
|
{
|
||||||
|
int32_t num;
|
||||||
|
int32_t den;
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline struct WaylandScale waylandScaleFromInt(int32_t scale)
|
||||||
|
{
|
||||||
|
return (struct WaylandScale) { scale, 1 };
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline struct WaylandScale waylandScaleFromRatio(int32_t num, int32_t den)
|
||||||
|
{
|
||||||
|
return (struct WaylandScale) { num, den };
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool waylandScaleValid(struct WaylandScale scale)
|
||||||
|
{
|
||||||
|
return scale.num > 0 && scale.den > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool waylandScaleEqual(struct WaylandScale a, struct WaylandScale b)
|
||||||
|
{
|
||||||
|
return (int64_t)a.num * b.den == (int64_t)b.num * a.den;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int waylandScaleCmp(struct WaylandScale a, struct WaylandScale b)
|
||||||
|
{
|
||||||
|
int64_t lhs = (int64_t)a.num * b.den;
|
||||||
|
int64_t rhs = (int64_t)b.num * a.den;
|
||||||
|
|
||||||
|
return (lhs > rhs) - (lhs < rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool waylandScaleIsFractional(struct WaylandScale scale)
|
||||||
|
{
|
||||||
|
return waylandScaleValid(scale) && scale.num % scale.den != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int waylandScaleFloor(struct WaylandScale scale)
|
||||||
|
{
|
||||||
|
return scale.num / scale.den;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int waylandScaleCeil(struct WaylandScale scale)
|
||||||
|
{
|
||||||
|
return (scale.num + scale.den - 1) / scale.den;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int waylandScaleMulInt(struct WaylandScale scale, int value)
|
||||||
|
{
|
||||||
|
return (int)(((int64_t)value * scale.num + scale.den / 2) / scale.den);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline double waylandScaleToDouble(struct WaylandScale scale)
|
||||||
|
{
|
||||||
|
return (double)scale.num / (double)scale.den;
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Looking Glass
|
* Looking Glass
|
||||||
* Copyright © 2017-2025 The Looking Glass Authors
|
* Copyright © 2017-2026 The Looking Glass Authors
|
||||||
* https://looking-glass.io
|
* https://looking-glass.io
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Looking Glass
|
* Looking Glass
|
||||||
* Copyright © 2017-2025 The Looking Glass Authors
|
* Copyright © 2017-2026 The Looking Glass Authors
|
||||||
* https://looking-glass.io
|
* https://looking-glass.io
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
@@ -28,6 +28,7 @@
|
|||||||
|
|
||||||
#include "common/debug.h"
|
#include "common/debug.h"
|
||||||
#include "common/option.h"
|
#include "common/option.h"
|
||||||
|
#include "interface/renderer.h"
|
||||||
|
|
||||||
#include "dynamic/wayland_desktops.h"
|
#include "dynamic/wayland_desktops.h"
|
||||||
|
|
||||||
@@ -143,6 +144,9 @@ static bool waylandInit(const LG_DSInitParams params)
|
|||||||
if (!waylandRegistryInit())
|
if (!waylandRegistryInit())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if (!waylandColorMgmtInit())
|
||||||
|
return false;
|
||||||
|
|
||||||
if (!waylandActivationInit())
|
if (!waylandActivationInit())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@@ -189,6 +193,7 @@ static void waylandFree(void)
|
|||||||
waylandPresentationFree();
|
waylandPresentationFree();
|
||||||
waylandInputFree();
|
waylandInputFree();
|
||||||
waylandOutputFree();
|
waylandOutputFree();
|
||||||
|
waylandColorMgmtFree();
|
||||||
waylandRegistryFree();
|
waylandRegistryFree();
|
||||||
waylandCursorFree();
|
waylandCursorFree();
|
||||||
wl_display_disconnect(wlWm.display);
|
wl_display_disconnect(wlWm.display);
|
||||||
@@ -202,6 +207,12 @@ static bool waylandGetProp(LG_DSProperty prop, void * ret)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (prop == LG_DS_NATIVE_HDR)
|
||||||
|
{
|
||||||
|
*(bool *)ret = wlWm.cmCanDoHDR;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -227,6 +238,22 @@ static void waylandMinimize(void)
|
|||||||
wlWm.desktop->minimize();
|
wlWm.desktop->minimize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool waylandHDRCallback(const void * rendererFormat)
|
||||||
|
{
|
||||||
|
if (!wlWm.colorManager)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const LG_RendererFormat * format = (const LG_RendererFormat *)rendererFormat;
|
||||||
|
if (format->hdr)
|
||||||
|
return waylandRequestHDR(format->hdrDisplayPrimary, format->hdrWhitePoint,
|
||||||
|
format->hdrMaxDisplayLuminance, format->hdrMinDisplayLuminance,
|
||||||
|
format->hdrMaxContentLightLevel, format->hdrMaxFrameAverageLightLevel,
|
||||||
|
format->hdrPQ);
|
||||||
|
else
|
||||||
|
waylandRequestClearHDR();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
struct LG_DisplayServerOps LGDS_Wayland =
|
struct LG_DisplayServerOps LGDS_Wayland =
|
||||||
{
|
{
|
||||||
.name = "Wayland",
|
.name = "Wayland",
|
||||||
@@ -263,6 +290,7 @@ struct LG_DisplayServerOps LGDS_Wayland =
|
|||||||
.uncapturePointer = waylandUncapturePointer,
|
.uncapturePointer = waylandUncapturePointer,
|
||||||
.grabKeyboard = waylandGrabKeyboard,
|
.grabKeyboard = waylandGrabKeyboard,
|
||||||
.ungrabKeyboard = waylandUngrabKeyboard,
|
.ungrabKeyboard = waylandUngrabKeyboard,
|
||||||
|
.getCharCode = waylandGetCharCode,
|
||||||
.warpPointer = waylandWarpPointer,
|
.warpPointer = waylandWarpPointer,
|
||||||
.realignPointer = waylandRealignPointer,
|
.realignPointer = waylandRealignPointer,
|
||||||
.isValidPointerPos = waylandIsValidPointerPos,
|
.isValidPointerPos = waylandIsValidPointerPos,
|
||||||
@@ -275,6 +303,8 @@ struct LG_DisplayServerOps LGDS_Wayland =
|
|||||||
.getFullscreen = waylandGetFullscreen,
|
.getFullscreen = waylandGetFullscreen,
|
||||||
.minimize = waylandMinimize,
|
.minimize = waylandMinimize,
|
||||||
|
|
||||||
|
.setHDRImageDescription = waylandHDRCallback,
|
||||||
|
|
||||||
.cbInit = waylandCBInit,
|
.cbInit = waylandCBInit,
|
||||||
.cbNotice = waylandCBNotice,
|
.cbNotice = waylandCBNotice,
|
||||||
.cbRelease = waylandCBRelease,
|
.cbRelease = waylandCBRelease,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Looking Glass
|
* Looking Glass
|
||||||
* Copyright © 2017-2025 The Looking Glass Authors
|
* Copyright © 2017-2026 The Looking Glass Authors
|
||||||
* https://looking-glass.io
|
* https://looking-glass.io
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
@@ -47,6 +47,11 @@
|
|||||||
#include "wayland-idle-inhibit-unstable-v1-client-protocol.h"
|
#include "wayland-idle-inhibit-unstable-v1-client-protocol.h"
|
||||||
#include "wayland-xdg-output-unstable-v1-client-protocol.h"
|
#include "wayland-xdg-output-unstable-v1-client-protocol.h"
|
||||||
#include "wayland-xdg-activation-v1-client-protocol.h"
|
#include "wayland-xdg-activation-v1-client-protocol.h"
|
||||||
|
#include "wayland-fractional-scale-v1-client-protocol.h"
|
||||||
|
#include "wayland-content-type-v1-client-protocol.h"
|
||||||
|
#include "wayland-color-management-v1-client-protocol.h"
|
||||||
|
|
||||||
|
#include "scale.h"
|
||||||
|
|
||||||
typedef void (*WaylandPollCallback)(uint32_t events, void * opaque);
|
typedef void (*WaylandPollCallback)(uint32_t events, void * opaque);
|
||||||
|
|
||||||
@@ -62,7 +67,7 @@ struct WaylandPoll
|
|||||||
struct WaylandOutput
|
struct WaylandOutput
|
||||||
{
|
{
|
||||||
uint32_t name;
|
uint32_t name;
|
||||||
wl_fixed_t scale;
|
struct WaylandScale scale;
|
||||||
int32_t scaleInt;
|
int32_t scaleInt;
|
||||||
int32_t logicalWidth;
|
int32_t logicalWidth;
|
||||||
int32_t logicalHeight;
|
int32_t logicalHeight;
|
||||||
@@ -81,13 +86,6 @@ struct SurfaceOutput
|
|||||||
struct wl_list link;
|
struct wl_list link;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum EGLSwapWithDamageState {
|
|
||||||
SWAP_WITH_DAMAGE_UNKNOWN,
|
|
||||||
SWAP_WITH_DAMAGE_UNSUPPORTED,
|
|
||||||
SWAP_WITH_DAMAGE_KHR,
|
|
||||||
SWAP_WITH_DAMAGE_EXT,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct xkb_context;
|
struct xkb_context;
|
||||||
struct xkb_keymap;
|
struct xkb_keymap;
|
||||||
struct xkb_state;
|
struct xkb_state;
|
||||||
@@ -108,12 +106,13 @@ struct WaylandDSState
|
|||||||
struct wl_shm * shm;
|
struct wl_shm * shm;
|
||||||
struct wl_compositor * compositor;
|
struct wl_compositor * compositor;
|
||||||
|
|
||||||
wl_fixed_t scale;
|
struct WaylandScale scale;
|
||||||
bool fractionalScale;
|
bool fractionalScale;
|
||||||
bool needsResize;
|
bool needsResize;
|
||||||
bool configured;
|
bool configured;
|
||||||
bool warpSupport;
|
bool warpSupport;
|
||||||
double cursorX, cursorY;
|
double cursorX, cursorY;
|
||||||
|
double scrollState;
|
||||||
|
|
||||||
#if defined(ENABLE_EGL) || defined(ENABLE_OPENGL)
|
#if defined(ENABLE_EGL) || defined(ENABLE_OPENGL)
|
||||||
struct wl_egl_window * eglWindow;
|
struct wl_egl_window * eglWindow;
|
||||||
@@ -122,7 +121,8 @@ struct WaylandDSState
|
|||||||
|
|
||||||
#ifdef ENABLE_OPENGL
|
#ifdef ENABLE_OPENGL
|
||||||
EGLDisplay glDisplay;
|
EGLDisplay glDisplay;
|
||||||
EGLConfig glConfig;
|
EGLConfig glConfig; // primary config (best bit depth probed)
|
||||||
|
EGLConfig glConfigSDR; // fallback 8-bit SDR config
|
||||||
EGLSurface glSurface;
|
EGLSurface glSurface;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -172,11 +172,52 @@ struct WaylandDSState
|
|||||||
|
|
||||||
struct wp_viewporter * viewporter;
|
struct wp_viewporter * viewporter;
|
||||||
struct wp_viewport * viewport;
|
struct wp_viewport * viewport;
|
||||||
|
struct wp_fractional_scale_manager_v1 * fractionalScaleManager;
|
||||||
|
struct wp_fractional_scale_v1 * fractionalScaleInterface;
|
||||||
struct zxdg_output_manager_v1 * xdgOutputManager;
|
struct zxdg_output_manager_v1 * xdgOutputManager;
|
||||||
struct wl_list outputs; // WaylandOutput::link
|
struct wl_list outputs; // WaylandOutput::link
|
||||||
struct wl_list surfaceOutputs; // SurfaceOutput::link
|
struct wl_list surfaceOutputs; // SurfaceOutput::link
|
||||||
bool useFractionalScale;
|
bool useFractionalScale;
|
||||||
|
|
||||||
|
struct wp_content_type_manager_v1 * contentTypeManager;
|
||||||
|
struct wp_content_type_v1 * contentType;
|
||||||
|
|
||||||
|
// Color management (HDR)
|
||||||
|
struct wp_color_manager_v1 * colorManager;
|
||||||
|
struct wp_color_management_surface_v1 * colorSurface;
|
||||||
|
struct wp_image_description_v1 * hdrImageDesc;
|
||||||
|
struct wp_image_description_creator_params_v1 * hdrImageCreator;
|
||||||
|
|
||||||
|
// Set to true when an HDR image description is active on the surface
|
||||||
|
bool hdrActive;
|
||||||
|
|
||||||
|
// wp_color_manager_v1 feature advertisement tracking.
|
||||||
|
// Set to true after the done event for the color-manager has been received
|
||||||
|
// and all compositor capabilities have been recorded.
|
||||||
|
bool cmFeaturesDone;
|
||||||
|
bool cmHasParametric;
|
||||||
|
bool cmHasLuminances;
|
||||||
|
bool cmHasMasteringPrimaries;
|
||||||
|
bool cmHasTFSt2084PQ;
|
||||||
|
bool cmHasTFExtLinear;
|
||||||
|
bool cmHasPrimariesBT2020;
|
||||||
|
bool cmHasPrimariesSRGB;
|
||||||
|
bool cmHasPerceptualIntent;
|
||||||
|
bool cmCanDoHDR; // true if compositor supports features needed for HDR
|
||||||
|
|
||||||
|
// Pending HDR format to apply (set by frame thread, applied in swap buffers).
|
||||||
|
// pendingHDRApply and pendingHDRClear are accessed from multiple threads
|
||||||
|
// without a lock, so they must be atomic.
|
||||||
|
_Atomic(bool) pendingHDRApply;
|
||||||
|
_Atomic(bool) pendingHDRClear;
|
||||||
|
bool pendingHDRPQ;
|
||||||
|
uint16_t pendingHDRDisplayPrimary[3][2];
|
||||||
|
uint16_t pendingHDRWhitePoint[2];
|
||||||
|
uint32_t pendingHDRMaxDisplayLuminance;
|
||||||
|
uint32_t pendingHDRMinDisplayLuminance;
|
||||||
|
uint32_t pendingHDRMaxCLL;
|
||||||
|
uint32_t pendingHDRMaxFALL;
|
||||||
|
|
||||||
LGEvent * frameEvent;
|
LGEvent * frameEvent;
|
||||||
|
|
||||||
struct wl_list poll; // WaylandPoll::link
|
struct wl_list poll; // WaylandPoll::link
|
||||||
@@ -259,6 +300,24 @@ void waylandGLSetSwapInterval(int interval);
|
|||||||
void waylandGLSwapBuffers(void);
|
void waylandGLSwapBuffers(void);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// HDR color management (Wayland color-management-v1)
|
||||||
|
bool waylandColorMgmtInit(void);
|
||||||
|
void waylandColorMgmtFree(void);
|
||||||
|
void waylandSetHDRImageDescription(const uint16_t displayPrimary[3][2],
|
||||||
|
const uint16_t whitePoint[2], uint32_t maxDisplayLuminance,
|
||||||
|
uint32_t minDisplayLuminance, uint32_t maxCLL, uint32_t maxFALL,
|
||||||
|
bool hdrPQ);
|
||||||
|
void waylandClearHDRImageDescription(void);
|
||||||
|
|
||||||
|
// Queue HDR change from any thread (applied in waylandEGLSwapBuffers).
|
||||||
|
// Returns true if the request was queued, false if HDR is not available
|
||||||
|
// (no color manager, missing features, or unsupported TF/primaries).
|
||||||
|
bool waylandRequestHDR(const uint16_t displayPrimary[3][2],
|
||||||
|
const uint16_t whitePoint[2], uint32_t maxDisplayLuminance,
|
||||||
|
uint32_t minDisplayLuminance, uint32_t maxCLL, uint32_t maxFALL,
|
||||||
|
bool hdrPQ);
|
||||||
|
void waylandRequestClearHDR(void);
|
||||||
|
|
||||||
// idle module
|
// idle module
|
||||||
bool waylandIdleInit(void);
|
bool waylandIdleInit(void);
|
||||||
void waylandIdleFree(void);
|
void waylandIdleFree(void);
|
||||||
@@ -277,13 +336,14 @@ void waylandUncapturePointer(void);
|
|||||||
void waylandRealignPointer(void);
|
void waylandRealignPointer(void);
|
||||||
void waylandWarpPointer(int x, int y, bool exiting);
|
void waylandWarpPointer(int x, int y, bool exiting);
|
||||||
void waylandGuestPointerUpdated(double x, double y, double localX, double localY);
|
void waylandGuestPointerUpdated(double x, double y, double localX, double localY);
|
||||||
|
int waylandGetCharCode(int key);
|
||||||
|
|
||||||
// output module
|
// output module
|
||||||
bool waylandOutputInit(void);
|
bool waylandOutputInit(void);
|
||||||
void waylandOutputFree(void);
|
void waylandOutputFree(void);
|
||||||
void waylandOutputBind(uint32_t name, uint32_t version);
|
void waylandOutputBind(uint32_t name, uint32_t version);
|
||||||
void waylandOutputTryUnbind(uint32_t name);
|
void waylandOutputTryUnbind(uint32_t name);
|
||||||
wl_fixed_t waylandOutputGetScale(struct wl_output * output);
|
struct WaylandScale waylandOutputGetScale(struct wl_output * output);
|
||||||
|
|
||||||
// poll module
|
// poll module
|
||||||
bool waylandPollInit(void);
|
bool waylandPollInit(void);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Looking Glass
|
* Looking Glass
|
||||||
* Copyright © 2017-2025 The Looking Glass Authors
|
* Copyright © 2017-2026 The Looking Glass Authors
|
||||||
* https://looking-glass.io
|
* https://looking-glass.io
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
@@ -31,29 +31,39 @@
|
|||||||
|
|
||||||
// Surface-handling listeners.
|
// Surface-handling listeners.
|
||||||
|
|
||||||
void waylandWindowUpdateScale(void)
|
static void setScale(struct WaylandScale newScale)
|
||||||
{
|
{
|
||||||
wl_fixed_t maxScale = 0;
|
wlWm.scale = newScale;
|
||||||
struct SurfaceOutput * node;
|
wlWm.fractionalScale = waylandScaleIsFractional(newScale);
|
||||||
|
|
||||||
wl_list_for_each(node, &wlWm.surfaceOutputs, link)
|
|
||||||
{
|
|
||||||
wl_fixed_t scale = waylandOutputGetScale(node->output);
|
|
||||||
if (scale > maxScale)
|
|
||||||
maxScale = scale;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (maxScale)
|
|
||||||
{
|
|
||||||
wlWm.scale = maxScale;
|
|
||||||
wlWm.fractionalScale = wl_fixed_from_int(wl_fixed_to_int(maxScale)) != maxScale;
|
|
||||||
wlWm.needsResize = true;
|
wlWm.needsResize = true;
|
||||||
|
|
||||||
|
if (wlWm.desktop->configured())
|
||||||
|
{
|
||||||
waylandCursorScaleChange();
|
waylandCursorScaleChange();
|
||||||
app_invalidateWindow(true);
|
app_invalidateWindow(true);
|
||||||
waylandStopWaitFrame();
|
waylandStopWaitFrame();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void waylandWindowUpdateScale(void)
|
||||||
|
{
|
||||||
|
if (wlWm.fractionalScaleInterface)
|
||||||
|
return;
|
||||||
|
|
||||||
|
struct WaylandScale maxScale = waylandScaleFromInt(0);
|
||||||
|
struct SurfaceOutput * node;
|
||||||
|
|
||||||
|
wl_list_for_each(node, &wlWm.surfaceOutputs, link)
|
||||||
|
{
|
||||||
|
struct WaylandScale scale = waylandOutputGetScale(node->output);
|
||||||
|
if (waylandScaleCmp(scale, maxScale) > 0)
|
||||||
|
maxScale = scale;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (waylandScaleValid(maxScale))
|
||||||
|
setScale(maxScale);
|
||||||
|
}
|
||||||
|
|
||||||
static void wlSurfaceEnterHandler(void * data, struct wl_surface * surface, struct wl_output * output)
|
static void wlSurfaceEnterHandler(void * data, struct wl_surface * surface, struct wl_output * output)
|
||||||
{
|
{
|
||||||
struct SurfaceOutput * node = malloc(sizeof(*node));
|
struct SurfaceOutput * node = malloc(sizeof(*node));
|
||||||
@@ -85,9 +95,19 @@ static const struct wl_surface_listener wlSurfaceListener = {
|
|||||||
.leave = wlSurfaceLeaveHandler,
|
.leave = wlSurfaceLeaveHandler,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void fractionalScalePreferredScale(void * data,
|
||||||
|
struct wp_fractional_scale_v1 * fractionalScale, uint32_t scale)
|
||||||
|
{
|
||||||
|
setScale(waylandScaleFromRatio(scale, 120));
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct wp_fractional_scale_v1_listener fractionalScaleListener = {
|
||||||
|
.preferred_scale = fractionalScalePreferredScale,
|
||||||
|
};
|
||||||
|
|
||||||
bool waylandWindowInit(const char * title, const char * appId, bool fullscreen, bool maximize, bool borderless, bool resizable)
|
bool waylandWindowInit(const char * title, const char * appId, bool fullscreen, bool maximize, bool borderless, bool resizable)
|
||||||
{
|
{
|
||||||
wlWm.scale = wl_fixed_from_int(1);
|
wlWm.scale = waylandScaleFromInt(1);
|
||||||
|
|
||||||
wlWm.frameEvent = lgCreateEvent(true, 0);
|
wlWm.frameEvent = lgCreateEvent(true, 0);
|
||||||
if (!wlWm.frameEvent)
|
if (!wlWm.frameEvent)
|
||||||
@@ -110,8 +130,23 @@ bool waylandWindowInit(const char * title, const char * appId, bool fullscreen,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (wlWm.fractionalScaleManager)
|
||||||
|
{
|
||||||
|
wlWm.fractionalScaleInterface = wp_fractional_scale_manager_v1_get_fractional_scale(
|
||||||
|
wlWm.fractionalScaleManager, wlWm.surface);
|
||||||
|
wp_fractional_scale_v1_add_listener(wlWm.fractionalScaleInterface,
|
||||||
|
&fractionalScaleListener, NULL);
|
||||||
|
}
|
||||||
|
else
|
||||||
wl_surface_add_listener(wlWm.surface, &wlSurfaceListener, NULL);
|
wl_surface_add_listener(wlWm.surface, &wlSurfaceListener, NULL);
|
||||||
|
|
||||||
|
if (wlWm.contentTypeManager)
|
||||||
|
{
|
||||||
|
wlWm.contentType = wp_content_type_manager_v1_get_surface_content_type(
|
||||||
|
wlWm.contentTypeManager, wlWm.surface);
|
||||||
|
wp_content_type_v1_set_content_type(wlWm.contentType, WP_CONTENT_TYPE_V1_TYPE_GAME);
|
||||||
|
}
|
||||||
|
|
||||||
if (!wlWm.desktop->shellInit(wlWm.display, wlWm.surface,
|
if (!wlWm.desktop->shellInit(wlWm.display, wlWm.surface,
|
||||||
title, appId, fullscreen, maximize, borderless, resizable))
|
title, appId, fullscreen, maximize, borderless, resizable))
|
||||||
return false;
|
return false;
|
||||||
@@ -122,6 +157,10 @@ bool waylandWindowInit(const char * title, const char * appId, bool fullscreen,
|
|||||||
|
|
||||||
void waylandWindowFree(void)
|
void waylandWindowFree(void)
|
||||||
{
|
{
|
||||||
|
if (wlWm.fractionalScaleInterface)
|
||||||
|
wp_fractional_scale_v1_destroy(wlWm.fractionalScaleInterface);
|
||||||
|
if (wlWm.contentType)
|
||||||
|
wp_content_type_v1_destroy(wlWm.contentType);
|
||||||
wl_surface_destroy(wlWm.surface);
|
wl_surface_destroy(wlWm.surface);
|
||||||
lgFreeEvent(wlWm.frameEvent);
|
lgFreeEvent(wlWm.frameEvent);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Looking Glass
|
* Looking Glass
|
||||||
* Copyright © 2017-2025 The Looking Glass Authors
|
* Copyright © 2017-2026 The Looking Glass Authors
|
||||||
* https://looking-glass.io
|
* https://looking-glass.io
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Looking Glass
|
* Looking Glass
|
||||||
* Copyright © 2017-2025 The Looking Glass Authors
|
* Copyright © 2017-2026 The Looking Glass Authors
|
||||||
* https://looking-glass.io
|
* https://looking-glass.io
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Looking Glass
|
* Looking Glass
|
||||||
* Copyright © 2017-2025 The Looking Glass Authors
|
* Copyright © 2017-2026 The Looking Glass Authors
|
||||||
* https://looking-glass.io
|
* https://looking-glass.io
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Looking Glass
|
* Looking Glass
|
||||||
* Copyright © 2017-2025 The Looking Glass Authors
|
* Copyright © 2017-2026 The Looking Glass Authors
|
||||||
* https://looking-glass.io
|
* https://looking-glass.io
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Looking Glass
|
* Looking Glass
|
||||||
* Copyright © 2017-2025 The Looking Glass Authors
|
* Copyright © 2017-2026 The Looking Glass Authors
|
||||||
* https://looking-glass.io
|
* https://looking-glass.io
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Looking Glass
|
* Looking Glass
|
||||||
* Copyright © 2017-2025 The Looking Glass Authors
|
* Copyright © 2017-2026 The Looking Glass Authors
|
||||||
* https://looking-glass.io
|
* https://looking-glass.io
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Looking Glass
|
* Looking Glass
|
||||||
* Copyright © 2017-2025 The Looking Glass Authors
|
* Copyright © 2017-2026 The Looking Glass Authors
|
||||||
* https://looking-glass.io
|
* https://looking-glass.io
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Looking Glass
|
* Looking Glass
|
||||||
* Copyright © 2017-2025 The Looking Glass Authors
|
* Copyright © 2017-2026 The Looking Glass Authors
|
||||||
* https://looking-glass.io
|
* https://looking-glass.io
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Looking Glass
|
* Looking Glass
|
||||||
* Copyright © 2017-2025 The Looking Glass Authors
|
* Copyright © 2017-2026 The Looking Glass Authors
|
||||||
* https://looking-glass.io
|
* https://looking-glass.io
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Looking Glass
|
* Looking Glass
|
||||||
* Copyright © 2017-2025 The Looking Glass Authors
|
* Copyright © 2017-2026 The Looking Glass Authors
|
||||||
* https://looking-glass.io
|
* https://looking-glass.io
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
@@ -1087,8 +1087,9 @@ static void setFocus(bool focused, double x, double y)
|
|||||||
app_handleFocusEvent(focused);
|
app_handleFocusEvent(focused);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int getCharcode(int detail)
|
static int x11GetCharCode(int detail)
|
||||||
{
|
{
|
||||||
|
detail += x11.minKeycode;
|
||||||
if (detail < x11.minKeycode || detail > x11.maxKeycode)
|
if (detail < x11.minKeycode || detail > x11.maxKeycode)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@@ -1229,8 +1230,7 @@ static void x11XInputEvent(XGenericEventCookie *cookie)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
XIDeviceEvent *device = cookie->data;
|
XIDeviceEvent *device = cookie->data;
|
||||||
app_handleKeyPress(device->detail - x11.minKeycode,
|
app_handleKeyPress(device->detail - x11.minKeycode);
|
||||||
getCharcode(device->detail));
|
|
||||||
|
|
||||||
if (!x11.xic || !app_isOverlayMode())
|
if (!x11.xic || !app_isOverlayMode())
|
||||||
return;
|
return;
|
||||||
@@ -1280,8 +1280,7 @@ static void x11XInputEvent(XGenericEventCookie *cookie)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
XIDeviceEvent *device = cookie->data;
|
XIDeviceEvent *device = cookie->data;
|
||||||
app_handleKeyRelease(device->detail - x11.minKeycode,
|
app_handleKeyRelease(device->detail - x11.minKeycode);
|
||||||
getCharcode(device->detail));
|
|
||||||
|
|
||||||
if (!x11.xic || !app_isOverlayMode())
|
if (!x11.xic || !app_isOverlayMode())
|
||||||
return;
|
return;
|
||||||
@@ -1310,8 +1309,7 @@ static void x11XInputEvent(XGenericEventCookie *cookie)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
XIRawEvent *raw = cookie->data;
|
XIRawEvent *raw = cookie->data;
|
||||||
app_handleKeyPress(raw->detail - x11.minKeycode,
|
app_handleKeyPress(raw->detail - x11.minKeycode);
|
||||||
getCharcode(raw->detail));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1321,8 +1319,7 @@ static void x11XInputEvent(XGenericEventCookie *cookie)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
XIRawEvent *raw = cookie->data;
|
XIRawEvent *raw = cookie->data;
|
||||||
app_handleKeyRelease(raw->detail - x11.minKeycode,
|
app_handleKeyRelease(raw->detail - x11.minKeycode);
|
||||||
getCharcode(raw->detail));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2017,6 +2014,7 @@ struct LG_DisplayServerOps LGDS_X11 =
|
|||||||
.ungrabPointer = x11UngrabPointer,
|
.ungrabPointer = x11UngrabPointer,
|
||||||
.capturePointer = x11CapturePointer,
|
.capturePointer = x11CapturePointer,
|
||||||
.uncapturePointer = x11UncapturePointer,
|
.uncapturePointer = x11UncapturePointer,
|
||||||
|
.getCharCode = x11GetCharCode,
|
||||||
.grabKeyboard = x11GrabKeyboard,
|
.grabKeyboard = x11GrabKeyboard,
|
||||||
.ungrabKeyboard = x11UngrabKeyboard,
|
.ungrabKeyboard = x11UngrabKeyboard,
|
||||||
.warpPointer = x11WarpPointer,
|
.warpPointer = x11WarpPointer,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Looking Glass
|
* Looking Glass
|
||||||
* Copyright © 2017-2025 The Looking Glass Authors
|
* Copyright © 2017-2026 The Looking Glass Authors
|
||||||
* https://looking-glass.io
|
* https://looking-glass.io
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Looking Glass
|
* Looking Glass
|
||||||
* Copyright © 2017-2025 The Looking Glass Authors
|
* Copyright © 2017-2026 The Looking Glass Authors
|
||||||
* https://looking-glass.io
|
* https://looking-glass.io
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
@@ -59,8 +59,8 @@ void app_handleButtonPress(int button);
|
|||||||
void app_handleButtonRelease(int button);
|
void app_handleButtonRelease(int button);
|
||||||
void app_handleWheelMotion(double motion);
|
void app_handleWheelMotion(double motion);
|
||||||
void app_handleKeyboardTyped(const char * typed);
|
void app_handleKeyboardTyped(const char * typed);
|
||||||
void app_handleKeyPress(int scancode, int charcode);
|
void app_handleKeyPress(int scancode);
|
||||||
void app_handleKeyRelease(int scancode, int charcode);
|
void app_handleKeyRelease(int scancode);
|
||||||
void app_handleKeyboardModifiers(bool ctrl, bool shift, bool alt, bool super);
|
void app_handleKeyboardModifiers(bool ctrl, bool shift, bool alt, bool super);
|
||||||
void app_handleKeyboardLEDs(bool numLock, bool capsLock, bool scrollLock);
|
void app_handleKeyboardLEDs(bool numLock, bool capsLock, bool scrollLock);
|
||||||
void app_handleEnterEvent(bool entered);
|
void app_handleEnterEvent(bool entered);
|
||||||
@@ -72,6 +72,13 @@ void app_setFullscreen(bool fs);
|
|||||||
bool app_getFullscreen(void);
|
bool app_getFullscreen(void);
|
||||||
bool app_getProp(LG_DSProperty prop, void * ret);
|
bool app_getProp(LG_DSProperty prop, void * ret);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the last call to setHDRImageDescription() failed.
|
||||||
|
* When this returns true, the renderer should fall back to software
|
||||||
|
* tone-mapping even on a compositor that reports LG_DS_NATIVE_HDR.
|
||||||
|
*/
|
||||||
|
bool app_getHDRDescFailed(void);
|
||||||
|
|
||||||
#ifdef ENABLE_EGL
|
#ifdef ENABLE_EGL
|
||||||
EGLDisplay app_getEGLDisplay(void);
|
EGLDisplay app_getEGLDisplay(void);
|
||||||
EGLNativeWindowType app_getEGLNativeWindow(void);
|
EGLNativeWindowType app_getEGLNativeWindow(void);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Looking Glass
|
* Looking Glass
|
||||||
* Copyright © 2017-2025 The Looking Glass Authors
|
* Copyright © 2017-2026 The Looking Glass Authors
|
||||||
* https://looking-glass.io
|
* https://looking-glass.io
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Looking Glass
|
* Looking Glass
|
||||||
* Copyright © 2017-2025 The Looking Glass Authors
|
* Copyright © 2017-2026 The Looking Glass Authors
|
||||||
* https://looking-glass.io
|
* https://looking-glass.io
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
|||||||
51
client/include/evdev.h
Normal file
51
client/include/evdev.h
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
/**
|
||||||
|
* Looking Glass
|
||||||
|
* Copyright © 2017-2026 The Looking Glass Authors
|
||||||
|
* https://looking-glass.io
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the Free
|
||||||
|
* Software Foundation; either version 2 of the License, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc., 59
|
||||||
|
* Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* initialize configuration options
|
||||||
|
*/
|
||||||
|
void evdev_earlyInit(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* start the evdev layer
|
||||||
|
*/
|
||||||
|
bool evdev_start(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* stop the evdev layer
|
||||||
|
*/
|
||||||
|
void evdev_stop(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* grab the keyboard for exclusive access
|
||||||
|
*/
|
||||||
|
void evdev_grabKeyboard(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ungrab the keyboard
|
||||||
|
*/
|
||||||
|
void evdev_ungrabKeyboard(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* returns true if input should only be processed by evdev
|
||||||
|
*/
|
||||||
|
bool evdev_isExclusive(void);
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Looking Glass
|
* Looking Glass
|
||||||
* Copyright © 2017-2025 The Looking Glass Authors
|
* Copyright © 2017-2026 The Looking Glass Authors
|
||||||
* https://looking-glass.io
|
* https://looking-glass.io
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Looking Glass
|
* Looking Glass
|
||||||
* Copyright © 2017-2025 The Looking Glass Authors
|
* Copyright © 2017-2026 The Looking Glass Authors
|
||||||
* https://looking-glass.io
|
* https://looking-glass.io
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Looking Glass
|
* Looking Glass
|
||||||
* Copyright © 2017-2025 The Looking Glass Authors
|
* Copyright © 2017-2026 The Looking Glass Authors
|
||||||
* https://looking-glass.io
|
* https://looking-glass.io
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
@@ -53,6 +53,14 @@ typedef enum LG_DSProperty
|
|||||||
* return data type: bool
|
* return data type: bool
|
||||||
*/
|
*/
|
||||||
LG_DS_WARP_SUPPORT,
|
LG_DS_WARP_SUPPORT,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* returns true if the display server supports native HDR via
|
||||||
|
* setHDRImageDescription (i.e., the compositor actually has the
|
||||||
|
* required color-management features to process HDR content).
|
||||||
|
* return data type: bool
|
||||||
|
*/
|
||||||
|
LG_DS_NATIVE_HDR,
|
||||||
}
|
}
|
||||||
LG_DSProperty;
|
LG_DSProperty;
|
||||||
|
|
||||||
@@ -183,6 +191,9 @@ struct LG_DisplayServerOps
|
|||||||
void (*capturePointer)(void);
|
void (*capturePointer)(void);
|
||||||
void (*uncapturePointer)(void);
|
void (*uncapturePointer)(void);
|
||||||
|
|
||||||
|
/* get the character code for the provided scancode */
|
||||||
|
int (*getCharCode)(int sc);
|
||||||
|
|
||||||
/* exiting = true if the warp is to leave the window */
|
/* exiting = true if the warp is to leave the window */
|
||||||
void (*warpPointer)(int x, int y, bool exiting);
|
void (*warpPointer)(int x, int y, bool exiting);
|
||||||
|
|
||||||
@@ -210,6 +221,13 @@ struct LG_DisplayServerOps
|
|||||||
void (*setFullscreen)(bool fs);
|
void (*setFullscreen)(bool fs);
|
||||||
void (*minimize)(void);
|
void (*minimize)(void);
|
||||||
|
|
||||||
|
/* HDR color management - set display image description.
|
||||||
|
* Optional, if not supported set to NULL.
|
||||||
|
* Returns true on success, false if the description could not be applied
|
||||||
|
* (e.g., compositor doesn't support the required transfer function or
|
||||||
|
* primaries, or the image description creation failed). */
|
||||||
|
bool (*setHDRImageDescription)(const void * rendererFormat);
|
||||||
|
|
||||||
/* clipboard support, optional, if not supported set to NULL */
|
/* clipboard support, optional, if not supported set to NULL */
|
||||||
bool (*cbInit)(void);
|
bool (*cbInit)(void);
|
||||||
void (*cbNotice)(LG_ClipboardData type);
|
void (*cbNotice)(LG_ClipboardData type);
|
||||||
@@ -253,6 +271,7 @@ struct LG_DisplayServerOps
|
|||||||
DEBUG_ASSERT((x)->ungrabPointer ); \
|
DEBUG_ASSERT((x)->ungrabPointer ); \
|
||||||
DEBUG_ASSERT((x)->capturePointer ); \
|
DEBUG_ASSERT((x)->capturePointer ); \
|
||||||
DEBUG_ASSERT((x)->uncapturePointer ); \
|
DEBUG_ASSERT((x)->uncapturePointer ); \
|
||||||
|
DEBUG_ASSERT((x)->getCharCode ); \
|
||||||
DEBUG_ASSERT((x)->warpPointer ); \
|
DEBUG_ASSERT((x)->warpPointer ); \
|
||||||
DEBUG_ASSERT((x)->realignPointer ); \
|
DEBUG_ASSERT((x)->realignPointer ); \
|
||||||
DEBUG_ASSERT((x)->isValidPointerPos ); \
|
DEBUG_ASSERT((x)->isValidPointerPos ); \
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Looking Glass
|
* Looking Glass
|
||||||
* Copyright © 2017-2025 The Looking Glass Authors
|
* Copyright © 2017-2026 The Looking Glass Authors
|
||||||
* https://looking-glass.io
|
* https://looking-glass.io
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Looking Glass
|
* Looking Glass
|
||||||
* Copyright © 2017-2025 The Looking Glass Authors
|
* Copyright © 2017-2026 The Looking Glass Authors
|
||||||
* https://looking-glass.io
|
* https://looking-glass.io
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Looking Glass
|
* Looking Glass
|
||||||
* Copyright © 2017-2025 The Looking Glass Authors
|
* Copyright © 2017-2026 The Looking Glass Authors
|
||||||
* https://looking-glass.io
|
* https://looking-glass.io
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
@@ -84,6 +84,14 @@ typedef struct LG_RendererFormat
|
|||||||
unsigned int pitch; // scanline bytes (or compressed size)
|
unsigned int pitch; // scanline bytes (or compressed size)
|
||||||
unsigned int bpp; // bits per pixel (zero if compressed)
|
unsigned int bpp; // bits per pixel (zero if compressed)
|
||||||
LG_RendererRotate rotate; // guest rotation
|
LG_RendererRotate rotate; // guest rotation
|
||||||
|
|
||||||
|
// HDR static metadata (from KVMFRFrame, valid when hdr is true)
|
||||||
|
uint16_t hdrDisplayPrimary[3][2];
|
||||||
|
uint16_t hdrWhitePoint[2];
|
||||||
|
uint32_t hdrMaxDisplayLuminance;
|
||||||
|
uint32_t hdrMinDisplayLuminance;
|
||||||
|
uint32_t hdrMaxContentLightLevel;
|
||||||
|
uint32_t hdrMaxFrameAverageLightLevel;
|
||||||
}
|
}
|
||||||
LG_RendererFormat;
|
LG_RendererFormat;
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Looking Glass
|
* Looking Glass
|
||||||
* Copyright © 2017-2025 The Looking Glass Authors
|
* Copyright © 2017-2026 The Looking Glass Authors
|
||||||
* https://looking-glass.io
|
* https://looking-glass.io
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Looking Glass
|
* Looking Glass
|
||||||
* Copyright © 2017-2025 The Looking Glass Authors
|
* Copyright © 2017-2026 The Looking Glass Authors
|
||||||
* https://looking-glass.io
|
* https://looking-glass.io
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Looking Glass
|
* Looking Glass
|
||||||
* Copyright © 2017-2025 The Looking Glass Authors
|
* Copyright © 2017-2026 The Looking Glass Authors
|
||||||
* https://looking-glass.io
|
* https://looking-glass.io
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Looking Glass
|
* Looking Glass
|
||||||
* Copyright © 2017-2025 The Looking Glass Authors
|
* Copyright © 2017-2026 The Looking Glass Authors
|
||||||
* https://looking-glass.io
|
* https://looking-glass.io
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Looking Glass
|
* Looking Glass
|
||||||
* Copyright © 2017-2025 The Looking Glass Authors
|
* Copyright © 2017-2026 The Looking Glass Authors
|
||||||
* https://looking-glass.io
|
* https://looking-glass.io
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Looking Glass
|
* Looking Glass
|
||||||
* Copyright © 2017-2025 The Looking Glass Authors
|
* Copyright © 2017-2026 The Looking Glass Authors
|
||||||
* https://looking-glass.io
|
* https://looking-glass.io
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Looking Glass
|
* Looking Glass
|
||||||
* Copyright © 2017-2025 The Looking Glass Authors
|
* Copyright © 2017-2026 The Looking Glass Authors
|
||||||
* https://looking-glass.io
|
* https://looking-glass.io
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
@@ -91,6 +91,7 @@ struct EGL_Desktop
|
|||||||
|
|
||||||
// map HDR content to SDR
|
// map HDR content to SDR
|
||||||
bool mapHDRtoSDR;
|
bool mapHDRtoSDR;
|
||||||
|
bool nativeHDR;
|
||||||
int peakLuminance;
|
int peakLuminance;
|
||||||
int maxCLL;
|
int maxCLL;
|
||||||
|
|
||||||
@@ -479,6 +480,13 @@ bool egl_desktopRender(EGL_Desktop * desktop, unsigned int outputWidth,
|
|||||||
EGL_Texture * texture = egl_postProcessGetOutput(desktop->pp,
|
EGL_Texture * texture = egl_postProcessGetOutput(desktop->pp,
|
||||||
&finalSizeX, &finalSizeY);
|
&finalSizeX, &finalSizeY);
|
||||||
|
|
||||||
|
if (unlikely(!texture))
|
||||||
|
{
|
||||||
|
texture = tex;
|
||||||
|
finalSizeX = width;
|
||||||
|
finalSizeY = height;
|
||||||
|
}
|
||||||
|
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
egl_resetViewport(desktop->egl);
|
egl_resetViewport(desktop->egl);
|
||||||
|
|
||||||
@@ -541,7 +549,7 @@ bool egl_desktopRender(EGL_Desktop * desktop, unsigned int outputWidth,
|
|||||||
{
|
{
|
||||||
.type = EGL_UNIFORM_TYPE_1I,
|
.type = EGL_UNIFORM_TYPE_1I,
|
||||||
.location = shader->uCBMode,
|
.location = shader->uCBMode,
|
||||||
.f = { desktop->cbMode }
|
.i = { desktop->cbMode }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.type = EGL_UNIFORM_TYPE_1I,
|
.type = EGL_UNIFORM_TYPE_1I,
|
||||||
@@ -551,7 +559,7 @@ bool egl_desktopRender(EGL_Desktop * desktop, unsigned int outputWidth,
|
|||||||
{
|
{
|
||||||
.type = EGL_UNIFORM_TYPE_1I,
|
.type = EGL_UNIFORM_TYPE_1I,
|
||||||
.location = shader->uMapHDRtoSDR,
|
.location = shader->uMapHDRtoSDR,
|
||||||
.i = { desktop->mapHDRtoSDR }
|
.i = { desktop->mapHDRtoSDR && !desktop->nativeHDR }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.type = EGL_UNIFORM_TYPE_1F,
|
.type = EGL_UNIFORM_TYPE_1F,
|
||||||
@@ -561,7 +569,7 @@ bool egl_desktopRender(EGL_Desktop * desktop, unsigned int outputWidth,
|
|||||||
{
|
{
|
||||||
.type = EGL_UNIFORM_TYPE_1I,
|
.type = EGL_UNIFORM_TYPE_1I,
|
||||||
.location = shader->uMapHDRPQ,
|
.location = shader->uMapHDRPQ,
|
||||||
.f = { desktop->hdrPQ }
|
.i = { desktop->hdrPQ }
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -572,6 +580,11 @@ bool egl_desktopRender(EGL_Desktop * desktop, unsigned int outputWidth,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void egl_desktopSetNativeHDR(EGL_Desktop * desktop, bool nativeHDR)
|
||||||
|
{
|
||||||
|
desktop->nativeHDR = nativeHDR;
|
||||||
|
}
|
||||||
|
|
||||||
void egl_desktopSpiceConfigure(EGL_Desktop * desktop, int width, int height)
|
void egl_desktopSpiceConfigure(EGL_Desktop * desktop, int width, int height)
|
||||||
{
|
{
|
||||||
if (!desktop->spiceTexture)
|
if (!desktop->spiceTexture)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Looking Glass
|
* Looking Glass
|
||||||
* Copyright © 2017-2025 The Looking Glass Authors
|
* Copyright © 2017-2026 The Looking Glass Authors
|
||||||
* https://looking-glass.io
|
* https://looking-glass.io
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
@@ -42,6 +42,7 @@ bool egl_desktopInit(EGL * egl, EGL_Desktop ** desktop, EGLDisplay * display,
|
|||||||
void egl_desktopFree(EGL_Desktop ** desktop);
|
void egl_desktopFree(EGL_Desktop ** desktop);
|
||||||
|
|
||||||
void egl_desktopConfigUI(EGL_Desktop * desktop);
|
void egl_desktopConfigUI(EGL_Desktop * desktop);
|
||||||
|
void egl_desktopSetNativeHDR(EGL_Desktop * desktop, bool nativeHDR);
|
||||||
bool egl_desktopSetup (EGL_Desktop * desktop, const LG_RendererFormat format);
|
bool egl_desktopSetup (EGL_Desktop * desktop, const LG_RendererFormat format);
|
||||||
bool egl_desktopUpdate(EGL_Desktop * desktop, const FrameBuffer * frame, int dmaFd,
|
bool egl_desktopUpdate(EGL_Desktop * desktop, const FrameBuffer * frame, int dmaFd,
|
||||||
const FrameDamageRect * damageRects, int damageRectsCount);
|
const FrameDamageRect * damageRects, int damageRectsCount);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Looking Glass
|
* Looking Glass
|
||||||
* Copyright © 2017-2025 The Looking Glass Authors
|
* Copyright © 2017-2026 The Looking Glass Authors
|
||||||
* https://looking-glass.io
|
* https://looking-glass.io
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Looking Glass
|
* Looking Glass
|
||||||
* Copyright © 2017-2025 The Looking Glass Authors
|
* Copyright © 2017-2026 The Looking Glass Authors
|
||||||
* https://looking-glass.io
|
* https://looking-glass.io
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Looking Glass
|
* Looking Glass
|
||||||
* Copyright © 2017-2025 The Looking Glass Authors
|
* Copyright © 2017-2026 The Looking Glass Authors
|
||||||
* https://looking-glass.io
|
* https://looking-glass.io
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
@@ -121,6 +121,9 @@ struct Inst
|
|||||||
|
|
||||||
bool showSpice;
|
bool showSpice;
|
||||||
int spiceWidth, spiceHeight;
|
int spiceWidth, spiceHeight;
|
||||||
|
|
||||||
|
bool configSupportsHDR; // true if we probed FP16 or 10-bit EGL config
|
||||||
|
bool hdr; // true if current frame format is HDR
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct Option egl_options[] =
|
static struct Option egl_options[] =
|
||||||
@@ -607,6 +610,26 @@ static bool egl_onFrameFormat(LG_Renderer * renderer, const LG_RendererFormat fo
|
|||||||
egl_cursorSetScale(this->cursor, scale);
|
egl_cursorSetScale(this->cursor, scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Track HDR state and warn if HDR frames arrive without any HDR path
|
||||||
|
this->hdr = format.hdr;
|
||||||
|
if (format.hdr)
|
||||||
|
{
|
||||||
|
bool nativeHDR = false;
|
||||||
|
app_getProp(LG_DS_NATIVE_HDR, &nativeHDR);
|
||||||
|
if (!this->configSupportsHDR && !nativeHDR)
|
||||||
|
DEBUG_WARN("HDR frames being displayed on an 8-bit EGL surface "
|
||||||
|
"without a color-managed compositor; tones may be incorrect");
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the display server supports native HDR (via setHDRImageDescription),
|
||||||
|
// disable software tone-mapping to avoid double tone-mapping.
|
||||||
|
// However, if the last call to setHDRImageDescription actually failed
|
||||||
|
// (e.g., compositor missing required primaries), keep tone-mapping on.
|
||||||
|
bool nativeHDR = false;
|
||||||
|
app_getProp(LG_DS_NATIVE_HDR, &nativeHDR);
|
||||||
|
egl_desktopSetNativeHDR(this->desktop,
|
||||||
|
format.hdr && nativeHDR && !app_getHDRDescFailed());
|
||||||
|
|
||||||
egl_update_scale_type(this);
|
egl_update_scale_type(this);
|
||||||
egl_damageSetup(this->damage, format.frameWidth, format.frameHeight);
|
egl_damageSetup(this->damage, format.frameWidth, format.frameHeight);
|
||||||
|
|
||||||
@@ -774,22 +797,51 @@ static bool egl_renderStartup(LG_Renderer * renderer, bool useDMA)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Probe for best available color depth: FP16 → 10-bit → 8-bit
|
||||||
|
static const struct { EGLint r, g, b, a, depth; const char * desc; } configs[] =
|
||||||
|
{
|
||||||
|
{ 16, 16, 16, 0, 48, "FP16 (RGBA16F)" },
|
||||||
|
{ 10, 10, 10, 2, 32, "10-bit (RGBA10)" },
|
||||||
|
{ 8, 8, 8, 0, 24, "8-bit (RGBA8)" },
|
||||||
|
};
|
||||||
|
EGLint num_config;
|
||||||
|
const char * configDesc = NULL;
|
||||||
|
int chosen = -1;
|
||||||
|
|
||||||
|
for (int i = 0; i < (int)(sizeof(configs) / sizeof(configs[0])); ++i)
|
||||||
|
{
|
||||||
EGLint attr[] =
|
EGLint attr[] =
|
||||||
{
|
{
|
||||||
EGL_BUFFER_SIZE , 30,
|
EGL_RED_SIZE , configs[i].r,
|
||||||
|
EGL_GREEN_SIZE , configs[i].g,
|
||||||
|
EGL_BLUE_SIZE , configs[i].b,
|
||||||
|
EGL_ALPHA_SIZE , configs[i].a,
|
||||||
|
EGL_BUFFER_SIZE , configs[i].depth,
|
||||||
EGL_RENDERABLE_TYPE , EGL_OPENGL_ES2_BIT,
|
EGL_RENDERABLE_TYPE , EGL_OPENGL_ES2_BIT,
|
||||||
EGL_SAMPLE_BUFFERS , maxSamples > 0 ? 1 : 0,
|
EGL_SAMPLE_BUFFERS , maxSamples > 0 ? 1 : 0,
|
||||||
EGL_SAMPLES , maxSamples,
|
EGL_SAMPLES , maxSamples,
|
||||||
EGL_NONE
|
EGL_NONE
|
||||||
};
|
};
|
||||||
|
|
||||||
EGLint num_config;
|
if (eglChooseConfig(this->display, attr, &this->configs, 1, &num_config) &&
|
||||||
if (!eglChooseConfig(this->display, attr, &this->configs, 1, &num_config))
|
num_config > 0)
|
||||||
{
|
{
|
||||||
DEBUG_ERROR("Failed to choose config (eglError: 0x%x)", eglGetError());
|
configDesc = configs[i].desc;
|
||||||
|
chosen = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (chosen < 0)
|
||||||
|
{
|
||||||
|
DEBUG_ERROR("Failed to choose any EGL config");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this->configSupportsHDR = chosen <= 1; // FP16 or 10-bit
|
||||||
|
DEBUG_INFO("EGL config: %s%s", configDesc,
|
||||||
|
this->configSupportsHDR ? " (HDR capable)" : "");
|
||||||
|
|
||||||
const EGLint surfattr[] =
|
const EGLint surfattr[] =
|
||||||
{
|
{
|
||||||
EGL_RENDER_BUFFER, this->opt.doubleBuffer ? EGL_BACK_BUFFER : EGL_SINGLE_BUFFER,
|
EGL_RENDER_BUFFER, this->opt.doubleBuffer ? EGL_BACK_BUFFER : EGL_SINGLE_BUFFER,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Looking Glass
|
* Looking Glass
|
||||||
* Copyright © 2017-2025 The Looking Glass Authors
|
* Copyright © 2017-2026 The Looking Glass Authors
|
||||||
* https://looking-glass.io
|
* https://looking-glass.io
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Looking Glass
|
* Looking Glass
|
||||||
* Copyright © 2017-2025 The Looking Glass Authors
|
* Copyright © 2017-2026 The Looking Glass Authors
|
||||||
* https://looking-glass.io
|
* https://looking-glass.io
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Looking Glass
|
* Looking Glass
|
||||||
* Copyright © 2017-2025 The Looking Glass Authors
|
* Copyright © 2017-2026 The Looking Glass Authors
|
||||||
* https://looking-glass.io
|
* https://looking-glass.io
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Looking Glass
|
* Looking Glass
|
||||||
* Copyright © 2017-2025 The Looking Glass Authors
|
* Copyright © 2017-2026 The Looking Glass Authors
|
||||||
* https://looking-glass.io
|
* https://looking-glass.io
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Looking Glass
|
* Looking Glass
|
||||||
* Copyright © 2017-2025 The Looking Glass Authors
|
* Copyright © 2017-2026 The Looking Glass Authors
|
||||||
* https://looking-glass.io
|
* https://looking-glass.io
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Looking Glass
|
* Looking Glass
|
||||||
* Copyright © 2017-2025 The Looking Glass Authors
|
* Copyright © 2017-2026 The Looking Glass Authors
|
||||||
* https://looking-glass.io
|
* https://looking-glass.io
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Looking Glass
|
* Looking Glass
|
||||||
* Copyright © 2017-2025 The Looking Glass Authors
|
* Copyright © 2017-2026 The Looking Glass Authors
|
||||||
* https://looking-glass.io
|
* https://looking-glass.io
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Looking Glass
|
* Looking Glass
|
||||||
* Copyright © 2017-2025 The Looking Glass Authors
|
* Copyright © 2017-2026 The Looking Glass Authors
|
||||||
* https://looking-glass.io
|
* https://looking-glass.io
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Looking Glass
|
* Looking Glass
|
||||||
* Copyright © 2017-2025 The Looking Glass Authors
|
* Copyright © 2017-2026 The Looking Glass Authors
|
||||||
* https://looking-glass.io
|
* https://looking-glass.io
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Looking Glass
|
* Looking Glass
|
||||||
* Copyright © 2017-2025 The Looking Glass Authors
|
* Copyright © 2017-2026 The Looking Glass Authors
|
||||||
* https://looking-glass.io
|
* https://looking-glass.io
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Looking Glass
|
* Looking Glass
|
||||||
* Copyright © 2017-2025 The Looking Glass Authors
|
* Copyright © 2017-2026 The Looking Glass Authors
|
||||||
* https://looking-glass.io
|
* https://looking-glass.io
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Looking Glass
|
* Looking Glass
|
||||||
* Copyright © 2017-2025 The Looking Glass Authors
|
* Copyright © 2017-2026 The Looking Glass Authors
|
||||||
* https://looking-glass.io
|
* https://looking-glass.io
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Looking Glass
|
* Looking Glass
|
||||||
* Copyright © 2017-2025 The Looking Glass Authors
|
* Copyright © 2017-2026 The Looking Glass Authors
|
||||||
* https://looking-glass.io
|
* https://looking-glass.io
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Looking Glass
|
* Looking Glass
|
||||||
* Copyright © 2017-2025 The Looking Glass Authors
|
* Copyright © 2017-2026 The Looking Glass Authors
|
||||||
* https://looking-glass.io
|
* https://looking-glass.io
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Looking Glass
|
* Looking Glass
|
||||||
* Copyright © 2017-2025 The Looking Glass Authors
|
* Copyright © 2017-2026 The Looking Glass Authors
|
||||||
* https://looking-glass.io
|
* https://looking-glass.io
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Looking Glass
|
* Looking Glass
|
||||||
* Copyright © 2017-2025 The Looking Glass Authors
|
* Copyright © 2017-2026 The Looking Glass Authors
|
||||||
* https://looking-glass.io
|
* https://looking-glass.io
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Looking Glass
|
* Looking Glass
|
||||||
* Copyright © 2017-2025 The Looking Glass Authors
|
* Copyright © 2017-2026 The Looking Glass Authors
|
||||||
* https://looking-glass.io
|
* https://looking-glass.io
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Looking Glass
|
* Looking Glass
|
||||||
* Copyright © 2017-2025 The Looking Glass Authors
|
* Copyright © 2017-2026 The Looking Glass Authors
|
||||||
* https://looking-glass.io
|
* https://looking-glass.io
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Looking Glass
|
* Looking Glass
|
||||||
* Copyright © 2017-2025 The Looking Glass Authors
|
* Copyright © 2017-2026 The Looking Glass Authors
|
||||||
* https://looking-glass.io
|
* https://looking-glass.io
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Looking Glass
|
* Looking Glass
|
||||||
* Copyright © 2017-2025 The Looking Glass Authors
|
* Copyright © 2017-2026 The Looking Glass Authors
|
||||||
* https://looking-glass.io
|
* https://looking-glass.io
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Looking Glass
|
* Looking Glass
|
||||||
* Copyright © 2017-2025 The Looking Glass Authors
|
* Copyright © 2017-2026 The Looking Glass Authors
|
||||||
* https://looking-glass.io
|
* https://looking-glass.io
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#extension GL_OES_EGL_image_external_essl3 : enable
|
#extension GL_OES_EGL_image_external_essl3 : enable
|
||||||
|
|
||||||
precision highp float;
|
precision highp float;
|
||||||
|
precision highp int;
|
||||||
|
|
||||||
in vec2 fragCoord;
|
in vec2 fragCoord;
|
||||||
out vec4 fragColor;
|
out vec4 fragColor;
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#version 300 es
|
#version 300 es
|
||||||
precision highp float;
|
precision highp float;
|
||||||
|
precision highp int;
|
||||||
|
|
||||||
in vec2 uv;
|
in vec2 uv;
|
||||||
out vec4 color;
|
out vec4 color;
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#version 300 es
|
#version 300 es
|
||||||
precision highp float;
|
precision highp float;
|
||||||
|
precision highp int;
|
||||||
|
|
||||||
#include "color_blind.h"
|
#include "color_blind.h"
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#version 300 es
|
#version 300 es
|
||||||
precision highp float;
|
precision highp float;
|
||||||
|
precision highp int;
|
||||||
|
|
||||||
out vec4 color;
|
out vec4 color;
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#extension GL_OES_EGL_image_external_essl3 : enable
|
#extension GL_OES_EGL_image_external_essl3 : enable
|
||||||
|
|
||||||
precision highp float;
|
precision highp float;
|
||||||
|
precision highp int;
|
||||||
|
|
||||||
#define EGL_SCALE_AUTO 0
|
#define EGL_SCALE_AUTO 0
|
||||||
#define EGL_SCALE_NEAREST 1
|
#define EGL_SCALE_NEAREST 1
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#extension GL_OES_EGL_image_external_essl3 : enable
|
#extension GL_OES_EGL_image_external_essl3 : enable
|
||||||
|
|
||||||
precision highp float;
|
precision highp float;
|
||||||
|
precision highp int;
|
||||||
|
|
||||||
in vec2 fragCoord;
|
in vec2 fragCoord;
|
||||||
out vec4 fragColor;
|
out vec4 fragColor;
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#extension GL_OES_EGL_image_external_essl3 : enable
|
#extension GL_OES_EGL_image_external_essl3 : enable
|
||||||
|
|
||||||
precision highp float;
|
precision highp float;
|
||||||
|
precision highp int;
|
||||||
|
|
||||||
#define PI 3.141592653589793
|
#define PI 3.141592653589793
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#extension GL_OES_EGL_image_external_essl3 : enable
|
#extension GL_OES_EGL_image_external_essl3 : enable
|
||||||
|
|
||||||
precision highp float;
|
precision highp float;
|
||||||
|
precision highp int;
|
||||||
|
|
||||||
in vec2 fragCoord;
|
in vec2 fragCoord;
|
||||||
out vec4 fragColor;
|
out vec4 fragColor;
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#extension GL_OES_EGL_image_external_essl3 : enable
|
#extension GL_OES_EGL_image_external_essl3 : enable
|
||||||
|
|
||||||
precision highp float;
|
precision highp float;
|
||||||
|
precision highp int;
|
||||||
|
|
||||||
#include "compat.h"
|
#include "compat.h"
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#extension GL_OES_EGL_image_external_essl3 : enable
|
#extension GL_OES_EGL_image_external_essl3 : enable
|
||||||
|
|
||||||
precision highp float;
|
precision highp float;
|
||||||
|
precision highp int;
|
||||||
|
|
||||||
#include "compat.h"
|
#include "compat.h"
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#version 300 es
|
#version 300 es
|
||||||
precision highp float;
|
precision highp float;
|
||||||
|
precision highp int;
|
||||||
|
|
||||||
#include "compat.h"
|
#include "compat.h"
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Looking Glass
|
* Looking Glass
|
||||||
* Copyright © 2017-2025 The Looking Glass Authors
|
* Copyright © 2017-2026 The Looking Glass Authors
|
||||||
* https://looking-glass.io
|
* https://looking-glass.io
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Looking Glass
|
* Looking Glass
|
||||||
* Copyright © 2017-2025 The Looking Glass Authors
|
* Copyright © 2017-2026 The Looking Glass Authors
|
||||||
* https://looking-glass.io
|
* https://looking-glass.io
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Looking Glass
|
* Looking Glass
|
||||||
* Copyright © 2017-2025 The Looking Glass Authors
|
* Copyright © 2017-2026 The Looking Glass Authors
|
||||||
* https://looking-glass.io
|
* https://looking-glass.io
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
@@ -255,7 +255,6 @@ EGL_TexStatus egl_texBufferStreamProcess(EGL_Texture * texture)
|
|||||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
||||||
|
|
||||||
this->sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
|
this->sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
|
||||||
glFlush();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return EGL_TEX_STATUS_OK;
|
return EGL_TEX_STATUS_OK;
|
||||||
@@ -271,7 +270,8 @@ EGL_TexStatus egl_texBufferStreamGet(EGL_Texture * texture, GLuint * tex,
|
|||||||
|
|
||||||
if (this->sync)
|
if (this->sync)
|
||||||
{
|
{
|
||||||
switch(glClientWaitSync(this->sync, 0, 40000000)) // 40ms
|
switch(glClientWaitSync(
|
||||||
|
this->sync, GL_SYNC_FLUSH_COMMANDS_BIT, 40000000)) //40ms
|
||||||
{
|
{
|
||||||
case GL_ALREADY_SIGNALED:
|
case GL_ALREADY_SIGNALED:
|
||||||
case GL_CONDITION_SATISFIED:
|
case GL_CONDITION_SATISFIED:
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Looking Glass
|
* Looking Glass
|
||||||
* Copyright © 2017-2025 The Looking Glass Authors
|
* Copyright © 2017-2026 The Looking Glass Authors
|
||||||
* https://looking-glass.io
|
* https://looking-glass.io
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Looking Glass
|
* Looking Glass
|
||||||
* Copyright © 2017-2025 The Looking Glass Authors
|
* Copyright © 2017-2026 The Looking Glass Authors
|
||||||
* https://looking-glass.io
|
* https://looking-glass.io
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
#include "texture_buffer.h"
|
#include "texture_buffer.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
#include "common/vector.h"
|
#include "common/array.h"
|
||||||
#include "egl_dynprocs.h"
|
#include "egl_dynprocs.h"
|
||||||
#include "egldebug.h"
|
#include "egldebug.h"
|
||||||
|
|
||||||
@@ -30,6 +30,8 @@ struct FdImage
|
|||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
EGLImage image;
|
EGLImage image;
|
||||||
|
GLsync sync;
|
||||||
|
int texIndex;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct TexDMABUF
|
typedef struct TexDMABUF
|
||||||
@@ -37,7 +39,9 @@ typedef struct TexDMABUF
|
|||||||
TextureBuffer base;
|
TextureBuffer base;
|
||||||
|
|
||||||
EGLDisplay display;
|
EGLDisplay display;
|
||||||
Vector images;
|
|
||||||
|
struct FdImage images[2];
|
||||||
|
int lastIndex;
|
||||||
|
|
||||||
EGL_PixelFormat pixFmt;
|
EGL_PixelFormat pixFmt;
|
||||||
unsigned fourcc;
|
unsigned fourcc;
|
||||||
@@ -59,21 +63,26 @@ static void egl_texDMABUFCleanup(EGL_Texture * texture)
|
|||||||
TextureBuffer * parent = UPCAST(TextureBuffer, texture);
|
TextureBuffer * parent = UPCAST(TextureBuffer, texture);
|
||||||
TexDMABUF * this = UPCAST(TexDMABUF , parent);
|
TexDMABUF * this = UPCAST(TexDMABUF , parent);
|
||||||
|
|
||||||
struct FdImage * image;
|
for(int i = 0; i < ARRAY_LENGTH(this->images); ++i)
|
||||||
vector_forEachRef(image, &this->images)
|
{
|
||||||
g_egl_dynProcs.eglDestroyImage(this->display, image->image);
|
if (this->images[i].image != EGL_NO_IMAGE)
|
||||||
vector_clear(&this->images);
|
{
|
||||||
|
g_egl_dynProcs.eglDestroyImage(this->display, this->images[i].image);
|
||||||
|
this->images[i].image = EGL_NO_IMAGE;
|
||||||
|
}
|
||||||
|
if (this->images[i].sync)
|
||||||
|
{
|
||||||
|
glDeleteSync(this->images[i].sync);
|
||||||
|
this->images[i].sync = 0;
|
||||||
|
}
|
||||||
|
this->images[i].fd = -1;
|
||||||
|
this->images[i].texIndex = -1;
|
||||||
|
}
|
||||||
|
|
||||||
egl_texUtilFreeBuffers(parent->buf, parent->texCount);
|
egl_texUtilFreeBuffers(parent->buf, parent->texCount);
|
||||||
|
|
||||||
if (parent->tex[0])
|
if (parent->tex[0])
|
||||||
glDeleteTextures(parent->texCount, parent->tex);
|
glDeleteTextures(parent->texCount, parent->tex);
|
||||||
|
|
||||||
if (parent->sync)
|
|
||||||
{
|
|
||||||
glDeleteSync(parent->sync);
|
|
||||||
parent->sync = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// dmabuf functions
|
// dmabuf functions
|
||||||
@@ -84,17 +93,18 @@ static bool egl_texDMABUFInit(EGL_Texture ** texture, EGL_TexType type,
|
|||||||
TexDMABUF * this = calloc(1, sizeof(*this));
|
TexDMABUF * this = calloc(1, sizeof(*this));
|
||||||
*texture = &this->base.base;
|
*texture = &this->base.base;
|
||||||
|
|
||||||
if (!vector_create(&this->images, sizeof(struct FdImage), 2))
|
for(int i = 0; i < ARRAY_LENGTH(this->images); ++i)
|
||||||
{
|
{
|
||||||
free(this);
|
this->images[i].fd = -1;
|
||||||
*texture = NULL;
|
this->images[i].image = EGL_NO_IMAGE;
|
||||||
return false;
|
this->images[i].sync = 0;
|
||||||
|
this->images[i].texIndex = -1;
|
||||||
}
|
}
|
||||||
|
this->lastIndex = -1;
|
||||||
|
|
||||||
EGL_Texture * parent = &this->base.base;
|
EGL_Texture * parent = &this->base.base;
|
||||||
if (!egl_texBufferStreamInit(&parent, type, display))
|
if (!egl_texBufferStreamInit(&parent, type, display))
|
||||||
{
|
{
|
||||||
vector_destroy(&this->images);
|
|
||||||
free(this);
|
free(this);
|
||||||
*texture = NULL;
|
*texture = NULL;
|
||||||
return false;
|
return false;
|
||||||
@@ -119,8 +129,6 @@ static void egl_texDMABUFFree(EGL_Texture * texture)
|
|||||||
TexDMABUF * this = UPCAST(TexDMABUF , parent);
|
TexDMABUF * this = UPCAST(TexDMABUF , parent);
|
||||||
|
|
||||||
egl_texDMABUFCleanup(texture);
|
egl_texDMABUFCleanup(texture);
|
||||||
vector_destroy(&this->images);
|
|
||||||
|
|
||||||
egl_texBufferFree(&parent->base);
|
egl_texBufferFree(&parent->base);
|
||||||
free(this);
|
free(this);
|
||||||
}
|
}
|
||||||
@@ -141,22 +149,8 @@ static bool texDMABUFSetup(EGL_Texture * texture)
|
|||||||
egl_texDMABUFCleanup(texture);
|
egl_texDMABUFCleanup(texture);
|
||||||
|
|
||||||
glGenTextures(parent->texCount, parent->tex);
|
glGenTextures(parent->texCount, parent->tex);
|
||||||
for(int i = 0; i < parent->texCount; ++i)
|
|
||||||
{
|
|
||||||
glBindTexture(GL_TEXTURE_EXTERNAL_OES, parent->tex[i]);
|
|
||||||
glTexImage2D(GL_TEXTURE_EXTERNAL_OES,
|
|
||||||
0,
|
|
||||||
texture->format.intFormat,
|
|
||||||
this->width,
|
|
||||||
texture->format.height,
|
|
||||||
0,
|
|
||||||
this->format,
|
|
||||||
texture->format.dataType,
|
|
||||||
NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_EXTERNAL_OES, 0);
|
|
||||||
parent->rIndex = -1;
|
parent->rIndex = -1;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -212,16 +206,12 @@ static bool egl_texDMABUFUpdate(EGL_Texture * texture,
|
|||||||
|
|
||||||
DEBUG_ASSERT(update->type == EGL_TEXTYPE_DMABUF);
|
DEBUG_ASSERT(update->type == EGL_TEXTYPE_DMABUF);
|
||||||
|
|
||||||
EGLImage image = EGL_NO_IMAGE;
|
struct FdImage *fdImage =
|
||||||
|
(this->images[0].fd == update->dmaFD) ? &this->images[0] :
|
||||||
struct FdImage * fdImage;
|
(this->images[1].fd == update->dmaFD) ? &this->images[1] :
|
||||||
vector_forEachRef(fdImage, &this->images)
|
(this->images[0].fd == -1) ? &this->images[0] :
|
||||||
if (fdImage->fd == update->dmaFD)
|
&this->images[1];
|
||||||
{
|
EGLImage image = fdImage->image;
|
||||||
image = fdImage->image;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (unlikely(image == EGL_NO_IMAGE))
|
if (unlikely(image == EGL_NO_IMAGE))
|
||||||
{
|
{
|
||||||
bool setup = false;
|
bool setup = false;
|
||||||
@@ -248,28 +238,31 @@ static bool egl_texDMABUFUpdate(EGL_Texture * texture,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (unlikely(!vector_push(&this->images, &(struct FdImage) {
|
fdImage->fd = update->dmaFD;
|
||||||
.fd = update->dmaFD,
|
fdImage->image = image;
|
||||||
.image = image,
|
|
||||||
})))
|
|
||||||
{
|
|
||||||
DEBUG_ERROR("Failed to store EGLImage");
|
|
||||||
g_egl_dynProcs.eglDestroyImage(this->display, image);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
int slot = (fdImage == &this->images[0]) ? 0 : 1;
|
||||||
|
fdImage->texIndex = slot;
|
||||||
INTERLOCKED_SECTION(parent->copyLock,
|
INTERLOCKED_SECTION(parent->copyLock,
|
||||||
{
|
{
|
||||||
glBindTexture(GL_TEXTURE_EXTERNAL_OES, parent->tex[parent->bufIndex]);
|
glBindTexture(GL_TEXTURE_EXTERNAL_OES, parent->tex[slot]);
|
||||||
g_egl_dynProcs.glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, image);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
if (likely(parent->sync))
|
glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
glDeleteSync(parent->sync);
|
glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
g_egl_dynProcs.glEGLImageTargetTexture2DOES(
|
||||||
parent->sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
|
GL_TEXTURE_EXTERNAL_OES, image);
|
||||||
});
|
});
|
||||||
glFlush();
|
}
|
||||||
|
|
||||||
|
this->lastIndex = (fdImage == &this->images[0]) ? 0 : 1;
|
||||||
|
INTERLOCKED_SECTION(parent->copyLock,
|
||||||
|
{
|
||||||
|
if (fdImage->sync)
|
||||||
|
glDeleteSync(fdImage->sync);
|
||||||
|
fdImage->sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
|
||||||
|
});
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -284,23 +277,22 @@ static EGL_TexStatus egl_texDMABUFGet(EGL_Texture * texture, GLuint * tex,
|
|||||||
TextureBuffer * parent = UPCAST(TextureBuffer, texture);
|
TextureBuffer * parent = UPCAST(TextureBuffer, texture);
|
||||||
TexDMABUF * this = UPCAST(TexDMABUF , parent);
|
TexDMABUF * this = UPCAST(TexDMABUF , parent);
|
||||||
|
|
||||||
|
if (unlikely(this->lastIndex < 0))
|
||||||
|
return EGL_TEX_STATUS_NOTREADY;
|
||||||
|
|
||||||
|
struct FdImage *cur = &this->images[this->lastIndex];
|
||||||
GLsync sync = 0;
|
GLsync sync = 0;
|
||||||
|
|
||||||
INTERLOCKED_SECTION(parent->copyLock,
|
INTERLOCKED_SECTION(parent->copyLock, {
|
||||||
{
|
if (cur->sync) {
|
||||||
if (parent->sync)
|
sync = cur->sync;
|
||||||
{
|
cur->sync = 0;
|
||||||
sync = parent->sync;
|
|
||||||
parent->sync = 0;
|
|
||||||
parent->rIndex = parent->bufIndex;
|
|
||||||
if (++parent->bufIndex == parent->texCount)
|
|
||||||
parent->bufIndex = 0;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (sync)
|
if (sync)
|
||||||
{
|
{
|
||||||
switch(glClientWaitSync(sync, 0, 20000000)) // 20ms
|
switch (glClientWaitSync(sync, GL_SYNC_FLUSH_COMMANDS_BIT, 20000000)) //20ms
|
||||||
{
|
{
|
||||||
case GL_ALREADY_SIGNALED:
|
case GL_ALREADY_SIGNALED:
|
||||||
case GL_CONDITION_SATISFIED:
|
case GL_CONDITION_SATISFIED:
|
||||||
@@ -308,10 +300,11 @@ static EGL_TexStatus egl_texDMABUFGet(EGL_Texture * texture, GLuint * tex,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case GL_TIMEOUT_EXPIRED:
|
case GL_TIMEOUT_EXPIRED:
|
||||||
|
// Put it back for next try
|
||||||
INTERLOCKED_SECTION(parent->copyLock,
|
INTERLOCKED_SECTION(parent->copyLock,
|
||||||
{
|
{
|
||||||
if (!parent->sync)
|
if (!cur->sync)
|
||||||
parent->sync = sync;
|
cur->sync = sync;
|
||||||
else
|
else
|
||||||
glDeleteSync(sync);
|
glDeleteSync(sync);
|
||||||
});
|
});
|
||||||
@@ -325,7 +318,7 @@ static EGL_TexStatus egl_texDMABUFGet(EGL_Texture * texture, GLuint * tex,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
*tex = parent->tex[parent->rIndex];
|
*tex = parent->tex[cur->texIndex];
|
||||||
|
|
||||||
if (fmt)
|
if (fmt)
|
||||||
*fmt = this->pixFmt;
|
*fmt = this->pixFmt;
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user