Compare commits

...

110 Commits

Author SHA1 Message Date
Geoffrey McRae
6625cd733a [client] main: log if the frame format is using PQ or not 2023-10-27 01:16:08 +11:00
Geoffrey McRae
b41840b010 [host] all: tell the client if HDR PQ is in use or not 2023-10-27 01:11:57 +11:00
Geoffrey McRae
2f36aaff5c [client] egl: prepare for DXGI HDR10 support 2023-10-27 01:03:22 +11:00
Geoffrey McRae
200b7b732c [host] dxgi: properly convert HDR16 to HDR10
DXGI doesn't take into account the SDRWhiteLevel that has already been
applied to the monitor when it converts to HDR10 which results in clipping.
This change set implements a HLSL shader to reverse this while at the same
time converting to HDR10.

This is still not perfect but far better then doing nothing.
2023-10-26 22:57:41 +11:00
Geoffrey McRae
eeea24ebfb [client] egl: invalidate the window when HDR settings are changed 2023-10-24 13:46:51 +11:00
Geoffrey McRae
54066094bd [github] workflow: use latest ubuntu for cross compile build 2023-10-22 19:56:21 +11:00
Geoffrey McRae
c5923b9b4d [host] dxgi: obtain HDR color space and monitor information 2023-10-22 17:38:42 +11:00
Geoffrey McRae
bde2eef175 [host] dxgi: fix format for HDR10 when it needs correcting 2023-10-22 04:01:51 +11:00
Geoffrey McRae
e0bdd869d6 [all] fix client build on linux 2023-10-22 04:00:44 +11:00
Geoffrey McRae
ccd0a0bcf9 [host] dxgi: use HDR10 instead of HDR16 to save bandwidth 2023-10-22 03:47:32 +11:00
Geoffrey McRae
742e41c2c3 [host] dxgi: fix HDR damage aware copy 2023-10-22 03:15:12 +11:00
Geoffrey McRae
3ed71a09f4 [common] all: implement strdup directly
Dr.Memory on Windows complains bitterly about invalid heap free as
it doesn't seem to be able to track this function's allocations. As
it's such a trivial function we can just implement it locally.
2023-10-22 02:25:25 +11:00
Geoffrey McRae
12d051d8c0 [host] nvfbc: do not try to init on non NVIDIA hardware 2023-10-22 01:46:57 +11:00
Geoffrey McRae
a6a6b8779a [host] nvfbc: fix use of initialized variable 2023-10-22 01:21:20 +11:00
Geoffrey McRae
ad65561511 [host] app: cleanup local variables during init. 2023-10-21 22:03:22 +11:00
Geoffrey McRae
6b65c7e339 [all] lgmp: update to fix memory leak on shutdown 2023-10-21 22:02:33 +11:00
Geoffrey McRae
646f5b1be8 [host] fix windows compilation with mingw clang 2023-10-21 22:02:02 +11:00
Geoffrey McRae
128a8938c6 [host] nvfbc: remove useless update of member 2023-10-20 22:12:42 +11:00
Geoffrey McRae
2e515657dd [all] update/add license headers 2023-10-20 15:36:34 +11:00
Geoffrey McRae
1cf8e8c846 [doc] add luminance to words 2023-10-20 15:34:35 +11:00
Geoffrey McRae
df5c648377 [client] egl: remove unit qualifier from label 2023-10-20 15:30:36 +11:00
Geoffrey McRae
78df2073ff [client] egl: make it possible to configure HDR to SDR mapping 2023-10-20 15:26:27 +11:00
Geoffrey McRae
844a37a276 [all] update LGMP to fix invalid index access bug 2023-10-20 14:21:11 +11:00
Geoffrey McRae
e658c2e0a2 [client] x11: change to a more visible "dot" cursor
This change alters the small square dot cursor to a more visible 16x16
cursor for X11. A new option `spice:largeDotCursor` can be set to use an
alternative 32x32 cursor for the vision impaired.
2023-09-13 21:54:31 +10:00
Geoffrey McRae
b2ec60d2dc [client/host] common: fix trim value bug reading the wrong variable 2023-09-13 21:54:31 +10:00
Zenithal
e6aa2b85a9 [module] AMD SEV support 2023-09-13 15:12:40 +10:00
Geoffrey McRae
a3045e0b4a [client] main: don't request activation just because we re-connected 2023-09-13 14:08:18 +10:00
Geoffrey McRae
9cadb64942 [client] main: make activation requests optional 2023-09-13 14:07:42 +10:00
Geoffrey McRae
82607a7d6f [client] x11: read the i3 IPC response 2023-09-12 02:03:24 +10:00
Geoffrey McRae
8d90c9c2a5 [doc] add new words to words.txt 2023-09-12 01:27:34 +10:00
Geoffrey McRae
24d4fce17c [client] x11: add support for i3 global full screen toggle
This commit adds an interface to the X11 display server code to support
various window manage specific features, such as in this case, the i3
global full screen toggle.

This feature specifically uses the i3 IPC to cause looking glass to go
full screen across all monitors if the new option `i3:globalFullScreen`
is enabled.
2023-09-12 01:19:06 +10:00
Geoffrey McRae
8dba4b6c0b [client] x11: fix cleanup if XIQueryVersion fails 2023-09-11 23:41:52 +10:00
Geoffrey McRae
193977895b [client] add new option input:captureOnFocus
This option allows the client to automatically enter capture mode if the
window is focused.

Closes #1088
2023-09-11 21:02:32 +10:00
Jonathan Rubenstein
219c73edbe [doc] faq.rst: Reword libdecor package installation
Also change package name to Debian
package libdecor-0-dev
2023-07-25 10:15:28 +10:00
Jonathan Rubenstein
6522920ea1 [doc] faq.rst: Update libdecor source link
Source code moved from https://gitlab.gnome.org/jadahl/libdecor
to https://gitlab.freedesktop.org/libdecor/libdecor
2023-07-25 10:15:28 +10:00
esi
e32b292cc1 [module] Fix build on Linux 6.4 (fixes #1075) 2023-06-30 07:29:15 +10:00
Netboy3
53525847fd [common] options: Fix regression in option parsing logic 2023-05-03 18:20:01 +10:00
Geoffrey McRae
9d66a68403 [common] options: fix build on windows (no strndup) 2023-05-02 12:32:59 +10:00
Geoffrey McRae
07bcc54732 [common] options: trim whitespace from option values
This closes #1071
2023-05-02 12:27:17 +10:00
Geoffrey McRae
dab5618a6d [host] linux: fix compilation 2023-04-26 16:31:02 +10:00
Geoffrey McRae
ad43969c1a [client] egl: add support to map HDR to SDR 2023-04-26 16:26:54 +10:00
Geoffrey McRae
99333a03c1 [host] nvfbc: fix failure to store last hdr state 2023-04-26 15:58:22 +10:00
Geoffrey McRae
45318aa653 [host] nvfbc: bump the format version when HDR status changes 2023-04-26 15:55:26 +10:00
Geoffrey McRae
f84165ac66 [host] app: report to the client if the frame is actually HDR 2023-04-26 15:48:01 +10:00
Geoffrey McRae
e4a8424fad [host] nvfbc: fix ARGB10 support
There is no performance penalty to using ARGB10 as it's still a 32-bit copy per
pixel and the nvidia driver internally handles any conversions required to make
this work for both SDR and HDR.
2023-04-19 19:52:30 +10:00
Geoffrey McRae
880d8042a4 [client] egl: fix support for deep color modes (30bpp) 2023-04-19 18:02:14 +10:00
Geoffrey McRae
a629d24dc3 [client] egl: fix fourcc for RGBA10 dmabuf 2023-04-19 17:30:40 +10:00
MakiseKurisu
7c1bb13d70 [all] add MakiseKurisu to AUTHORS 2023-04-16 19:50:35 +10:00
MakiseKurisu
9d5c543a53 [module] add logging for kvmfr_module_init 2023-04-16 19:50:35 +10:00
MakiseKurisu
063a859de1 [module] add logging for kvmfr_pci_probe 2023-04-16 19:50:35 +10:00
Geoffrey McRae
4f4cf2be7d [client] audio: provide option to prevent volume level sync 2023-04-16 19:10:35 +10:00
Geoffrey McRae
9759b5aa8f [idd] the cursor pos is only valid if it's visible 2023-04-14 21:40:21 +10:00
Geoffrey McRae
bbd0c7a99b [idd] implement cursor shape & position transmission 2023-04-14 20:40:00 +10:00
Geoffrey McRae
c11748a76f [idd] remove unused member variable 2023-04-14 14:10:19 +10:00
Geoffrey McRae
d6b26b0eb1 [idd] resend the last captured frame if a new client connects 2023-04-14 14:08:09 +10:00
Geoffrey McRae
fd0cc6aa10 [idd] consistency: change t to st 2023-04-14 14:08:03 +10:00
Geoffrey McRae
80b9bda59d [idd] keep the textures mapped until overwrite for future re-use 2023-04-14 13:26:08 +10:00
Geoffrey McRae
0c176acf94 [idd] updated to a VS2022 project with Windows 10 support 2023-04-14 12:14:17 +10:00
Geoffrey McRae
0c3dce3ca6 [idd] implemented frame feed from the guest (very hacky)
This is NOT READY for general consumption, if you decide to make
use of this driver, DO NOT ASK FOR SUPPORT.
2023-04-11 16:55:58 +10:00
Geoffrey McRae
3c85957b99 [idd] implemented core shared memory functionallity and LGMP setup 2023-04-11 16:53:57 +10:00
Geoffrey McRae
77ddcfe489 [idd] implement CIVSHMEM and open it 2023-04-11 16:53:57 +10:00
Geoffrey McRae
d228ef135e [idd] target a specific version of windows 2023-04-11 16:53:57 +10:00
Geoffrey McRae
0afcf2c2ce [idd] add LGMP to the project 2023-04-11 16:53:57 +10:00
Geoffrey McRae
75da66a090 [idd] initial indirect driver with Looking Glass monitor 2023-04-11 16:53:57 +10:00
Geoffrey McRae
11676d3d56 [common] windows: fix invalid free of stack allocated memory 2023-04-11 16:51:25 +10:00
Geoffrey McRae
b13682a9ef [lgmp] update library to fix issues with MSVC builds 2023-04-11 16:51:02 +10:00
Geoffrey McRae
642634293d [lgmp] update to fix compilation under MSVC 2023-04-10 10:24:53 +10:00
Geoffrey McRae
01f9c2bfb5 [lgmp] update to fix alignment with MSVC compiled code 2023-04-10 10:21:39 +10:00
Geoffrey McRae
9385b2de7a [submodule] update LGMP to the latest version for incoming Idd support 2023-04-10 03:07:07 +10:00
Jonathan Rubenstein
d2f7667fae [github] CODEOWERS: Fix typo stopping JJRcop owning /doc/
Made an embarassing typo
2023-04-09 09:43:19 +10:00
Jonathan Rubenstein
cfef966603 [github] build: Use debian package for sphinxcontrib-spelling 2023-04-05 08:13:54 +10:00
Jonathan Rubenstein
4f09d5b771 [doc] troubleshooting: Rewrite missing desktop 2023-04-04 23:31:41 +10:00
Geoffrey McRae
b7b302334c [client] main: remove debug true from if statement 2023-04-02 20:14:16 +10:00
Geoffrey McRae
28e74a73a4 [client] main: detect and warn on sub-optimal guest CPU configuration 2023-04-02 20:13:14 +10:00
Geoffrey McRae
996e1b2f7a [client] overlay: fix race on startup that caused a segfault
Fixes #1065
2023-03-30 14:59:37 +11:00
Geoffrey McRae
0ee5751b3a [client] egl: fix buffer overflow 2023-03-30 14:16:51 +11:00
Geoffrey McRae
e067db7bb4 [doc] fix typos and correct 1440p resolution.
Closes #1064
Closes #1061
2023-03-19 12:57:16 +11:00
Geoffrey McRae
b4b4a37b2b [client] egl: switch to using GL_TEXTURE_EXTERNAL_OES for DMABUF
According to Erik @ NVidia the open source NVidia driver will not
create a EGLImage from a DMABUF if the target is not
GL_TEXTURE_EXTERNAL_OES. This change set converts the dmabuf texture
from GL_TEXTURE_2D to GL_TEXTURE_EXTERNAL_OES and at runtime performs a
global search & replace on fragment shaders as needed to remain
compatible, replacing `sampler2D` with `samplerExternalOES`.

Ref: https://github.com/NVIDIA/open-gpu-kernel-modules/discussions/243#discussioncomment-3283415
2023-03-09 09:20:01 +11:00
Geoffrey McRae
bbc9204bfe [client] egl: ensure the preprocessed files have a null terminator 2023-03-09 09:15:39 +11:00
Geoffrey McRae
894b8b0c22 [client] x11: generate synthetic EnterNotify event on cursor leave
If the cursor was grabbed the window the cursor moves over when it is
ungrabbed will recieve an EnterNotify event with the mode of
NotifyUngrab, unfortunatly some window manages such as i3 will ignore
this message and as such focus follows mouse will not function
correctly. This patch injects a normal EnterNotify to work around this
issue.
2023-03-05 16:42:47 +11:00
Geoffrey McRae
91b0cba145 [client] egl: switch from mediump to highp
This fixes a rounding issue on certain hardware (NVidia) which actually
implement mediump as half precision (16-bit) float. It's safe to assume
`highp` is available as if the GPU does not support it, then the shader
compiler will try to find a lower precision that is supported by the GPU
2023-03-05 14:10:21 +11:00
Geoffrey McRae
2f48798db9 [client] wayland: check for failure of wl_display_connect 2023-02-28 23:38:44 +11:00
Geoffrey McRae
254b370bbf [client] audio/pipewire: fix compilation under clang 2023-01-24 13:46:22 +11:00
Geoffrey McRae
86efc47505 [client] audio/pipewire: PW_KEY_TARGET_OBJECT only exists as of 0.3.44 2023-01-24 13:43:17 +11:00
Geoffrey McRae
b559d6b9bc [client] audio/pipewire: add options to set the default out/rec devices 2023-01-24 13:35:25 +11:00
Geoffrey McRae
48cd0c3789 [client] audio: add missing earlyInit call for audio devs 2023-01-24 13:35:18 +11:00
Geoffrey McRae
6f8e6f9a19 [client] x11: catch and print details of X11 errors with a backtrace 2023-01-05 17:33:01 +11:00
Geoffrey McRae
188f25c6bf [host] nvfbc: increase retry timeout to 1 second 2022-12-09 08:00:03 +11:00
Geoffrey McRae
8619f787b9 [host] nvfbc: retry on failure to init
@quantum has observed nvfbc under rare circumstances fail to initialize,
this adds a retry to the init with a short delay to hopefully recover
from this situation.
2022-12-08 21:24:11 +11:00
Quantum
60ac03ebaf [client] wayland: implement window size setting for xdg-shell
This should allow win:autoResize to work on Wayland when the compositor
supports such an operation.
2022-12-08 21:08:33 +11:00
Quantum
e1ebde3cd2 [host] windows: log to stderr that logs will continue in file
This prevents users from posting the stderr as if it's the only output.
2022-12-08 21:08:07 +11:00
Quantum
f519904c38 [host] app: clarify that config file not found is not fatal
This prevents users from thinking this is the problem they are facing.
2022-12-08 21:08:07 +11:00
Geoffrey McRae
fa6f1abaac [obs] fix compatibility with updated LGMP build 2022-11-08 00:00:39 +11:00
Geoffrey McRae
875242fe15 [host] app: improve throttleFPS logic 2022-11-07 22:56:20 +11:00
Geoffrey McRae
20b5957999 [client] update LGMP to fix buffer overflow bug 2022-11-07 21:57:10 +11:00
Geoffrey McRae
f0cb9d1167 [client] main: fix spice display fallback when waiting for LGMP upgrade 2022-11-07 19:16:52 +11:00
Geoffrey McRae
6cd88a70ad [host/client] lgmp: update to fix possible race issue 2022-11-07 14:44:26 +11:00
Geoffrey McRae
697bbcd6d4 [host] app: correct timer restart on lgmp corruption recovery 2022-11-07 13:36:57 +11:00
Geoffrey McRae
ecca5720a9 [host] app: ensure that rand will be random 2022-11-07 13:26:52 +11:00
Geoffrey McRae
50e856f823 [host] lgmp: update LGMP again to fix bug in last update 2022-11-07 13:20:24 +11:00
Geoffrey McRae
6359bb9acd [host] lgmp: update to fix failure to randomize the session ID 2022-11-07 13:12:51 +11:00
Geoffrey McRae
938011fce6 [module] swap offset & size in printk output for consistency 2022-11-07 13:12:51 +11:00
Geoffrey McRae
d09a10299e [module] cosmetics 2022-11-07 13:12:51 +11:00
Geoffrey McRae
8e706636d3 [host] app: don't stop the lgmpTimer on session recovery 2022-11-07 12:20:25 +11:00
Ali Abdel-Qader
352cd2fafe [client] remove non-prototype function declarations
With -Wstrict-prototypes on non-protyped functions are deprecated and
functions must include a void parameter if they do not take parameters.
2022-11-01 08:03:15 +11:00
Chris Spencer
081a0a419d [client] audio: use actual device period if larger than expected maximum
This is rare and I'm not sure what causes it, but PipeWire sometimes uses a
larger period size than requested for no obvious reason (e.g., we could
request a period size of 512, but PipeWire uses 2048 anyway). This causes
us to stay in a permanent state of underrunning because the target latency
is too low.

With this change, we use the actual device period in the target latency
calculation if it is larger than the expected maximum. We may still get
some glitches at the beginning of playback (because the startup latency is
based upon the expected maximum period size), but it will recover after a
few seconds as it adjusts to the new target latency.
2022-11-01 08:02:37 +11:00
esi
7e42e6cdce [obs] Fix function call causing crash on lgUpdate 2022-11-01 08:01:54 +11:00
Quantum
d857b2a36e [cmake] CheckSubmodule: check for nanosvg 2022-11-01 08:01:08 +11:00
Quantum
ba64a2d400 [repos] nanosvg: convert to submodule
This is fine now that nanosvg can be compiled with -Wstrict-prototypes
without warning.
2022-11-01 08:01:08 +11:00
Geoffrey McRae
9d8bc46812 [client] keybind: fix typo 2022-11-01 08:00:37 +11:00
278 changed files with 5502 additions and 5239 deletions

2
.github/CODEOWNERS vendored
View File

@@ -1,4 +1,4 @@
# Jonathan Rubenstein (JJRcop)
# - Primary documentation manager. Does not require direct approval for every
# - change, but should be consulted for large additions and changes.
docs/ jrubcop@gmail.com
/doc/ jrubcop@gmail.com

View File

@@ -97,7 +97,7 @@ jobs:
make -j$(nproc)
host-windows-cross:
runs-on: ubuntu-20.04
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
@@ -183,8 +183,8 @@ jobs:
sudo apt-get update
- name: Install docs dependencies
run: |
sudo apt-get install python3-sphinx python3-sphinx-rtd-theme
sudo pip3 install sphinxcontrib-spelling
sudo apt-get install python3-sphinx python3-sphinx-rtd-theme \
python3-sphinxcontrib.spelling
- name: Build docs
run: |
cd doc

5
.gitignore vendored
View File

@@ -10,3 +10,8 @@ module/modules.order
*/build
__pycache__
*.py[co]
*/.vs
idd/Debug
idd/x64
idd/LGIdd/x64
idd/LGIdd/Debug

3
.gitmodules vendored
View File

@@ -10,3 +10,6 @@
[submodule "repos/wayland-protocols"]
path = repos/wayland-protocols
url = https://gitlab.freedesktop.org/wayland/wayland-protocols.git
[submodule "repos/nanosvg"]
path = repos/nanosvg
url = https://github.com/memononen/nanosvg.git

View File

@@ -9,7 +9,7 @@ arcnmx <arcnmx@users.noreply.github.com> (arcnmx)
TheCakeIsNaOH <TheCakeIsNaOH@gmail.com> (TheCakeIsNaOH)
NamoDev <namodev@users.noreply.github.com> (NamoDev)
feltcat <58396817+feltcat@users.noreply.github.com> (feltcat)
Ali Abdel-Qader <abdelqaderali@protonmail.com>
Ali Abdel-Qader <abdelqaderali@protonmail.com> (thrifty-txt)
Jack Karamanian <karamanian.jack@gmail.com>
Mikko Rasa <tdb@tdb.fi> (DataBeaver)
Omar Pakker <Omar007@users.noreply.github.com> (Omar007)
@@ -65,3 +65,5 @@ Leonard Fricke <leonard.fricke98@gmail.com> (Leo1998)
David Meier <meier_david_91@hotmail.com> (Kenny.ch)
Daniel Cordero <looking-glass@0xdc.io> (0xdc)
esi <git@esibun.net> (esibun)
MakiseKurisu <saberconer@gmail.com> (MakiseKurisu)
Zenithal <i@zenithal.me> (ZenithalHourlyRate)

View File

@@ -1,6 +1,6 @@
/**
* Looking Glass
* Copyright © 2017-2022 The Looking Glass Authors
* Copyright © 2017-2023 The Looking Glass Authors
* https://looking-glass.io
*
* This program is free software; you can redistribute it and/or modify it
@@ -28,6 +28,7 @@
#include "common/debug.h"
#include "common/stringutils.h"
#include "common/util.h"
#include "common/option.h"
typedef enum
{
@@ -129,6 +130,29 @@ static void pipewire_onPlaybackDrained(void * userdata)
pw_thread_loop_unlock(pw.thread);
}
static struct Option pipewire_options[] =
{
{
.module = "pipewire",
.name = "outDevice",
.description = "The default playback device to use",
.type = OPTION_TYPE_STRING
},
{
.module = "pipewire",
.name = "recDevice",
.description = "The default record device to use",
.type = OPTION_TYPE_STRING
},
{0}
};
static void pipewire_earlyInit(void)
{
option_register(pipewire_options);
}
static bool pipewire_init(void)
{
pw_init(NULL, NULL);
@@ -221,9 +245,8 @@ static void pipewire_playbackSetup(int channels, int sampleRate,
pw.playback.pullFn = pullFn;
pw_thread_loop_lock(pw.thread);
pw.playback.stream = pw_stream_new_simple(
pw.loop,
"Looking Glass",
struct pw_properties * props =
pw_properties_new(
PW_KEY_NODE_NAME , "Looking Glass",
PW_KEY_MEDIA_TYPE , "Audio",
@@ -231,7 +254,22 @@ static void pipewire_playbackSetup(int channels, int sampleRate,
PW_KEY_MEDIA_ROLE , "Music",
PW_KEY_NODE_LATENCY , requestedNodeLatency,
NULL
),
);
const char * device = option_get_string("pipewire", "outDevice");
if (device)
{
#ifdef PW_KEY_TARGET_OBJECT
pw_properties_set(props, PW_KEY_TARGET_OBJECT, device);
#else
pw_properties_set(props, PW_KEY_NODE_TARGET, device);
#endif
}
pw.playback.stream = pw_stream_new_simple(
pw.loop,
"Looking Glass",
props,
&events,
NULL
);
@@ -449,17 +487,30 @@ static void pipewire_recordStart(int channels, int sampleRate,
pw.record.stride = sizeof(uint16_t) * channels;
pw.record.pushFn = pushFn;
pw_thread_loop_lock(pw.thread);
pw.record.stream = pw_stream_new_simple(
pw.loop,
"Looking Glass",
struct pw_properties * props =
pw_properties_new(
PW_KEY_NODE_NAME , "Looking Glass",
PW_KEY_MEDIA_TYPE , "Audio",
PW_KEY_MEDIA_CATEGORY, "Capture",
PW_KEY_MEDIA_ROLE , "Music",
NULL
),
);
const char * device = option_get_string("pipewire", "recDevice");
if (device)
{
#ifdef PW_KEY_TARGET_OBJECT
pw_properties_set(props, PW_KEY_TARGET_OBJECT, device);
#else
pw_properties_set(props, PW_KEY_NODE_TARGET, device);
#endif
}
pw_thread_loop_lock(pw.thread);
pw.record.stream = pw_stream_new_simple(
pw.loop,
"Looking Glass",
props,
&events,
NULL
);
@@ -543,9 +594,10 @@ static void pipewire_free(void)
struct LG_AudioDevOps LGAD_PipeWire =
{
.name = "PipeWire",
.init = pipewire_init,
.free = pipewire_free,
.name = "PipeWire",
.earlyInit = pipewire_earlyInit,
.init = pipewire_init,
.free = pipewire_free,
.playback =
{
.setup = pipewire_playbackSetup,

View File

@@ -1,6 +1,6 @@
/**
* Looking Glass
* Copyright © 2017-2022 The Looking Glass Authors
* Copyright © 2017-2023 The Looking Glass Authors
* https://looking-glass.io
*
* This program is free software; you can redistribute it and/or modify it

View File

@@ -1,6 +1,6 @@
/**
* Looking Glass
* Copyright © 2017-2022 The Looking Glass Authors
* Copyright © 2017-2023 The Looking Glass Authors
* https://looking-glass.io
*
* This program is free software; you can redistribute it and/or modify it

View File

@@ -1,6 +1,6 @@
/**
* Looking Glass
* Copyright © 2017-2022 The Looking Glass Authors
* Copyright © 2017-2023 The Looking Glass Authors
* https://looking-glass.io
*
* This program is free software; you can redistribute it and/or modify it

View File

@@ -1,6 +1,6 @@
/**
* Looking Glass
* Copyright © 2017-2022 The Looking Glass Authors
* Copyright © 2017-2023 The Looking Glass Authors
* https://looking-glass.io
*
* This program is free software; you can redistribute it and/or modify it

View File

@@ -1,6 +1,6 @@
/**
* Looking Glass
* Copyright © 2017-2022 The Looking Glass Authors
* Copyright © 2017-2023 The Looking Glass Authors
* https://looking-glass.io
*
* This program is free software; you can redistribute it and/or modify it

View File

@@ -1,6 +1,6 @@
/**
* Looking Glass
* Copyright © 2017-2022 The Looking Glass Authors
* Copyright © 2017-2023 The Looking Glass Authors
* https://looking-glass.io
*
* This program is free software; you can redistribute it and/or modify it

View File

@@ -1,6 +1,6 @@
/**
* Looking Glass
* Copyright © 2017-2022 The Looking Glass Authors
* Copyright © 2017-2023 The Looking Glass Authors
* https://looking-glass.io
*
* This program is free software; you can redistribute it and/or modify it

View File

@@ -1,6 +1,6 @@
/**
* Looking Glass
* Copyright © 2017-2022 The Looking Glass Authors
* Copyright © 2017-2023 The Looking Glass Authors
* https://looking-glass.io
*
* This program is free software; you can redistribute it and/or modify it

View File

@@ -1,6 +1,6 @@
/**
* Looking Glass
* Copyright © 2017-2022 The Looking Glass Authors
* Copyright © 2017-2023 The Looking Glass Authors
* https://looking-glass.io
*
* This program is free software; you can redistribute it and/or modify it

View File

@@ -1,6 +1,6 @@
/**
* Looking Glass
* Copyright © 2017-2022 The Looking Glass Authors
* Copyright © 2017-2023 The Looking Glass Authors
* https://looking-glass.io
*
* This program is free software; you can redistribute it and/or modify it

View File

@@ -1,6 +1,6 @@
/**
* Looking Glass
* Copyright © 2017-2022 The Looking Glass Authors
* Copyright © 2017-2023 The Looking Glass Authors
* https://looking-glass.io
*
* This program is free software; you can redistribute it and/or modify it

View File

@@ -1,6 +1,6 @@
/**
* Looking Glass
* Copyright © 2017-2022 The Looking Glass Authors
* Copyright © 2017-2023 The Looking Glass Authors
* https://looking-glass.io
*
* This program is free software; you can redistribute it and/or modify it

View File

@@ -1,6 +1,6 @@
/**
* Looking Glass
* Copyright © 2017-2022 The Looking Glass Authors
* Copyright © 2017-2023 The Looking Glass Authors
* https://looking-glass.io
*
* This program is free software; you can redistribute it and/or modify it
@@ -65,15 +65,30 @@ static const struct xdg_surface_listener xdgSurfaceListener = {
static void xdgToplevelConfigure(void * data, struct xdg_toplevel * xdgToplevel,
int32_t width, int32_t height, struct wl_array * states)
{
wlWm.width = width;
wlWm.height = height;
wlWm.width = width;
wlWm.height = height;
wlWm.fullscreen = false;
wlWm.floating = true;
enum xdg_toplevel_state * state;
wl_array_for_each(state, states)
{
if (*state == XDG_TOPLEVEL_STATE_FULLSCREEN)
switch (*state)
{
case XDG_TOPLEVEL_STATE_FULLSCREEN:
wlWm.fullscreen = true;
// fallthrough
case XDG_TOPLEVEL_STATE_MAXIMIZED:
case XDG_TOPLEVEL_STATE_TILED_LEFT:
case XDG_TOPLEVEL_STATE_TILED_RIGHT:
case XDG_TOPLEVEL_STATE_TILED_TOP:
case XDG_TOPLEVEL_STATE_TILED_BOTTOM:
wlWm.floating = false;
break;
default:
break;
}
}
}
@@ -156,5 +171,14 @@ void waylandMinimize(void)
void waylandShellResize(int w, int h)
{
//TODO: Implement resize for XDG.
if (!wlWm.floating)
return;
wlWm.width = w;
wlWm.height = h;
xdg_surface_set_window_geometry(wlWm.xdgSurface, 0, 0, w, h);
wlWm.needsResize = true;
app_invalidateWindow(true);
waylandStopWaitFrame();
}

View File

@@ -1,6 +1,6 @@
/**
* Looking Glass
* Copyright © 2017-2022 The Looking Glass Authors
* Copyright © 2017-2023 The Looking Glass Authors
* https://looking-glass.io
*
* This program is free software; you can redistribute it and/or modify it

View File

@@ -1,6 +1,6 @@
/**
* Looking Glass
* Copyright © 2017-2022 The Looking Glass Authors
* Copyright © 2017-2023 The Looking Glass Authors
* https://looking-glass.io
*
* This program is free software; you can redistribute it and/or modify it
@@ -71,12 +71,16 @@ static bool waylandProbe(void)
static bool waylandInit(const LG_DSInitParams params)
{
memset(&wlWm, 0, sizeof(wlWm));
wlWm.display = wl_display_connect(NULL);
if (!wlWm.display)
return false;
wl_list_init(&wlWm.surfaceOutputs);
wlWm.warpSupport = option_get_bool("wayland", "warpSupport");
wlWm.useFractionalScale = option_get_bool("wayland", "fractionScale");
wlWm.display = wl_display_connect(NULL);
wlWm.width = params.w;
wlWm.height = params.h;

View File

@@ -1,6 +1,6 @@
/**
* Looking Glass
* Copyright © 2017-2022 The Looking Glass Authors
* Copyright © 2017-2023 The Looking Glass Authors
* https://looking-glass.io
*
* This program is free software; you can redistribute it and/or modify it
@@ -112,6 +112,7 @@ struct WaylandDSState
bool fractionalScale;
bool needsResize;
bool fullscreen;
bool floating;
uint32_t resizeSerial;
bool configured;
bool warpSupport;

View File

@@ -1,6 +1,6 @@
/**
* Looking Glass
* Copyright © 2017-2022 The Looking Glass Authors
* Copyright © 2017-2023 The Looking Glass Authors
* https://looking-glass.io
*
* This program is free software; you can redistribute it and/or modify it

View File

@@ -17,6 +17,10 @@ add_library(displayserver_X11 STATIC
x11.c
atoms.c
clipboard.c
cursor.c
wm/default.c
wm/i3.c
)
add_definitions(-D GLX_GLXEXT_PROTOTYPES)
@@ -24,9 +28,10 @@ add_definitions(-D GLX_GLXEXT_PROTOTYPES)
target_link_libraries(displayserver_X11
PkgConfig::DISPLAYSERVER_X11
lg_common
lg_resources
)
target_include_directories(displayserver_X11
PRIVATE
src
.
)

View File

@@ -1,6 +1,6 @@
/**
* Looking Glass
* Copyright © 2017-2022 The Looking Glass Authors
* Copyright © 2017-2023 The Looking Glass Authors
* https://looking-glass.io
*
* This program is free software; you can redistribute it and/or modify it

View File

@@ -1,6 +1,6 @@
/**
* Looking Glass
* Copyright © 2017-2022 The Looking Glass Authors
* Copyright © 2017-2023 The Looking Glass Authors
* https://looking-glass.io
*
* This program is free software; you can redistribute it and/or modify it

View File

@@ -1,6 +1,6 @@
/**
* Looking Glass
* Copyright © 2017-2022 The Looking Glass Authors
* Copyright © 2017-2023 The Looking Glass Authors
* https://looking-glass.io
*
* This program is free software; you can redistribute it and/or modify it
@@ -103,7 +103,7 @@ bool x11CBEventThread(const XEvent xe)
return false;
}
bool x11CBInit()
bool x11CBInit(void)
{
x11cb.aCurSelection = BadValue;
for(int i = 0; i < LG_CLIPBOARD_DATA_NONE; ++i)

View File

@@ -1,6 +1,6 @@
/**
* Looking Glass
* Copyright © 2017-2022 The Looking Glass Authors
* Copyright © 2017-2023 The Looking Glass Authors
* https://looking-glass.io
*
* This program is free software; you can redistribute it and/or modify it

View File

@@ -0,0 +1,105 @@
/**
* Looking Glass
* Copyright © 2017-2023 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 "cursor.h"
#include "common/util.h"
#include <string.h>
#include <errno.h>
struct MemFile
{
const char * data;
int size;
int pos;
};
static int x11cursor_read(XcursorFile *file, unsigned char * buf, int len)
{
struct MemFile * f = (struct MemFile *)file->closure;
if (f->pos == f->size)
return 0;
len = min(f->size - f->pos, len);
memcpy(buf, f->data + f->pos, len);
f->pos += len;
return len;
}
static int x11cursor_write(XcursorFile *file, unsigned char * buf, int len)
{
errno = -EINVAL;
return -1;
}
static int x11cursor_seek(XcursorFile *file, long offset, int whence)
{
struct MemFile * f = (struct MemFile *)file->closure;
long target;
switch(whence)
{
case SEEK_SET:
target = offset;
break;
case SEEK_CUR:
target = f->pos + offset;
break;
case SEEK_END:
target = f->size + offset;
break;
default:
errno = -EINVAL;
return -1;
}
if (target < 0 || target > f->size)
{
errno = -EINVAL;
return -1;
}
f->pos = target;
return target;
}
XcursorImages * x11cursor_load(const char * cursor, int size)
{
struct MemFile closure =
{
.data = cursor,
.size = size,
.pos = 0
};
XcursorFile f =
{
.closure = &closure,
.read = x11cursor_read,
.write = x11cursor_write,
.seek = x11cursor_seek
};
return XcursorXcFileLoadAllImages(&f);
}

View File

@@ -0,0 +1,29 @@
/**
* Looking Glass
* Copyright © 2017-2023 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
*/
#ifndef _H_X11DS_CURSOR_
#define _H_X11DS_CURSOR_
#include <X11/Xlib.h>
#include <X11/Xcursor/Xcursor.h>
XcursorImages * x11cursor_load(const char * cursor, int size);
#endif

View File

@@ -0,0 +1,39 @@
/**
* Looking Glass
* Copyright © 2017-2023 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
*/
#ifndef _H_X11DS_WM_
#define _H_X11DS_WM_
#include <stdint.h>
#include <stdbool.h>
typedef struct X11WM
{
void (*setup)(void);
bool (*init)(void);
void (*deinit)(void);
void (*setFullscreen)(bool enable);
}
X11WM;
extern X11WM X11WM_Default;
extern X11WM X11WM_i3;
#endif

View File

@@ -0,0 +1,71 @@
/**
* Looking Glass
* Copyright © 2017-2023 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
*/
#ifndef _H_X11DS_WM_DEFAULT_
#define _H_X11DS_WM_DEFAULT_
#include "wm.h"
#include "x11.h"
#include "atoms.h"
static void wm_default_setup(void)
{
}
static bool wm_default_init(void)
{
return true;
}
static void wm_default_deinit(void)
{
}
static void wm_default_setFullscreen(bool enable)
{
XEvent e =
{
.xclient = {
.type = ClientMessage,
.send_event = true,
.message_type = x11atoms._NET_WM_STATE,
.format = 32,
.window = x11.window,
.data.l = {
enable ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE,
x11atoms._NET_WM_STATE_FULLSCREEN,
0
}
}
};
XSendEvent(x11.display, DefaultRootWindow(x11.display), False,
SubstructureNotifyMask | SubstructureRedirectMask, &e);
};
X11WM X11WM_Default =
{
.setup = wm_default_setup,
.init = wm_default_init,
.deinit = wm_default_deinit,
.setFullscreen = wm_default_setFullscreen
};
#endif

View File

@@ -0,0 +1,194 @@
/**
* Looking Glass
* Copyright © 2017-2023 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
*/
#ifndef _H_X11DS_WM_DEFAULT_
#define _H_X11DS_WM_DEFAULT_
#include "wm.h"
#include "x11.h"
#include "atoms.h"
#include "common/debug.h"
#include "common/option.h"
#include "common/util.h"
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/un.h>
static struct Option options[] =
{
// app options
{
.module = "i3",
.name = "globalFullScreen",
.description = "Use i3's global full screen feature (spans all monitors)",
.type = OPTION_TYPE_BOOL,
.value.x_bool = false,
},
{0}
};
struct i3state
{
int sock;
bool globalFullScreen;
};
static struct i3state i3;
static void wm_i3_setup(void)
{
option_register(options);
}
static bool wm_i3_init(void)
{
memset(&i3, 0, sizeof(i3));
i3.globalFullScreen = option_get_bool("i3", "globalFullScreen");
FILE * fd = popen("i3 --get-socketpath", "r");
if (!fd)
return false;
struct sockaddr_un addr = { .sun_family = AF_UNIX };
char path[sizeof(addr.sun_path)];
int pathLen;
if ((pathLen = fread(path, 1, sizeof(path), fd)) <= 0)
{
pclose(fd);
return false;
}
pclose(fd);
if(path[pathLen-1] == '\n')
--pathLen;
path[pathLen] = '\0';
i3.sock = socket(AF_UNIX, SOCK_STREAM, 0);
if (i3.sock < 0)
{
DEBUG_ERROR("Failed to create socket for i3 IPC");
return false;
}
strncpy(addr.sun_path, path, sizeof(addr.sun_path));
if (connect(i3.sock, (struct sockaddr *)&addr, sizeof(addr)) < 0)
{
DEBUG_ERROR("Failed to connect to the i3 IPC socket");
perror("connect");
goto err_socket;
}
DEBUG_INFO("i3 IPC Connected");
return true;
err_socket:
close(i3.sock);
return false;
}
static void wm_i3_deinit(void)
{
close(i3.sock);
}
static void wm_i3_setFullscreen(bool enable)
{
if (!i3.globalFullScreen)
{
X11WM_Default.setFullscreen(enable);
return;
}
struct i3Msg
{
char magic[6];
uint32_t length;
uint32_t type;
char payload[0];
}
__attribute__((packed));
#define I3_IPC_TYPE_RUN_COMMAND 0
char cmd[128];
int cmdLen = snprintf(cmd, sizeof(cmd),
"[id=%lu] fullscreen toggle global",
x11.window);
struct i3Msg *msg = alloca(sizeof(struct i3Msg) + cmdLen);
memcpy(msg->magic, "i3-ipc", 6);
msg->length = cmdLen;
msg->type = I3_IPC_TYPE_RUN_COMMAND;
memcpy(msg->payload, cmd, cmdLen);
int msgSize = sizeof(*msg) + msg->length;
char * buf = (char *)msg;
while(msgSize)
{
int wrote = write(i3.sock, buf, msgSize);
if (wrote <= 0)
{
DEBUG_WARN("i3 IPC communication failure");
return;
}
buf += wrote;
msgSize -= wrote;
}
if ((msgSize = read(i3.sock, msg, sizeof(*msg))) < 0)
{
DEBUG_WARN("i3 IPC read failure");
return;
}
if (memcmp(msg->magic, "i3-ipc", 6) != 0 ||
msg->type != I3_IPC_TYPE_RUN_COMMAND)
{
DEBUG_WARN("i3 IPC unexpected reply");
return;
}
// read and discard the payload
while(msg->length)
{
int len = read(i3.sock, cmd, min(msg->length, sizeof(cmd)));
if (len <= 0)
{
DEBUG_WARN("i3 IPC failed to read payload");
return;
}
msg->length -= len;
}
};
X11WM X11WM_i3 =
{
.setup = wm_i3_setup,
.init = wm_i3_init,
.deinit = wm_i3_deinit,
.setFullscreen = wm_i3_setFullscreen
};
#endif

View File

@@ -1,6 +1,6 @@
/**
* Looking Glass
* Copyright © 2017-2022 The Looking Glass Authors
* Copyright © 2017-2023 The Looking Glass Authors
* https://looking-glass.io
*
* This program is free software; you can redistribute it and/or modify it
@@ -23,7 +23,11 @@
#include "x11.h"
#include "atoms.h"
#include "clipboard.h"
#include "cursor.h"
#include "resources/icondata.h"
#include "resources/no-input-cursor/16.xcur.h"
#include "resources/no-input-cursor/32.xcur.h"
#include <string.h>
#include <unistd.h>
@@ -53,10 +57,6 @@
#include "common/event.h"
#include "util.h"
#define _NET_WM_STATE_REMOVE 0
#define _NET_WM_STATE_ADD 1
#define _NET_WM_STATE_TOGGLE 2
struct X11DSState x11;
struct MwmHints
@@ -166,6 +166,8 @@ static void x11DoPresent(uint64_t msc)
static void x11Setup(void)
{
X11WM_Default.setup();
X11WM_i3 .setup();
}
static bool x11Probe(void)
@@ -230,6 +232,8 @@ static void x11CheckEWMHSupport(void)
DEBUG_INFO("EWMH-complient window manager detected: %s", wmName);
x11.ewmhSupport = true;
if (strcmp(wmName, "i3") == 0)
x11.wm = &X11WM_i3;
XFree(wmName);
out_supported:
@@ -242,17 +246,37 @@ out:
return;
}
static int x11ErrorHandler(Display * display, XErrorEvent * error)
{
char errorText[1024];
XGetErrorText(display, error->error_code, errorText, sizeof(errorText));
DEBUG_ERROR("X11 Error: %s", errorText);
DEBUG_PRINT_BACKTRACE();
return 0;
}
static int x11IOErrorHandler(Display * display)
{
DEBUG_FATAL("Fatal X11 IO Error");
return 0;
}
static bool x11Init(const LG_DSInitParams params)
{
XIDeviceInfo *devinfo;
int count;
int event, error;
XSetErrorHandler(x11ErrorHandler);
XSetIOErrorHandler(x11IOErrorHandler);
memset(&x11, 0, sizeof(x11));
x11.xValuator = -1;
x11.yValuator = -1;
x11.display = XOpenDisplay(NULL);
x11.display = XOpenDisplay(NULL);
x11.jitRender = params.jitRender;
x11.wm = &X11WM_Default;
XSetWindowAttributes swa =
{
@@ -350,6 +374,16 @@ static bool x11Init(const LG_DSInitParams params)
// check for Extended Window Manager Hints support
x11CheckEWMHSupport();
if (!x11.wm->init())
{
x11.wm = &X11WM_Default;
if (!x11.wm->init())
{
DEBUG_ERROR("Failed to initialize the X11 window manager subsystem");
goto fail_window;
}
}
if (x11atoms._NET_WM_PID)
{
pid_t pid = getpid();
@@ -457,7 +491,7 @@ static bool x11Init(const LG_DSInitParams params)
if (XIQueryVersion(x11.display, &major, &minor) != Success)
{
DEBUG_ERROR("Failed to query the XInput version");
return false;
goto fail_window;
}
DEBUG_INFO("X11 XInput %d.%d in use", major, minor);
@@ -596,29 +630,17 @@ static bool x11Init(const LG_DSInitParams params)
XFreePixmap(x11.display, temp);
}
/* create the square cursor */
{
static char data[] = { 0x07, 0x05, 0x07 };
static char mask[] = { 0xff, 0xff, 0xff };
XcursorImages * images;
if (params.largeCursorDot)
images = x11cursor_load(b_no_input_cursor_32_xcur,
b_no_input_cursor_32_xcur_size);
else
images = x11cursor_load(b_no_input_cursor_16_xcur,
b_no_input_cursor_16_xcur_size);
Colormap cmap = DefaultColormap(x11.display, DefaultScreen(x11.display));
XColor colors[2] =
{
{ .pixel = BlackPixelOfScreen(DefaultScreenOfDisplay(x11.display)) },
{ .pixel = WhitePixelOfScreen(DefaultScreenOfDisplay(x11.display)) }
};
XQueryColors(x11.display, cmap, colors, 2);
Pixmap img = XCreateBitmapFromData(x11.display, x11.window, data, 3, 3);
Pixmap msk = XCreateBitmapFromData(x11.display, x11.window, mask, 3, 3);
x11.cursors[LG_POINTER_SQUARE] = XCreatePixmapCursor(x11.display, img, msk,
&colors[0], &colors[1], 1, 1);
XFreePixmap(x11.display, img);
XFreePixmap(x11.display, msk);
}
x11.cursors[LG_POINTER_SQUARE] =
XcursorImagesLoadCursor(x11.display, images);
XcursorImagesDestroy(images);
/* initialize the rest of the cursors */
const char * cursorLookup[LG_POINTER_COUNT] = {
@@ -762,6 +784,7 @@ static void x11Free(void)
if (x11.keysyms)
XFree(x11.keysyms);
x11.wm->deinit();
XCloseDisplay(x11.display);
}
@@ -1152,6 +1175,46 @@ static void x11XInputEvent(XGenericEventCookie *cookie)
app_updateCursorPos(xie->event_x, xie->event_y);
app_handleEnterEvent(false);
x11.entered = false;
/**
* Because there is a race with the pointer ungrab the enter event for the
* next window is sometimes sent with the mode NotifyUngrab, unfortunatly
* some window managers such as i3 will ignore these which breaks focus
* follows mouse mode. To correct this we generate and send a normal
* EnterNotify event.
*/
int root_x, root_y, win_x, win_y;
Window root_win, child_win;
unsigned int mask;
XQueryPointer(x11.display, DefaultRootWindow(x11.display), &root_win,
&child_win, &root_x, &root_y, &win_x, &win_y, &mask);
int target_x, target_y;
Window target_root;
XTranslateCoordinates(x11.display, DefaultRootWindow(x11.display),
child_win, root_x, root_y, &target_x, &target_y, &target_root);
XEvent event;
memset(&event, 0, sizeof(event));
event.type = EnterNotify;
event.xcrossing.serial = 0;
event.xcrossing.send_event = True;
event.xcrossing.display = x11.display;
event.xcrossing.window = child_win;
event.xcrossing.root = root_win;
event.xcrossing.subwindow = child_win;
event.xcrossing.time = CurrentTime;
event.xcrossing.mode = NotifyNormal;
event.xcrossing.detail = NotifyNonlinear;
event.xcrossing.same_screen = True;
event.xcrossing.focus = False;
event.xcrossing.x = target_x;
event.xcrossing.y = target_y;
event.xcrossing.x_root = root_x;
event.xcrossing.y_root = root_y;
XSendEvent(x11.display, child_win, True, EnterWindowMask, &event);
XFlush(x11.display);
return;
}
@@ -1905,24 +1968,7 @@ static void x11SetFullscreen(bool fs)
if (x11.fullscreen == fs)
return;
XEvent e =
{
.xclient = {
.type = ClientMessage,
.send_event = true,
.message_type = x11atoms._NET_WM_STATE,
.format = 32,
.window = x11.window,
.data.l = {
fs ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE,
x11atoms._NET_WM_STATE_FULLSCREEN,
0
}
}
};
XSendEvent(x11.display, DefaultRootWindow(x11.display), False,
SubstructureNotifyMask | SubstructureRedirectMask, &e);
x11.wm->setFullscreen(fs);
}
static bool x11GetFullscreen(void)

View File

@@ -1,6 +1,6 @@
/**
* Looking Glass
* Copyright © 2017-2022 The Looking Glass Authors
* Copyright © 2017-2023 The Looking Glass Authors
* https://looking-glass.io
*
* This program is free software; you can redistribute it and/or modify it
@@ -33,6 +33,7 @@
#include "interface/displayserver.h"
#include "common/thread.h"
#include "common/types.h"
#include "wm.h"
enum Modifiers
{
@@ -48,11 +49,16 @@ enum Modifiers
#define MOD_COUNT (MOD_SUPER_RIGHT + 1)
#define _NET_WM_STATE_REMOVE 0
#define _NET_WM_STATE_ADD 1
#define _NET_WM_STATE_TOGGLE 2
struct X11DSState
{
Display * display;
Window window;
XVisualInfo * visual;
X11WM * wm;
int minKeycode, maxKeycode;
int symsPerKeycode;

View File

@@ -1,6 +1,6 @@
/**
* Looking Glass
* Copyright © 2017-2022 The Looking Glass Authors
* Copyright © 2017-2023 The Looking Glass Authors
* https://looking-glass.io
*
* This program is free software; you can redistribute it and/or modify it

View File

@@ -1,6 +1,6 @@
/**
* Looking Glass
* Copyright © 2017-2022 The Looking Glass Authors
* Copyright © 2017-2023 The Looking Glass Authors
* https://looking-glass.io
*
* This program is free software; you can redistribute it and/or modify it

View File

@@ -1,6 +1,6 @@
/**
* Looking Glass
* Copyright © 2017-2022 The Looking Glass Authors
* Copyright © 2017-2023 The Looking Glass Authors
* https://looking-glass.io
*
* This program is free software; you can redistribute it and/or modify it

View File

@@ -1,6 +1,6 @@
/**
* Looking Glass
* Copyright © 2017-2022 The Looking Glass Authors
* Copyright © 2017-2023 The Looking Glass Authors
* https://looking-glass.io
*
* This program is free software; you can redistribute it and/or modify it

View File

@@ -1,6 +1,6 @@
/**
* Looking Glass
* Copyright © 2017-2022 The Looking Glass Authors
* Copyright © 2017-2023 The Looking Glass Authors
* https://looking-glass.io
*
* This program is free software; you can redistribute it and/or modify it

View File

@@ -1,6 +1,6 @@
/**
* Looking Glass
* Copyright © 2017-2022 The Looking Glass Authors
* Copyright © 2017-2023 The Looking Glass Authors
* https://looking-glass.io
*
* This program is free software; you can redistribute it and/or modify it
@@ -90,6 +90,7 @@ typedef struct LG_DSInitParams
bool resizable;
bool borderless;
bool maximize;
bool largeCursorDot;
// if true the renderer requires an OpenGL context
bool opengl;

View File

@@ -1,6 +1,6 @@
/**
* Looking Glass
* Copyright © 2017-2022 The Looking Glass Authors
* Copyright © 2017-2023 The Looking Glass Authors
* https://looking-glass.io
*
* This program is free software; you can redistribute it and/or modify it

View File

@@ -1,6 +1,6 @@
/**
* Looking Glass
* Copyright © 2017-2022 The Looking Glass Authors
* Copyright © 2017-2023 The Looking Glass Authors
* https://looking-glass.io
*
* This program is free software; you can redistribute it and/or modify it

View File

@@ -1,6 +1,6 @@
/**
* Looking Glass
* Copyright © 2017-2022 The Looking Glass Authors
* Copyright © 2017-2023 The Looking Glass Authors
* https://looking-glass.io
*
* This program is free software; you can redistribute it and/or modify it
@@ -72,6 +72,8 @@ LG_RendererRotate;
typedef struct LG_RendererFormat
{
FrameType type; // frame type
bool hdr; // if the frame is HDR or not
bool hdrPQ; // if the HDR content is PQ mapped
unsigned int screenWidth; // actual width of the host
unsigned int screenHeight; // actual height of the host
unsigned int frameWidth; // width of frame transmitted

View File

@@ -1,6 +1,6 @@
/**
* Looking Glass
* Copyright © 2017-2022 The Looking Glass Authors
* Copyright © 2017-2023 The Looking Glass Authors
* https://looking-glass.io
*
* This program is free software; you can redistribute it and/or modify it

View File

@@ -1,6 +1,6 @@
/**
* Looking Glass
* Copyright © 2017-2022 The Looking Glass Authors
* Copyright © 2017-2023 The Looking Glass Authors
* https://looking-glass.io
*
* This program is free software; you can redistribute it and/or modify it

View File

@@ -1,6 +1,6 @@
/**
* Looking Glass
* Copyright © 2017-2022 The Looking Glass Authors
* Copyright © 2017-2023 The Looking Glass Authors
* https://looking-glass.io
*
* This program is free software; you can redistribute it and/or modify it
@@ -100,7 +100,7 @@ static bool cursorTexInit(struct CursorTex * t,
}
if (!egl_shaderCompile(t->shader,
vertex_code, vertex_size, fragment_code, fragment_size))
vertex_code, vertex_size, fragment_code, fragment_size, false))
{
DEBUG_ERROR("Failed to compile the cursor shader");
return false;

View File

@@ -1,6 +1,6 @@
/**
* Looking Glass
* Copyright © 2017-2022 The Looking Glass Authors
* Copyright © 2017-2023 The Looking Glass Authors
* https://looking-glass.io
*
* This program is free software; you can redistribute it and/or modify it

View File

@@ -1,6 +1,6 @@
/**
* Looking Glass
* Copyright © 2017-2022 The Looking Glass Authors
* Copyright © 2017-2023 The Looking Glass Authors
* https://looking-glass.io
*
* This program is free software; you can redistribute it and/or modify it
@@ -76,7 +76,8 @@ bool egl_damageInit(EGL_Damage ** damage)
if (!egl_shaderCompile((*damage)->shader,
b_shader_damage_vert, b_shader_damage_vert_size,
b_shader_damage_frag, b_shader_damage_frag_size))
b_shader_damage_frag, b_shader_damage_frag_size,
false))
{
DEBUG_ERROR("Failed to compile the damage shader");
return false;

View File

@@ -1,6 +1,6 @@
/**
* Looking Glass
* Copyright © 2017-2022 The Looking Glass Authors
* Copyright © 2017-2023 The Looking Glass Authors
* https://looking-glass.io
*
* This program is free software; you can redistribute it and/or modify it

View File

@@ -1,6 +1,6 @@
/**
* Looking Glass
* Copyright © 2017-2022 The Looking Glass Authors
* Copyright © 2017-2023 The Looking Glass Authors
* https://looking-glass.io
*
* This program is free software; you can redistribute it and/or modify it
@@ -46,9 +46,14 @@ struct DesktopShader
EGL_Shader * shader;
GLint uTransform;
GLint uDesktopSize;
GLint uSamplerType;
GLint uScaleAlgo;
GLint uNVGain;
GLint uCBMode;
GLint uIsHDR;
GLint uMapHDRtoSDR;
GLint uMapHDRGain;
GLint uMapHDRPQ;
};
struct EGL_Desktop
@@ -57,12 +62,14 @@ struct EGL_Desktop
EGLDisplay * display;
EGL_Texture * texture;
struct DesktopShader shader;
struct DesktopShader dmaShader, shader;
EGL_DesktopRects * mesh;
CountedBuffer * matrix;
// internals
int width, height;
bool hdr;
bool hdrPQ;
LG_RendererRotate rotate;
bool useSpice;
@@ -82,6 +89,11 @@ struct EGL_Desktop
bool useDMA;
LG_RendererFormat format;
// map HDR content to SDR
bool mapHDRtoSDR;
int peakLuminance;
int maxCLL;
EGL_PostProcess * pp;
_Atomic(bool) processFrame;
};
@@ -92,7 +104,8 @@ void toggleNV(int key, void * opaque);
static bool egl_initDesktopShader(
struct DesktopShader * shader,
const char * vertex_code , size_t vertex_size,
const char * fragment_code, size_t fragment_size
const char * fragment_code, size_t fragment_size,
bool useDMA
)
{
if (!egl_shaderInit(&shader->shader))
@@ -100,16 +113,21 @@ static bool egl_initDesktopShader(
if (!egl_shaderCompile(shader->shader,
vertex_code , vertex_size,
fragment_code, fragment_size))
fragment_code, fragment_size,
useDMA))
{
return false;
}
shader->uTransform = egl_shaderGetUniform(shader->shader, "transform" );
shader->uDesktopSize = egl_shaderGetUniform(shader->shader, "desktopSize");
shader->uScaleAlgo = egl_shaderGetUniform(shader->shader, "scaleAlgo" );
shader->uNVGain = egl_shaderGetUniform(shader->shader, "nvGain" );
shader->uCBMode = egl_shaderGetUniform(shader->shader, "cbMode" );
shader->uTransform = egl_shaderGetUniform(shader->shader, "transform" );
shader->uDesktopSize = egl_shaderGetUniform(shader->shader, "desktopSize" );
shader->uScaleAlgo = egl_shaderGetUniform(shader->shader, "scaleAlgo" );
shader->uNVGain = egl_shaderGetUniform(shader->shader, "nvGain" );
shader->uCBMode = egl_shaderGetUniform(shader->shader, "cbMode" );
shader->uIsHDR = egl_shaderGetUniform(shader->shader, "isHDR" );
shader->uMapHDRtoSDR = egl_shaderGetUniform(shader->shader, "mapHDRtoSDR" );
shader->uMapHDRGain = egl_shaderGetUniform(shader->shader, "mapHDRGain" );
shader->uMapHDRPQ = egl_shaderGetUniform(shader->shader, "mapHDRPQ" );
return true;
}
@@ -135,15 +153,6 @@ bool egl_desktopInit(EGL * egl, EGL_Desktop ** desktop_, EGLDisplay * display,
return false;
}
if (!egl_initDesktopShader(
&desktop->shader,
b_shader_desktop_vert , b_shader_desktop_vert_size,
b_shader_desktop_rgb_frag, b_shader_desktop_rgb_frag_size))
{
DEBUG_ERROR("Failed to initialize the generic desktop shader");
return false;
}
if (!egl_desktopRectsInit(&desktop->mesh, maxRects))
{
DEBUG_ERROR("Failed to initialize the desktop mesh");
@@ -157,6 +166,27 @@ bool egl_desktopInit(EGL * egl, EGL_Desktop ** desktop_, EGLDisplay * display,
return false;
}
if (!egl_initDesktopShader(
&desktop->shader,
b_shader_desktop_vert , b_shader_desktop_vert_size,
b_shader_desktop_rgb_frag, b_shader_desktop_rgb_frag_size,
false))
{
DEBUG_ERROR("Failed to initialize the desktop shader");
return false;
}
if (useDMA)
if (!egl_initDesktopShader(
&desktop->dmaShader,
b_shader_desktop_vert , b_shader_desktop_vert_size,
b_shader_desktop_rgb_frag, b_shader_desktop_rgb_frag_size,
true))
{
DEBUG_ERROR("Failed to initialize the desktop DMA shader");
return false;
}
app_registerKeybind(0, 'N', toggleNV, desktop,
"Toggle night vision mode");
@@ -166,6 +196,10 @@ bool egl_desktopInit(EGL * egl, EGL_Desktop ** desktop_, EGLDisplay * display,
desktop->scaleAlgo = option_get_int("egl", "scale" );
desktop->useDMA = useDMA;
desktop->mapHDRtoSDR = option_get_bool("egl", "mapHDRtoSDR" );
desktop->peakLuminance = option_get_int ("egl", "peakLuminance");
desktop->maxCLL = option_get_int ("egl", "maxCLL" );
if (!egl_postProcessInit(&desktop->pp))
{
DEBUG_ERROR("Failed to initialize the post process manager");
@@ -205,11 +239,12 @@ void egl_desktopFree(EGL_Desktop ** desktop)
if (!*desktop)
return;
egl_textureFree (&(*desktop)->texture );
egl_textureFree (&(*desktop)->spiceTexture );
egl_shaderFree (&(*desktop)->shader.shader);
egl_desktopRectsFree(&(*desktop)->mesh );
countedBufferRelease(&(*desktop)->matrix );
egl_textureFree (&(*desktop)->texture );
egl_textureFree (&(*desktop)->spiceTexture );
egl_shaderFree (&(*desktop)->shader .shader);
egl_shaderFree (&(*desktop)->dmaShader.shader);
egl_desktopRectsFree(&(*desktop)->mesh );
countedBufferRelease(&(*desktop)->matrix );
egl_postProcessFree(&(*desktop)->pp);
@@ -255,6 +290,28 @@ void egl_desktopConfigUI(EGL_Desktop * desktop)
}
igSliderInt("##nvgain", &desktop->nvGain, 0, desktop->nvMax, format, 0);
igPopItemWidth();
bool mapHDRtoSDR = desktop->mapHDRtoSDR;
int peakLuminance = desktop->peakLuminance;
int maxCLL = desktop->maxCLL;
igSeparator();
igCheckbox("Map HDR content to SDR", &mapHDRtoSDR);
igSliderInt("Peak Luminance", &peakLuminance, 1, 10000,
"%d nits",
ImGuiInputTextFlags_CharsDecimal);
igSliderInt("Max content light level", &maxCLL, 1, 10000,
"%d nits", ImGuiInputTextFlags_CharsDecimal);
if (mapHDRtoSDR != desktop->mapHDRtoSDR ||
peakLuminance != desktop->peakLuminance ||
maxCLL != desktop->maxCLL)
{
desktop->mapHDRtoSDR = mapHDRtoSDR;
desktop->peakLuminance = max(1, peakLuminance);
desktop->maxCLL = max(1, maxCLL);
app_invalidateWindow(true);
}
}
bool egl_desktopSetup(EGL_Desktop * desktop, const LG_RendererFormat format)
@@ -287,6 +344,8 @@ bool egl_desktopSetup(EGL_Desktop * desktop, const LG_RendererFormat format)
desktop->width = format.frameWidth;
desktop->height = format.frameHeight;
desktop->hdr = format.hdr;
desktop->hdrPQ = format.hdrPQ;
if (!egl_textureSetup(
desktop->texture,
@@ -399,18 +458,17 @@ bool egl_desktopRender(EGL_Desktop * desktop, unsigned int outputWidth,
if (atomic_exchange(&desktop->processFrame, false) ||
egl_postProcessConfigModified(desktop->pp))
egl_postProcessRun(desktop->pp, tex, desktop->mesh,
width, height, outputWidth, outputHeight);
width, height, outputWidth, outputHeight, desktop->useDMA);
unsigned int finalSizeX, finalSizeY;
GLuint texture = egl_postProcessGetOutput(desktop->pp,
EGL_Texture * texture = egl_postProcessGetOutput(desktop->pp,
&finalSizeX, &finalSizeY);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
egl_resetViewport(desktop->egl);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
glBindSampler(0, tex->sampler);
egl_textureBind(texture);
if (finalSizeX > width || finalSizeY > height)
scaleType = EGL_DESKTOP_DOWNSCALE;
@@ -435,7 +493,13 @@ bool egl_desktopRender(EGL_Desktop * desktop, unsigned int outputWidth,
scaleAlgo = desktop->scaleAlgo;
}
const struct DesktopShader * shader = &desktop->shader;
const struct DesktopShader * shader =
desktop->useDMA && texture == desktop->texture ?
&desktop->dmaShader : &desktop->shader;
const float mapHDRGain =
desktop->maxCLL / desktop->peakLuminance;
EGL_Uniform uniforms[] =
{
{
@@ -463,6 +527,26 @@ bool egl_desktopRender(EGL_Desktop * desktop, unsigned int outputWidth,
.type = EGL_UNIFORM_TYPE_1I,
.location = shader->uCBMode,
.f = { desktop->cbMode }
},
{
.type = EGL_UNIFORM_TYPE_1I,
.location = shader->uIsHDR,
.i = { desktop->hdr }
},
{
.type = EGL_UNIFORM_TYPE_1I,
.location = shader->uMapHDRtoSDR,
.i = { desktop->mapHDRtoSDR }
},
{
.type = EGL_UNIFORM_TYPE_1F,
.location = shader->uMapHDRGain,
.f = { mapHDRGain }
},
{
.type = EGL_UNIFORM_TYPE_1I,
.location = shader->uMapHDRPQ,
.f = { desktop->hdrPQ }
}
};

View File

@@ -1,6 +1,6 @@
/**
* Looking Glass
* Copyright © 2017-2022 The Looking Glass Authors
* Copyright © 2017-2023 The Looking Glass Authors
* https://looking-glass.io
*
* This program is free software; you can redistribute it and/or modify it

View File

@@ -1,6 +1,6 @@
/**
* Looking Glass
* Copyright © 2017-2022 The Looking Glass Authors
* Copyright © 2017-2023 The Looking Glass Authors
* https://looking-glass.io
*
* This program is free software; you can redistribute it and/or modify it

View File

@@ -1,6 +1,6 @@
/**
* Looking Glass
* Copyright © 2017-2022 The Looking Glass Authors
* Copyright © 2017-2023 The Looking Glass Authors
* https://looking-glass.io
*
* This program is free software; you can redistribute it and/or modify it

View File

@@ -1,6 +1,6 @@
/**
* Looking Glass
* Copyright © 2017-2022 The Looking Glass Authors
* Copyright © 2017-2023 The Looking Glass Authors
* https://looking-glass.io
*
* This program is free software; you can redistribute it and/or modify it
@@ -202,6 +202,27 @@ static struct Option egl_options[] =
.type = OPTION_TYPE_BOOL,
.value.x_bool = true
},
{
.module = "egl",
.name = "mapHDRtoSDR",
.description = "Map HDR content to the SDR color space",
.type = OPTION_TYPE_BOOL,
.value.x_bool = true
},
{
.module = "egl",
.name = "peakLuminance",
.description = "The peak luminance level in nits for HDR to SDR mapping",
.type = OPTION_TYPE_INT,
.value.x_int = 250,
},
{
.module = "egl",
.name = "maxCLL",
.description = "Maximum content light level in nits for HDR to SDR mapping",
.type = OPTION_TYPE_INT,
.value.x_int = 10000,
},
{0}
};
@@ -748,7 +769,7 @@ static bool egl_renderStartup(LG_Renderer * renderer, bool useDMA)
EGLint attr[] =
{
EGL_BUFFER_SIZE , 24,
EGL_BUFFER_SIZE , 30,
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
EGL_SAMPLE_BUFFERS , maxSamples > 0 ? 1 : 0,
EGL_SAMPLES , maxSamples,

View File

@@ -1,6 +1,6 @@
/**
* Looking Glass
* Copyright © 2017-2022 The Looking Glass Authors
* Copyright © 2017-2023 The Looking Glass Authors
* https://looking-glass.io
*
* This program is free software; you can redistribute it and/or modify it

View File

@@ -1,6 +1,6 @@
/**
* Looking Glass
* Copyright © 2017-2022 The Looking Glass Authors
* Copyright © 2017-2023 The Looking Glass Authors
* https://looking-glass.io
*
* This program is free software; you can redistribute it and/or modify it

View File

@@ -1,6 +1,6 @@
/**
* Looking Glass
* Copyright © 2017-2022 The Looking Glass Authors
* Copyright © 2017-2023 The Looking Glass Authors
* https://looking-glass.io
*
* This program is free software; you can redistribute it and/or modify it

View File

@@ -1,6 +1,6 @@
/**
* Looking Glass
* Copyright © 2017-2022 The Looking Glass Authors
* Copyright © 2017-2023 The Looking Glass Authors
* https://looking-glass.io
*
* This program is free software; you can redistribute it and/or modify it

View File

@@ -1,6 +1,6 @@
/**
* Looking Glass
* Copyright © 2017-2022 The Looking Glass Authors
* Copyright © 2017-2023 The Looking Glass Authors
* https://looking-glass.io
*
* This program is free software; you can redistribute it and/or modify it

View File

@@ -1,6 +1,6 @@
/**
* Looking Glass
* Copyright © 2017-2022 The Looking Glass Authors
* Copyright © 2017-2023 The Looking Glass Authors
* https://looking-glass.io
*
* This program is free software; you can redistribute it and/or modify it

View File

@@ -1,6 +1,6 @@
/**
* Looking Glass
* Copyright © 2017-2022 The Looking Glass Authors
* Copyright © 2017-2023 The Looking Glass Authors
* https://looking-glass.io
*
* This program is free software; you can redistribute it and/or modify it

View File

@@ -1,6 +1,6 @@
/**
* Looking Glass
* Copyright © 2017-2022 The Looking Glass Authors
* Copyright © 2017-2023 The Looking Glass Authors
* https://looking-glass.io
*
* This program is free software; you can redistribute it and/or modify it
@@ -68,9 +68,11 @@ typedef struct EGL_FilterOps
/* reads filter state from options */
void (*loadState)(EGL_Filter * filter);
/* set the input format of the filter */
/* set the input format of the filter
* useDMA will be true if the texture provided needs to use samplerExternalOES
*/
bool (*setup)(EGL_Filter * filter, enum EGL_PixelFormat pixFmt,
unsigned int width, unsigned int height);
unsigned int width, unsigned int height, bool useDMA);
/* set the output resolution hint for the filter
* this is optional and only a hint */
@@ -87,8 +89,8 @@ typedef struct EGL_FilterOps
/* runs the filter on the provided texture
* returns the processed texture as the output */
GLuint (*run)(EGL_Filter * filter, EGL_FilterRects * rects,
GLuint texture);
EGL_Texture * (*run)(EGL_Filter * filter, EGL_FilterRects * rects,
EGL_Texture * texture);
/* called when the filter output is no loger needed so it can release memory
* this is optional */
@@ -133,9 +135,10 @@ static inline void egl_filterLoadState(EGL_Filter * filter)
}
static inline bool egl_filterSetup(EGL_Filter * filter,
enum EGL_PixelFormat pixFmt, unsigned int width, unsigned int height)
enum EGL_PixelFormat pixFmt, unsigned int width, unsigned int height,
bool useDMA)
{
return filter->ops.setup(filter, pixFmt, width, height);
return filter->ops.setup(filter, pixFmt, width, height, useDMA);
}
static inline void egl_filterSetOutputResHint(EGL_Filter * filter,
@@ -156,8 +159,8 @@ static inline bool egl_filterPrepare(EGL_Filter * filter)
return filter->ops.prepare(filter);
}
static inline GLuint egl_filterRun(EGL_Filter * filter,
EGL_FilterRects * rects, GLuint texture)
static inline EGL_Texture * egl_filterRun(EGL_Filter * filter,
EGL_FilterRects * rects, EGL_Texture * texture)
{
return filter->ops.run(filter, rects, texture);
}

View File

@@ -1,6 +1,6 @@
/**
* Looking Glass
* Copyright © 2017-2022 The Looking Glass Authors
* Copyright © 2017-2023 The Looking Glass Authors
* https://looking-glass.io
*
* This program is free software; you can redistribute it and/or modify it
@@ -60,6 +60,7 @@ typedef struct EGL_FilterDownscale
EGL_Shader * lanczos2;
DownscaleFilter filter;
int useDMA;
enum EGL_PixelFormat pixFmt;
unsigned int width, height;
float pixelSize;
@@ -157,55 +158,26 @@ static bool egl_filterDownscaleInit(EGL_Filter ** filter)
return false;
}
this->useDMA = -1;
if (!egl_shaderInit(&this->nearest))
{
DEBUG_ERROR("Failed to initialize the shader");
goto error_this;
}
if (!egl_shaderCompile(this->nearest,
b_shader_basic_vert , b_shader_basic_vert_size,
b_shader_downscale_frag, b_shader_downscale_frag_size)
)
{
DEBUG_ERROR("Failed to compile the shader");
goto error_shader;
}
if (!egl_shaderInit(&this->linear))
{
DEBUG_ERROR("Failed to initialize the shader");
goto error_this;
}
if (!egl_shaderCompile(this->linear,
b_shader_basic_vert, b_shader_basic_vert_size,
b_shader_downscale_linear_frag, b_shader_downscale_linear_frag_size)
)
{
DEBUG_ERROR("Failed to compile the shader");
goto error_shader;
}
if (!egl_shaderInit(&this->lanczos2))
{
DEBUG_ERROR("Failed to initialize the shader");
goto error_this;
}
if (!egl_shaderCompile(this->lanczos2,
b_shader_basic_vert, b_shader_basic_vert_size,
b_shader_downscale_lanczos2_frag, b_shader_downscale_lanczos2_frag_size)
)
{
DEBUG_ERROR("Failed to compile the shader");
goto error_shader;
}
this->uNearest.type = EGL_UNIFORM_TYPE_3F;
this->uNearest.location =
egl_shaderGetUniform(this->nearest, "uConfig");
if (!egl_framebufferInit(&this->fb))
{
DEBUG_ERROR("Failed to initialize the framebuffer");
@@ -326,7 +298,8 @@ static bool egl_filterDownscaleImguiConfig(EGL_Filter * filter)
}
static bool egl_filterDownscaleSetup(EGL_Filter * filter,
enum EGL_PixelFormat pixFmt, unsigned int width, unsigned int height)
enum EGL_PixelFormat pixFmt, unsigned int width, unsigned int height,
bool useDMA)
{
EGL_FilterDownscale * this = UPCAST(EGL_FilterDownscale, filter);
@@ -336,6 +309,48 @@ static bool egl_filterDownscaleSetup(EGL_Filter * filter,
if (!this->enable)
return false;
if (this->useDMA != useDMA)
{
if (!egl_shaderCompile(this->nearest,
b_shader_basic_vert , b_shader_basic_vert_size,
b_shader_downscale_frag,
b_shader_downscale_frag_size,
useDMA)
)
{
DEBUG_ERROR("Failed to compile the shader");
return false;
}
if (!egl_shaderCompile(this->linear,
b_shader_basic_vert, b_shader_basic_vert_size,
b_shader_downscale_linear_frag,
b_shader_downscale_linear_frag_size,
useDMA)
)
{
DEBUG_ERROR("Failed to compile the shader");
return false;
}
if (!egl_shaderCompile(this->lanczos2,
b_shader_basic_vert, b_shader_basic_vert_size,
b_shader_downscale_lanczos2_frag,
b_shader_downscale_lanczos2_frag_size,
useDMA)
)
{
DEBUG_ERROR("Failed to compile the shader");
return false;
}
this->uNearest.type = EGL_UNIFORM_TYPE_3F;
this->uNearest.location =
egl_shaderGetUniform(this->nearest, "uConfig");
this->useDMA = useDMA;
}
if (this->prepared &&
pixFmt == this->pixFmt &&
this->width == width &&
@@ -385,15 +400,15 @@ static bool egl_filterDownscalePrepare(EGL_Filter * filter)
return true;
}
static GLuint egl_filterDownscaleRun(EGL_Filter * filter,
EGL_FilterRects * rects, GLuint texture)
static EGL_Texture * egl_filterDownscaleRun(EGL_Filter * filter,
EGL_FilterRects * rects, EGL_Texture * texture)
{
EGL_FilterDownscale * this = UPCAST(EGL_FilterDownscale, filter);
egl_framebufferBind(this->fb);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
egl_textureBind(texture);
EGL_Shader * shader;

View File

@@ -1,6 +1,6 @@
/**
* Looking Glass
* Copyright © 2017-2022 The Looking Glass Authors
* Copyright © 2017-2023 The Looking Glass Authors
* https://looking-glass.io
*
* This program is free software; you can redistribute it and/or modify it
@@ -37,6 +37,7 @@ typedef struct EGL_FilterFFXCAS
EGL_Shader * shader;
bool enable;
int useDMA;
enum EGL_PixelFormat pixFmt;
unsigned int width, height;
float sharpness;
@@ -106,21 +107,14 @@ static bool egl_filterFFXCASInit(EGL_Filter ** filter)
return false;
}
this->useDMA = -1;
if (!egl_shaderInit(&this->shader))
{
DEBUG_ERROR("Failed to initialize the shader");
goto error_this;
}
if (!egl_shaderCompile(this->shader,
b_shader_basic_vert , b_shader_basic_vert_size,
b_shader_ffx_cas_frag, b_shader_ffx_cas_frag_size)
)
{
DEBUG_ERROR("Failed to compile the shader");
goto error_shader;
}
this->consts = countedBufferNew(8 * sizeof(GLuint));
if (!this->consts)
{
@@ -128,12 +122,6 @@ static bool egl_filterFFXCASInit(EGL_Filter ** filter)
goto error_shader;
}
egl_shaderSetUniforms(this->shader, &(EGL_Uniform) {
.type = EGL_UNIFORM_TYPE_4UIV,
.location = egl_shaderGetUniform(this->shader, "uConsts"),
.v = this->consts,
}, 1);
egl_filterFFXCASLoadState(&this->base);
if (!egl_framebufferInit(&this->fb))
@@ -220,13 +208,35 @@ static bool egl_filterFFXCASImguiConfig(EGL_Filter * filter)
}
static bool egl_filterFFXCASSetup(EGL_Filter * filter,
enum EGL_PixelFormat pixFmt, unsigned int width, unsigned int height)
enum EGL_PixelFormat pixFmt, unsigned int width, unsigned int height,
bool useDMA)
{
EGL_FilterFFXCAS * this = UPCAST(EGL_FilterFFXCAS, filter);
if (!this->enable)
return false;
if (this->useDMA != useDMA)
{
if (!egl_shaderCompile(this->shader,
b_shader_basic_vert , b_shader_basic_vert_size,
b_shader_ffx_cas_frag, b_shader_ffx_cas_frag_size,
useDMA)
)
{
DEBUG_ERROR("Failed to compile the shader");
return false;
}
egl_shaderSetUniforms(this->shader, &(EGL_Uniform) {
.type = EGL_UNIFORM_TYPE_4UIV,
.location = egl_shaderGetUniform(this->shader, "uConsts"),
.v = this->consts,
}, 1);
this->useDMA = useDMA;
}
if (pixFmt == this->pixFmt && this->width == width && this->height == height)
return true;
@@ -262,15 +272,15 @@ static bool egl_filterFFXCASPrepare(EGL_Filter * filter)
return true;
}
static GLuint egl_filterFFXCASRun(EGL_Filter * filter,
EGL_FilterRects * rects, GLuint texture)
static EGL_Texture * egl_filterFFXCASRun(EGL_Filter * filter,
EGL_FilterRects * rects, EGL_Texture * texture)
{
EGL_FilterFFXCAS * this = UPCAST(EGL_FilterFFXCAS, filter);
egl_framebufferBind(this->fb);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
egl_textureBind(texture);
glBindSampler(0, this->sampler);
egl_shaderUse(this->shader);

View File

@@ -1,6 +1,6 @@
/**
* Looking Glass
* Copyright © 2017-2022 The Looking Glass Authors
* Copyright © 2017-2023 The Looking Glass Authors
* https://looking-glass.io
*
* This program is free software; you can redistribute it and/or modify it
@@ -42,6 +42,7 @@ typedef struct EGL_FilterFFXFSR1
CountedBuffer * consts;
EGL_Uniform easuUniform[2], rcasUniform;
int useDMA;
enum EGL_PixelFormat pixFmt;
unsigned int width, height;
unsigned int inWidth, inHeight;
@@ -109,6 +110,8 @@ static bool egl_filterFFXFSR1Init(EGL_Filter ** filter)
return false;
}
this->useDMA = -1;
if (!egl_shaderInit(&this->easu))
{
DEBUG_ERROR("Failed to initialize the Easu shader");
@@ -121,18 +124,10 @@ static bool egl_filterFFXFSR1Init(EGL_Filter ** filter)
goto error_esau;
}
if (!egl_shaderCompile(this->easu,
b_shader_basic_vert , b_shader_basic_vert_size,
b_shader_ffx_fsr1_easu_frag, b_shader_ffx_fsr1_easu_frag_size)
)
{
DEBUG_ERROR("Failed to compile the Easu shader");
goto error_rcas;
}
if (!egl_shaderCompile(this->rcas,
b_shader_basic_vert , b_shader_basic_vert_size,
b_shader_ffx_fsr1_rcas_frag, b_shader_ffx_fsr1_rcas_frag_size)
b_shader_ffx_fsr1_rcas_frag, b_shader_ffx_fsr1_rcas_frag_size,
false)
)
{
DEBUG_ERROR("Failed to compile the Rcas shader");
@@ -148,14 +143,6 @@ static bool egl_filterFFXFSR1Init(EGL_Filter ** filter)
egl_filterFFXFSR1LoadState(&this->base);
this->easuUniform[0].type = EGL_UNIFORM_TYPE_4UIV;
this->easuUniform[0].location =
egl_shaderGetUniform(this->easu, "uConsts");
this->easuUniform[0].v = this->consts;
this->easuUniform[1].type = EGL_UNIFORM_TYPE_2F;
this->easuUniform[1].location =
egl_shaderGetUniform(this->easu, "uOutRes");
this->rcasUniform.type = EGL_UNIFORM_TYPE_4UI;
this->rcasUniform.location = egl_shaderGetUniform(this->rcas, "uConsts");
rcasUpdateUniform(this);
@@ -335,13 +322,37 @@ static void egl_filterFFXFSR1SetOutputResHint(EGL_Filter * filter,
}
static bool egl_filterFFXFSR1Setup(EGL_Filter * filter,
enum EGL_PixelFormat pixFmt, unsigned int width, unsigned int height)
enum EGL_PixelFormat pixFmt, unsigned int width, unsigned int height,
bool useDMA)
{
EGL_FilterFFXFSR1 * this = UPCAST(EGL_FilterFFXFSR1, filter);
if (!this->enable)
return false;
if (this->useDMA != useDMA)
{
if (!egl_shaderCompile(this->easu,
b_shader_basic_vert , b_shader_basic_vert_size,
b_shader_ffx_fsr1_easu_frag, b_shader_ffx_fsr1_easu_frag_size,
useDMA)
)
{
DEBUG_ERROR("Failed to compile the Easu shader");
return false;
}
this->easuUniform[0].type = EGL_UNIFORM_TYPE_4UIV;
this->easuUniform[0].location =
egl_shaderGetUniform(this->easu, "uConsts");
this->easuUniform[0].v = this->consts;
this->easuUniform[1].type = EGL_UNIFORM_TYPE_2F;
this->easuUniform[1].location =
egl_shaderGetUniform(this->easu, "uOutRes");
this->useDMA = useDMA;
}
this->active = this->width > width && this->height > height;
if (!this->active)
return false;
@@ -395,15 +406,15 @@ static bool egl_filterFFXFSR1Prepare(EGL_Filter * filter)
return true;
}
static GLuint egl_filterFFXFSR1Run(EGL_Filter * filter,
EGL_FilterRects * rects, GLuint texture)
static EGL_Texture * egl_filterFFXFSR1Run(EGL_Filter * filter,
EGL_FilterRects * rects, EGL_Texture * texture)
{
EGL_FilterFFXFSR1 * this = UPCAST(EGL_FilterFFXFSR1, filter);
// pass 1, Easu
egl_framebufferBind(this->easuFb);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
egl_textureBind(texture);
glBindSampler(0, this->sampler);
egl_shaderUse(this->easu);
egl_filterRectsRender(this->easu, rects);
@@ -412,7 +423,7 @@ static GLuint egl_filterFFXFSR1Run(EGL_Filter * filter,
// pass 2, Rcas
egl_framebufferBind(this->rcasFb);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
egl_textureBind(texture);
glBindSampler(0, this->sampler);
egl_shaderUse(this->rcas);
egl_filterRectsRender(this->rcas, rects);

View File

@@ -1,6 +1,6 @@
/**
* Looking Glass
* Copyright © 2017-2022 The Looking Glass Authors
* Copyright © 2017-2023 The Looking Glass Authors
* https://looking-glass.io
*
* This program is free software; you can redistribute it and/or modify it

View File

@@ -1,6 +1,6 @@
/**
* Looking Glass
* Copyright © 2017-2022 The Looking Glass Authors
* Copyright © 2017-2023 The Looking Glass Authors
* https://looking-glass.io
*
* This program is free software; you can redistribute it and/or modify it
@@ -100,9 +100,7 @@ void egl_framebufferBind(EGL_Framebuffer * this)
glViewport(0, 0, this->tex->format.width, this->tex->format.height);
}
GLuint egl_framebufferGetTexture(EGL_Framebuffer * this)
EGL_Texture * egl_framebufferGetTexture(EGL_Framebuffer * this)
{
GLuint output;
egl_textureGet(this->tex, &output, NULL, NULL);
return output;
return this->tex;
}

View File

@@ -1,6 +1,6 @@
/**
* Looking Glass
* Copyright © 2017-2022 The Looking Glass Authors
* Copyright © 2017-2023 The Looking Glass Authors
* https://looking-glass.io
*
* This program is free software; you can redistribute it and/or modify it
@@ -32,4 +32,4 @@ bool egl_framebufferSetup(EGL_Framebuffer * this, enum EGL_PixelFormat pixFmt,
void egl_framebufferBind(EGL_Framebuffer * this);
GLuint egl_framebufferGetTexture(EGL_Framebuffer * this);
EGL_Texture * egl_framebufferGetTexture(EGL_Framebuffer * this);

View File

@@ -10,4 +10,4 @@ function process(line, second) {
}
}
{ process($0, $2) }
{ process($0, $2) } END { print "\0"; }

View File

@@ -1,6 +1,6 @@
/**
* Looking Glass
* Copyright © 2017-2022 The Looking Glass Authors
* Copyright © 2017-2023 The Looking Glass Authors
* https://looking-glass.io
*
* This program is free software; you can redistribute it and/or modify it

View File

@@ -1,6 +1,6 @@
/**
* Looking Glass
* Copyright © 2017-2022 The Looking Glass Authors
* Copyright © 2017-2023 The Looking Glass Authors
* https://looking-glass.io
*
* This program is free software; you can redistribute it and/or modify it

View File

@@ -1,6 +1,6 @@
/**
* Looking Glass
* Copyright © 2017-2022 The Looking Glass Authors
* Copyright © 2017-2023 The Looking Glass Authors
* https://looking-glass.io
*
* This program is free software; you can redistribute it and/or modify it
@@ -49,7 +49,7 @@ static const EGL_FilterOps * EGL_Filters[] =
struct EGL_PostProcess
{
Vector filters;
GLuint output;
EGL_Texture * output;
unsigned int outputX, outputY;
_Atomic(bool) modified;
@@ -606,7 +606,7 @@ bool egl_postProcessConfigModified(EGL_PostProcess * this)
bool egl_postProcessRun(EGL_PostProcess * this, EGL_Texture * tex,
EGL_DesktopRects * rects, int desktopWidth, int desktopHeight,
unsigned int targetX, unsigned int targetY)
unsigned int targetX, unsigned int targetY, bool useDMA)
{
if (targetX == 0 && targetY == 0)
DEBUG_FATAL("targetX || targetY == 0");
@@ -614,8 +614,9 @@ bool egl_postProcessRun(EGL_PostProcess * this, EGL_Texture * tex,
EGL_Filter * lastFilter = NULL;
unsigned int sizeX, sizeY;
GLuint texture;
if (egl_textureGet(tex, &texture, &sizeX, &sizeY) != EGL_TEX_STATUS_OK)
//TODO: clean this up
GLuint _unused;
if (egl_textureGet(tex, &_unused, &sizeX, &sizeY) != EGL_TEX_STATUS_OK)
return false;
if (atomic_exchange(&this->modified, false))
@@ -636,11 +637,12 @@ bool egl_postProcessRun(EGL_PostProcess * this, EGL_Texture * tex,
};
EGL_Filter * filter;
EGL_Texture * texture = tex;
vector_forEach(filter, &this->filters)
{
egl_filterSetOutputResHint(filter, targetX, targetY);
if (!egl_filterSetup(filter, tex->format.pixFmt, sizeX, sizeY) ||
if (!egl_filterSetup(filter, tex->format.pixFmt, sizeX, sizeY, useDMA) ||
!egl_filterPrepare(filter))
continue;
@@ -651,6 +653,9 @@ bool egl_postProcessRun(EGL_PostProcess * this, EGL_Texture * tex,
egl_filterRelease(lastFilter);
lastFilter = filter;
// the first filter to run will convert to a normal texture
useDMA = false;
}
this->output = texture;
@@ -659,7 +664,7 @@ bool egl_postProcessRun(EGL_PostProcess * this, EGL_Texture * tex,
return true;
}
GLuint egl_postProcessGetOutput(EGL_PostProcess * this,
EGL_Texture * egl_postProcessGetOutput(EGL_PostProcess * this,
unsigned int * outputX, unsigned int * outputY)
{
*outputX = this->outputX;

View File

@@ -1,6 +1,6 @@
/**
* Looking Glass
* Copyright © 2017-2022 The Looking Glass Authors
* Copyright © 2017-2023 The Looking Glass Authors
* https://looking-glass.io
*
* This program is free software; you can redistribute it and/or modify it
@@ -41,7 +41,7 @@ bool egl_postProcessConfigModified(EGL_PostProcess * this);
* targetX/Y is the final target output dimension hint if scalers are present */
bool egl_postProcessRun(EGL_PostProcess * this, EGL_Texture * tex,
EGL_DesktopRects * rects, int desktopWidth, int desktopHeight,
unsigned int targetX, unsigned int targetY);
unsigned int targetX, unsigned int targetY, bool useDMA);
GLuint egl_postProcessGetOutput(EGL_PostProcess * this,
EGL_Texture * egl_postProcessGetOutput(EGL_PostProcess * this,
unsigned int * outputX, unsigned int * outputY);

View File

@@ -1,6 +1,6 @@
/**
* Looking Glass
* Copyright © 2017-2022 The Looking Glass Authors
* Copyright © 2017-2023 The Looking Glass Authors
* https://looking-glass.io
*
* This program is free software; you can redistribute it and/or modify it
@@ -64,7 +64,8 @@ void egl_shaderFree(EGL_Shader ** shader)
*shader = NULL;
}
bool egl_shaderLoad(EGL_Shader * this, const char * vertex_file, const char * fragment_file)
bool egl_shaderLoad(EGL_Shader * this,
const char * vertex_file, const char * fragment_file, bool useDMA)
{
char * vertex_code, * fragment_code;
size_t vertex_size, fragment_size;
@@ -86,13 +87,16 @@ bool egl_shaderLoad(EGL_Shader * this, const char * vertex_file, const char * fr
DEBUG_INFO("Loaded fragment shader: %s", fragment_file);
bool ret = egl_shaderCompile(this, vertex_code, vertex_size, fragment_code, fragment_size);
bool ret = egl_shaderCompile(this,
vertex_code, vertex_size, fragment_code, fragment_size,
useDMA);
free(vertex_code);
free(fragment_code);
return ret;
}
bool egl_shaderCompile(EGL_Shader * this, const char * vertex_code,
static bool shaderCompile(EGL_Shader * this, const char * vertex_code,
size_t vertex_size, const char * fragment_code, size_t fragment_size)
{
if (this->hasShader)
@@ -204,6 +208,64 @@ bool egl_shaderCompile(EGL_Shader * this, const char * vertex_code,
return true;
}
bool egl_shaderCompile(EGL_Shader * this, const char * vertex_code,
size_t vertex_size, const char * fragment_code, size_t fragment_size,
bool useDMA)
{
if (useDMA)
{
const char * search = "sampler2D";
const char * replace = "samplerExternalOES";
const char * src = fragment_code;
int instances = 0;
while((src = strstr(src, search)))
{
++instances;
src += strlen(search);
}
const int diff = (strlen(replace) - strlen(search)) * instances;
char * newCode = malloc(fragment_size + diff + 1);
if (!newCode)
{
DEBUG_ERROR("Out of memory");
return false;
}
src = fragment_code;
char * dst = newCode;
for(int i = 0; i < instances; ++i)
{
const char * pos = strstr(src, search);
const int offset = pos - src;
memcpy(dst, src, offset);
dst += offset;
src = pos + strlen(search);
memcpy(dst, replace, strlen(replace));
dst += strlen(replace);
}
const int final = fragment_size - (src - fragment_code);
memcpy(dst, src, final);
dst[final] = 0;
bool result = shaderCompile(
this,
vertex_code, vertex_size,
newCode , fragment_size + diff);
free(newCode);
return result;
}
return shaderCompile(this,
vertex_code , vertex_size,
fragment_code, fragment_size);
}
void egl_shaderSetUniforms(EGL_Shader * this, EGL_Uniform * uniforms, int count)
{
egl_shaderFreeUniforms(this);

View File

@@ -1,6 +1,6 @@
/**
* Looking Glass
* Copyright © 2017-2022 The Looking Glass Authors
* Copyright © 2017-2023 The Looking Glass Authors
* https://looking-glass.io
*
* This program is free software; you can redistribute it and/or modify it
@@ -97,10 +97,11 @@ bool egl_shaderInit(EGL_Shader ** shader);
void egl_shaderFree(EGL_Shader ** shader);
bool egl_shaderLoad(EGL_Shader * model, const char * vertex_file,
const char * fragment_file);
const char * fragment_file, bool useDMA);
bool egl_shaderCompile(EGL_Shader * model, const char * vertex_code,
size_t vertex_size, const char * fragment_code, size_t fragment_size);
size_t vertex_size, const char * fragment_code, size_t fragment_size,
bool useDMA);
void egl_shaderSetUniforms(EGL_Shader * shader, EGL_Uniform * uniforms,
int count);

View File

@@ -1,5 +1,5 @@
#version 300 es
precision mediump float;
precision highp float;
layout(location = 0) in vec2 vertex;
out vec2 fragCoord;

View File

@@ -1,16 +1,21 @@
#if __VERSION__ == 300
vec4 textureGather(sampler2D tex, vec2 uv, int comp)
{
vec4 c0 = textureOffset(tex, uv, ivec2(0,1));
vec4 c1 = textureOffset(tex, uv, ivec2(1,1));
vec4 c2 = textureOffset(tex, uv, ivec2(1,0));
vec4 c3 = textureOffset(tex, uv, ivec2(0,0));
vec2 res = vec2(textureSize(tex, 0));
ivec2 p = ivec2((uv * res) - 0.5f);
// NOTE: we can't use texelFecthOffset because sampler2D may actually be samplerExternalOES
vec4 c0 = texelFetch(tex, p+ivec2(0,1), 0);
vec4 c1 = texelFetch(tex, p+ivec2(1,1), 0);
vec4 c2 = texelFetch(tex, p+ivec2(1,0), 0);
vec4 c3 = texelFetch(tex, p+ivec2(0,0), 0);
return vec4(c0[comp], c1[comp], c2[comp],c3[comp]);
}
#elif __VERSION__ < 300
vec4 textureGather(sampler2D tex, vec2 uv, int comp)
{
vec4 c3 = texture2D(tex, uv);
vec4 c3 = texture(tex, uv);
return vec4(c3[comp], c3[comp], c3[comp],c3[comp]);
}
#endif

View File

@@ -1,5 +1,5 @@
#version 300 es
precision mediump float;
precision highp float;
layout(location = 0) in vec3 vertexPosition_modelspace;
layout(location = 1) in vec2 vertexUV;

View File

@@ -1,5 +1,5 @@
#version 300 es
precision mediump float;
precision highp float;
in vec2 uv;
out vec4 color;

View File

@@ -1,5 +1,5 @@
#version 300 es
precision mediump float;
precision highp float;
#include "color_blind.h"

View File

@@ -1,5 +1,5 @@
#version 300 es
precision mediump float;
precision highp float;
out vec4 color;

View File

@@ -1,5 +1,5 @@
#version 300 es
precision mediump float;
precision highp float;
layout(location = 0) in vec2 vertex;
out vec2 uv;

View File

@@ -1,5 +1,7 @@
#version 300 es
precision mediump float;
#extension GL_OES_EGL_image_external_essl3 : enable
precision highp float;
#define EGL_SCALE_AUTO 0
#define EGL_SCALE_NEAREST 1
@@ -7,6 +9,7 @@ precision mediump float;
#define EGL_SCALE_MAX 3
#include "color_blind.h"
#include "hdr.h"
in vec2 uv;
out vec4 color;
@@ -17,21 +20,32 @@ uniform int scaleAlgo;
uniform float nvGain;
uniform int cbMode;
uniform bool isHDR;
uniform bool mapHDRtoSDR;
uniform float mapHDRGain;
uniform bool mapHDRPQ;
void main()
{
switch (scaleAlgo)
{
case EGL_SCALE_NEAREST:
{
vec2 ts = vec2(textureSize(sampler1, 0));
color = texelFetch(sampler1, ivec2(uv * ts), 0);
break;
}
case EGL_SCALE_LINEAR:
{
color = texture(sampler1, uv);
break;
}
}
if (isHDR && mapHDRtoSDR)
color.rgb = mapToSDR(color.rgb, mapHDRGain, mapHDRPQ);
if (cbMode > 0)
color = cbTransform(color, cbMode);

View File

@@ -1,10 +1,12 @@
#version 300 es
precision mediump float;
#extension GL_OES_EGL_image_external_essl3 : enable
precision highp float;
in vec2 fragCoord;
out vec4 fragColor;
uniform sampler2D texture;
uniform sampler2D sampler1;
uniform vec3 uConfig;
void main()
@@ -13,7 +15,7 @@ void main()
float vOffset = uConfig.y;
float hOffset = uConfig.z;
vec2 inRes = vec2(textureSize(texture, 0));
vec2 inRes = vec2(textureSize(sampler1, 0));
ivec2 point = ivec2(
(floor((fragCoord * inRes) / pixelSize) * pixelSize) +
pixelSize / 2.0f
@@ -22,5 +24,5 @@ void main()
point.x += int(pixelSize * hOffset);
point.y += int(pixelSize * vOffset);
fragColor = texelFetch(texture, point, 0);
fragColor = texelFetch(sampler1, point, 0);
}

View File

@@ -1,12 +1,14 @@
#version 300 es
precision mediump float;
#extension GL_OES_EGL_image_external_essl3 : enable
precision highp float;
#define PI 3.141592653589793
in vec2 fragCoord;
out vec4 fragColor;
uniform sampler2D texture;
uniform sampler2D sampler1;
float sinc(float x)
{
return x == 0.0 ? 1.0 : sin(x * PI) / (x * PI);
@@ -24,7 +26,7 @@ float lanczos(vec2 v)
void main()
{
vec2 size = vec2(textureSize(texture, 0));
vec2 size = vec2(textureSize(sampler1, 0));
vec2 pos = fragCoord * size;
vec2 invSize = 1.0 / size;
vec2 uvc = floor(pos) + vec2(0.5, 0.5);
@@ -54,7 +56,7 @@ void main()
vec3 color = vec3(0.0);
for (int i = 0; i < 9; ++i)
color += texture2D(texture, uvs[i] * invSize).rgb * factors[i];
color += texture(sampler1, uvs[i] * invSize).rgb * factors[i];
fragColor = vec4(color, 1.0);
}

View File

@@ -1,12 +1,14 @@
#version 300 es
precision mediump float;
#extension GL_OES_EGL_image_external_essl3 : enable
precision highp float;
in vec2 fragCoord;
out vec4 fragColor;
uniform sampler2D texture;
uniform sampler2D sampler1;
void main()
{
fragColor = texture2D(texture, fragCoord);
fragColor = texture(sampler1, fragCoord);
}

View File

@@ -1,12 +1,14 @@
#version 300 es
precision mediump float;
#extension GL_OES_EGL_image_external_essl3 : enable
precision highp float;
#include "compat.h"
in vec2 fragCoord;
out vec4 fragColor;
uniform sampler2D texture;
uniform sampler2D sampler1;
uniform uvec4 uConsts[2];
#define A_GPU 1
@@ -16,7 +18,7 @@ uniform uvec4 uConsts[2];
vec3 imageLoad(ivec2 point)
{
return texelFetch(texture, point, 0).rgb;
return texelFetch(sampler1, point, 0).rgb;
}
AF3 CasLoad(ASU2 p)
@@ -30,7 +32,7 @@ void CasInput(inout AF1 r,inout AF1 g,inout AF1 b) {}
void main()
{
vec2 res = vec2(textureSize(texture, 0));
vec2 res = vec2(textureSize(sampler1, 0));
uvec2 point = uvec2(fragCoord * res);
CasFilter(

View File

@@ -1,12 +1,14 @@
#version 300 es
precision mediump float;
#extension GL_OES_EGL_image_external_essl3 : enable
precision highp float;
#include "compat.h"
in vec2 fragCoord;
out vec4 fragColor;
uniform sampler2D texture;
uniform sampler2D sampler1;
uniform vec2 uOutRes;
uniform uvec4 uConsts[4];
@@ -18,20 +20,9 @@ uniform uvec4 uConsts[4];
#define FSR_EASU_F 1
vec4 _textureGather(sampler2D tex, vec2 uv, int comp)
{
vec2 res = vec2(textureSize(tex, 0));
ivec2 p = ivec2((uv * res) - 0.5f);
vec4 c0 = texelFetchOffset(tex, p, 0, ivec2(0,1));
vec4 c1 = texelFetchOffset(tex, p, 0, ivec2(1,1));
vec4 c2 = texelFetchOffset(tex, p, 0, ivec2(1,0));
vec4 c3 = texelFetchOffset(tex, p, 0, ivec2(0,0));
return vec4(c0[comp], c1[comp], c2[comp],c3[comp]);
}
AF4 FsrEasuRF(AF2 p){return AF4(_textureGather(texture, p, 0));}
AF4 FsrEasuGF(AF2 p){return AF4(_textureGather(texture, p, 1));}
AF4 FsrEasuBF(AF2 p){return AF4(_textureGather(texture, p, 2));}
AF4 FsrEasuRF(AF2 p){return AF4(textureGather(sampler1, p, 0));}
AF4 FsrEasuGF(AF2 p){return AF4(textureGather(sampler1, p, 1));}
AF4 FsrEasuBF(AF2 p){return AF4(textureGather(sampler1, p, 2));}
#include "ffx_fsr1.h"

View File

@@ -1,12 +1,12 @@
#version 300 es
precision mediump float;
precision highp float;
#include "compat.h"
in vec2 fragCoord;
out vec4 fragColor;
uniform sampler2D texture;
uniform sampler2D sampler1;
uniform uvec4 uConsts;
#define A_GPU 1
@@ -15,7 +15,7 @@ uniform uvec4 uConsts;
#include "ffx_a.h"
AF4 FsrRcasLoadF(ASU2 p) { return texelFetch(texture, ASU2(p), 0); }
AF4 FsrRcasLoadF(ASU2 p) { return texelFetch(sampler1, ASU2(p), 0); }
void FsrRcasInputF(inout AF1 r, inout AF1 g, inout AF1 b) {}
#define FSR_RCAS_F 1
@@ -24,7 +24,7 @@ void FsrRcasInputF(inout AF1 r, inout AF1 g, inout AF1 b) {}
void main()
{
vec2 inRes = vec2(textureSize(texture, 0));
vec2 inRes = vec2(textureSize(sampler1, 0));
uvec2 point = uvec2(fragCoord * (inRes + 0.5f));
FsrRcasF(fragColor.r, fragColor.g, fragColor.b, point, uConsts);

View File

@@ -0,0 +1,108 @@
/*
_______ _____ __ __ ____ __
/ ____(_)___ ___ ____ ___ ____ _ / ___// /_ ____ _____/ /__ _____ / __ \____ ______/ /__
/ / / / __ \/ _ \/ __ `__ \/ __ `/ \__ \/ __ \/ __ `/ __ / _ \/ ___/ / /_/ / __ `/ ___/ //_/
/ /___/ / / / / __/ / / / / / /_/ / ___/ / / / / /_/ / /_/ / __/ / / ____/ /_/ / /__/ ,<
\____/_/_/ /_/\___/_/ /_/ /_/\__,_/ /____/_/ /_/\__,_/\__,_/\___/_/ /_/ \__,_/\___/_/|_|
http://en.sbence.hu/ Shader: Try to get the SDR part of HDR content
*/
/**
* Translated to GLSL, original source is:
* https://github.com/VoidXH/Cinema-Shader-Pack
*/
// Configuration ---------------------------------------------------------------
const float knee = 0.75; // Compressor knee position
const float ratio = 4.0; // Compressor ratio: 1 = disabled, <1 = expander
// -----------------------------------------------------------------------------
// Precalculated values
const float compressor = 1.0 / ratio;
// PQ constants
const float m1inv = 16384.0 / 2610.0;
const float m2inv = 32.0 / 2523.0;
const float c1 = 3424.0 / 4096.0;
const float c2 = 2413.0 / 128.0;
const float c3 = 2392.0 / 128.0;
float minGain(vec3 pixel) { return min(pixel.r, min(pixel.g, pixel.b)); }
float maxGain(vec3 pixel) { return max(pixel.r, max(pixel.g, pixel.b)); }
float midGain(vec3 pixel)
{
return pixel.r < pixel.g ?
(pixel.r < pixel.b ?
min(pixel.g, pixel.b) : // min = r
min(pixel.r, pixel.g)) : // min = b
(pixel.g < pixel.b ?
min(pixel.r, pixel.b) : // min = g
min(pixel.r, pixel.g)); // min = b
}
vec3 compress(vec3 pixel)
{
float maxGain = maxGain(pixel);
return pixel * (maxGain < knee ? maxGain :
knee + max(maxGain - knee, 0.0) * compressor) / maxGain;
}
vec3 fixClip(vec3 pixel)
{
// keep the (mid - min) / (max - min) ratio
float preMin = minGain(pixel);
float preMid = midGain(pixel);
float preMax = maxGain(pixel);
vec3 clip = clamp(pixel, 0.0, 1.0);
float postMin = minGain(clip);
float postMid = midGain(clip);
float postMax = maxGain(clip);
float ratio = (preMid - preMin) / (preMax - preMin);
float newMid = ratio * (postMax - postMin) + postMin;
return vec3(clip.r != postMid ? clip.r : newMid,
clip.g != postMid ? clip.g : newMid,
clip.b != postMid ? clip.b : newMid);
}
// Returns luminance in nits
vec3 pq2lin(vec3 pq, float gain)
{
vec3 p = pow(pq, vec3(m2inv));
vec3 d = max(p - c1, vec3(0.0)) / (c2 - c3 * p);
return pow(d, vec3(m1inv)) * gain;
}
vec3 srgb2lin(vec3 c)
{
vec3 v = c / 12.92;
vec3 v2 = pow((c + vec3(0.055)) / 1.055, vec3(2.4));
vec3 threshold = vec3(0.04045);
vec3 result = mix(v, v2, greaterThanEqual(c, threshold));
return result;
}
vec3 lin2srgb(vec3 c)
{
vec3 v = c * 12.92;
vec3 v2 = pow(c, vec3(1.0/2.4)) * 1.055 - 0.055;
vec3 threshold = vec3(0.0031308);
vec3 result = mix(v, v2, greaterThanEqual(c, threshold));
return result;
}
// in linear space
vec3 bt2020to709(vec3 bt2020)
{
return vec3(
bt2020.r * 1.6605 + bt2020.g * -0.5876 + bt2020.b * -0.0728,
bt2020.r * -0.1246 + bt2020.g * 1.1329 + bt2020.b * -0.0083,
bt2020.r * -0.0182 + bt2020.g * -0.1006 + bt2020.b * 1.1187);
}
vec3 mapToSDR(vec3 color, float gain, bool pq)
{
if (pq)
color = pq2lin(color.rgb, gain);
color = bt2020to709(color);
return lin2srgb(compress(color));
}

View File

@@ -1,6 +1,6 @@
/**
* Looking Glass
* Copyright © 2017-2022 The Looking Glass Authors
* Copyright © 2017-2023 The Looking Glass Authors
* https://looking-glass.io
*
* This program is free software; you can redistribute it and/or modify it
@@ -25,6 +25,7 @@
#include "shader.h"
#include "common/framebuffer.h"
#include "common/debug.h"
#include "common/array.h"
#include <EGL/egl.h>
#include <EGL/eglext.h>
@@ -76,6 +77,7 @@ bool egl_textureInit(EGL_Texture ** texture_, EGLDisplay * display,
glSamplerParameteri(this->sampler, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glSamplerParameteri(this->sampler, GL_TEXTURE_WRAP_S , GL_CLAMP_TO_EDGE);
glSamplerParameteri(this->sampler, GL_TEXTURE_WRAP_T , GL_CLAMP_TO_EDGE);
return true;
}
@@ -203,14 +205,7 @@ enum EGL_TexStatus egl_textureProcess(EGL_Texture * this)
enum EGL_TexStatus egl_textureBind(EGL_Texture * this)
{
GLuint tex;
EGL_TexStatus status;
if ((status = this->ops.get(this, &tex)) != EGL_TEX_STATUS_OK)
return status;
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, tex);
glBindSampler(0, this->sampler);
return EGL_TEX_STATUS_OK;
return this->ops.bind(this);
}

View File

@@ -1,6 +1,6 @@
/**
* Looking Glass
* Copyright © 2017-2022 The Looking Glass Authors
* Copyright © 2017-2023 The Looking Glass Authors
* https://looking-glass.io
*
* This program is free software; you can redistribute it and/or modify it
@@ -93,6 +93,9 @@ typedef struct EGL_TextureOps
/* get the texture for use */
enum EGL_TexStatus (*get)(EGL_Texture * texture, GLuint * tex);
/* bind the texture for use */
enum EGL_TexStatus (*bind)(EGL_Texture * texture);
}
EGL_TextureOps;

View File

@@ -1,6 +1,6 @@
/**
* Looking Glass
* Copyright © 2017-2022 The Looking Glass Authors
* Copyright © 2017-2023 The Looking Glass Authors
* https://looking-glass.io
*
* This program is free software; you can redistribute it and/or modify it
@@ -292,6 +292,19 @@ EGL_TexStatus egl_texBufferStreamGet(EGL_Texture * texture, GLuint * tex)
return EGL_TEX_STATUS_OK;
}
EGL_TexStatus egl_texBufferBind(EGL_Texture * texture)
{
GLuint tex;
EGL_TexStatus status;
if ((status = texture->ops.get(texture, &tex)) != EGL_TEX_STATUS_OK)
return status;
glBindTexture(GL_TEXTURE_2D, tex);
return EGL_TEX_STATUS_OK;
}
const EGL_TextureOps EGL_TextureBuffer =
{
.init = egl_texBufferInit,
@@ -299,7 +312,8 @@ const EGL_TextureOps EGL_TextureBuffer =
.setup = egl_texBufferSetup,
.update = egl_texBufferUpdate,
.process = egl_texBufferProcess,
.get = egl_texBufferGet
.get = egl_texBufferGet,
.bind = egl_texBufferBind
};
const EGL_TextureOps EGL_TextureBufferStream =
@@ -309,5 +323,6 @@ const EGL_TextureOps EGL_TextureBufferStream =
.setup = egl_texBufferStreamSetup,
.update = egl_texBufferStreamUpdate,
.process = egl_texBufferStreamProcess,
.get = egl_texBufferStreamGet
.get = egl_texBufferStreamGet,
.bind = egl_texBufferBind
};

View File

@@ -1,6 +1,6 @@
/**
* Looking Glass
* Copyright © 2017-2022 The Looking Glass Authors
* Copyright © 2017-2023 The Looking Glass Authors
* https://looking-glass.io
*
* This program is free software; you can redistribute it and/or modify it
@@ -48,6 +48,7 @@ void egl_texBufferFree(EGL_Texture * texture_);
bool egl_texBufferSetup(EGL_Texture * texture_, const EGL_TexSetup * setup);
EGL_TexStatus egl_texBufferProcess(EGL_Texture * texture_);
EGL_TexStatus egl_texBufferGet(EGL_Texture * texture_, GLuint * tex);
EGL_TexStatus egl_texBufferBind(EGL_Texture * texture_);
bool egl_texBufferStreamInit(EGL_Texture ** texture_, EGL_TexType type,
EGLDisplay * display);

View File

@@ -1,6 +1,6 @@
/**
* Looking Glass
* Copyright © 2017-2022 The Looking Glass Authors
* Copyright © 2017-2023 The Looking Glass Authors
* https://looking-glass.io
*
* This program is free software; you can redistribute it and/or modify it
@@ -46,12 +46,26 @@ EGL_TextureOps EGL_TextureDMABUF;
// internal functions
static void egl_texDMABUFCleanup(TexDMABUF * this)
static void egl_texDMABUFCleanup(EGL_Texture * texture)
{
TextureBuffer * parent = UPCAST(TextureBuffer, texture);
TexDMABUF * this = UPCAST(TexDMABUF , parent);
struct FdImage * image;
vector_forEachRef(image, &this->images)
g_egl_dynProcs.eglDestroyImage(this->display, image->image);
vector_clear(&this->images);
egl_texUtilFreeBuffers(parent->buf, parent->texCount);
if (parent->tex[0])
glDeleteTextures(parent->texCount, parent->tex);
if (parent->sync)
{
glDeleteSync(parent->sync);
parent->sync = 0;
}
}
// dmabuf functions
@@ -92,7 +106,7 @@ static void egl_texDMABUFFree(EGL_Texture * texture)
TextureBuffer * parent = UPCAST(TextureBuffer, texture);
TexDMABUF * this = UPCAST(TexDMABUF , parent);
egl_texDMABUFCleanup(this);
egl_texDMABUFCleanup(texture);
vector_destroy(&this->images);
egl_texBufferFree(&parent->base);
@@ -102,11 +116,27 @@ static void egl_texDMABUFFree(EGL_Texture * texture)
static bool egl_texDMABUFSetup(EGL_Texture * texture, const EGL_TexSetup * setup)
{
TextureBuffer * parent = UPCAST(TextureBuffer, texture);
TexDMABUF * this = UPCAST(TexDMABUF , parent);
egl_texDMABUFCleanup(this);
egl_texDMABUFCleanup(texture);
return egl_texBufferSetup(&parent->base, setup);
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,
texture->format.width,
texture->format.height,
0,
texture->format.format,
texture->format.dataType,
NULL);
}
glBindTexture(GL_TEXTURE_EXTERNAL_OES, 0);
parent->rIndex = -1;
return true;
}
static bool egl_texDMABUFUpdate(EGL_Texture * texture,
@@ -173,8 +203,8 @@ static bool egl_texDMABUFUpdate(EGL_Texture * texture,
INTERLOCKED_SECTION(parent->copyLock,
{
glBindTexture(GL_TEXTURE_2D, parent->tex[parent->bufIndex]);
g_egl_dynProcs.glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image);
glBindTexture(GL_TEXTURE_EXTERNAL_OES, parent->tex[parent->bufIndex]);
g_egl_dynProcs.glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, image);
if (parent->sync)
glDeleteSync(parent->sync);
@@ -238,6 +268,18 @@ static EGL_TexStatus egl_texDMABUFGet(EGL_Texture * texture, GLuint * tex)
return EGL_TEX_STATUS_OK;
}
static EGL_TexStatus egl_texDMABUFBind(EGL_Texture * texture)
{
GLuint tex;
EGL_TexStatus status;
if ((status = egl_texDMABUFGet(texture, &tex)) != EGL_TEX_STATUS_OK)
return status;
glBindTexture(GL_TEXTURE_EXTERNAL_OES, tex);
return EGL_TEX_STATUS_OK;
}
EGL_TextureOps EGL_TextureDMABUF =
{
.init = egl_texDMABUFInit,
@@ -245,5 +287,6 @@ EGL_TextureOps EGL_TextureDMABUF =
.setup = egl_texDMABUFSetup,
.update = egl_texDMABUFUpdate,
.process = egl_texDMABUFProcess,
.get = egl_texDMABUFGet
.get = egl_texDMABUFGet,
.bind = egl_texDMABUFBind
};

View File

@@ -1,6 +1,6 @@
/**
* Looking Glass
* Copyright © 2017-2022 The Looking Glass Authors
* Copyright © 2017-2023 The Looking Glass Authors
* https://looking-glass.io
*
* This program is free software; you can redistribute it and/or modify it
@@ -109,6 +109,7 @@ static bool egl_texFBUpdate(EGL_Texture * texture, const EGL_TexUpdate * update)
rectsFramebufferToBuffer(
damage->rects,
damage->count,
texture->format.bpp,
parent->buf[parent->bufIndex].map,
texture->format.stride,
texture->format.height,
@@ -147,5 +148,6 @@ EGL_TextureOps EGL_TextureFrameBuffer =
.setup = egl_texFBSetup,
.update = egl_texFBUpdate,
.process = egl_texBufferStreamProcess,
.get = egl_texBufferStreamGet
.get = egl_texBufferStreamGet,
.bind = egl_texBufferBind
};

View File

@@ -1,6 +1,6 @@
/**
* Looking Glass
* Copyright © 2017-2022 The Looking Glass Authors
* Copyright © 2017-2023 The Looking Glass Authors
* https://looking-glass.io
*
* This program is free software; you can redistribute it and/or modify it
@@ -53,7 +53,7 @@ bool egl_texUtilGetFormat(const EGL_TexSetup * setup, EGL_TexFormat * fmt)
fmt->format = GL_RGBA;
fmt->intFormat = GL_RGB10_A2;
fmt->dataType = GL_UNSIGNED_INT_2_10_10_10_REV;
fmt->fourcc = DRM_FORMAT_BGRA1010102;
fmt->fourcc = DRM_FORMAT_BGRA2101010;
break;
case EGL_PF_RGBA16F:

View File

@@ -1,6 +1,6 @@
/**
* Looking Glass
* Copyright © 2017-2022 The Looking Glass Authors
* Copyright © 2017-2023 The Looking Glass Authors
* https://looking-glass.io
*
* This program is free software; you can redistribute it and/or modify it
@@ -64,7 +64,7 @@ void egl_texUtilUnmapBuffer(EGL_TexBuffer * buffer);
((uint32_t)(c) << 16) | ((uint32_t)(d) << 24))
#define DRM_FORMAT_ARGB8888 fourcc_code('A', 'R', '2', '4')
#define DRM_FORMAT_ABGR8888 fourcc_code('A', 'B', '2', '4')
#define DRM_FORMAT_BGRA1010102 fourcc_code('B', 'A', '3', '0')
#define DRM_FORMAT_BGRA2101010 fourcc_code('A', 'B', '3', '0')
#define DRM_FORMAT_ABGR16161616F fourcc_code('A', 'B', '4', 'H')
#define DRM_FORMAT_MOD_VENDOR_NONE 0

View File

@@ -1,6 +1,6 @@
/**
* Looking Glass
* Copyright © 2017-2022 The Looking Glass Authors
* Copyright © 2017-2023 The Looking Glass Authors
* https://looking-glass.io
*
* This program is free software; you can redistribute it and/or modify it

Some files were not shown because too many files have changed in this diff Show More