mirror of
https://github.com/gnif/LookingGlass.git
synced 2026-01-16 16:52:28 +00:00
Compare commits
1 Commits
dxgi-hlsl
...
host-downs
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
655c993c5b |
4
.github/CODEOWNERS
vendored
4
.github/CODEOWNERS
vendored
@@ -1,4 +0,0 @@
|
||||
# Jonathan Rubenstein (JJRcop)
|
||||
# - Primary documentation manager. Does not require direct approval for every
|
||||
# - change, but should be consulted for large additions and changes.
|
||||
/doc/ jrubcop@gmail.com
|
||||
18
.github/workflows/build.yml
vendored
18
.github/workflows/build.yml
vendored
@@ -12,7 +12,7 @@ jobs:
|
||||
wayland_shell: [xdg-shell, libdecor]
|
||||
build_type: [Release, Debug]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v1
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Install libdecor PPA
|
||||
@@ -62,7 +62,7 @@ jobs:
|
||||
module:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v1
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Build kernel module
|
||||
@@ -73,7 +73,7 @@ jobs:
|
||||
host-linux:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v1
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Install PipeWire repository
|
||||
@@ -97,9 +97,9 @@ jobs:
|
||||
make -j$(nproc)
|
||||
|
||||
host-windows-cross:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v1
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Update apt
|
||||
@@ -130,7 +130,7 @@ jobs:
|
||||
host-windows-native:
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v1
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Configure Windows host for native MinGW-w64
|
||||
@@ -153,7 +153,7 @@ jobs:
|
||||
matrix:
|
||||
cc: [gcc, clang]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v1
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Update apt
|
||||
@@ -183,8 +183,8 @@ jobs:
|
||||
sudo apt-get update
|
||||
- name: Install docs dependencies
|
||||
run: |
|
||||
sudo apt-get install python3-sphinx python3-sphinx-rtd-theme \
|
||||
python3-sphinxcontrib.spelling
|
||||
sudo apt-get install python3-sphinx python3-sphinx-rtd-theme
|
||||
sudo pip3 install sphinxcontrib-spelling
|
||||
- name: Build docs
|
||||
run: |
|
||||
cd doc
|
||||
|
||||
5
.gitignore
vendored
5
.gitignore
vendored
@@ -10,8 +10,3 @@ module/modules.order
|
||||
*/build
|
||||
__pycache__
|
||||
*.py[co]
|
||||
*/.vs
|
||||
idd/Debug
|
||||
idd/x64
|
||||
idd/LGIdd/x64
|
||||
idd/LGIdd/Debug
|
||||
|
||||
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -10,6 +10,3 @@
|
||||
[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
|
||||
|
||||
9
AUTHORS
9
AUTHORS
@@ -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> (thrifty-txt)
|
||||
Ali Abdel-Qader <abdelqaderali@protonmail.com>
|
||||
Jack Karamanian <karamanian.jack@gmail.com>
|
||||
Mikko Rasa <tdb@tdb.fi> (DataBeaver)
|
||||
Omar Pakker <Omar007@users.noreply.github.com> (Omar007)
|
||||
@@ -60,10 +60,3 @@ Johnathon Paul Weaver <weaver123_johnathon@hotmail.com> (8BallBomBom)
|
||||
Chris Spencer <spencercw@gmail.com> (spencercw)
|
||||
Mark Boorer <markboo99@gmail.com> (Shootfast)
|
||||
babbaj <babbaj45@gmail.com> (Babbaj)
|
||||
Matthew McMullin <matthew@mcmullin.one> (matthewjmc)
|
||||
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)
|
||||
|
||||
@@ -4,13 +4,13 @@ project(looking-glass-client C CXX)
|
||||
get_filename_component(PROJECT_TOP "${PROJECT_SOURCE_DIR}/.." ABSOLUTE)
|
||||
|
||||
if(PROJECT_SOURCE_DIR STREQUAL PROJECT_BINARY_DIR)
|
||||
message(FATAL_ERROR
|
||||
"\n"
|
||||
"In-source builds are not supported\n"
|
||||
"See build instructions provided in: "
|
||||
"${PROJECT_TOP}/doc/build.rst\n"
|
||||
"Refusing to continue"
|
||||
)
|
||||
message(FATAL_ERROR
|
||||
"\n"
|
||||
"In-source builds are not supported\n"
|
||||
"See build instructions provided in: "
|
||||
"${PROJECT_TOP}/doc/build.rst\n"
|
||||
"Refusing to continue"
|
||||
)
|
||||
endif()
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH "${PROJECT_TOP}/cmake/" "${PROJECT_SOURCE_DIR}/cmake/")
|
||||
@@ -66,7 +66,7 @@ add_compile_options(
|
||||
"-Wextra"
|
||||
"-Wno-sign-compare"
|
||||
"-Wno-unused-parameter"
|
||||
"$<$<COMPILE_LANGUAGE:C>:-Wstrict-prototypes>"
|
||||
"-Wstrict-prototypes"
|
||||
"$<$<C_COMPILER_ID:GNU>:-Wimplicit-fallthrough=2>"
|
||||
"-Werror"
|
||||
"-Wfatal-errors"
|
||||
@@ -101,57 +101,52 @@ add_definitions(-D ATOMIC_LOCKING)
|
||||
add_definitions(-D GL_GLEXT_PROTOTYPES)
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${CMAKE_BINARY_DIR}/version.c
|
||||
${CMAKE_BINARY_DIR}/_version.c
|
||||
COMMAND ${CMAKE_COMMAND} -D PROJECT_TOP=${PROJECT_TOP} -P
|
||||
${PROJECT_TOP}/version.cmake
|
||||
OUTPUT ${CMAKE_BINARY_DIR}/version.c
|
||||
${CMAKE_BINARY_DIR}/_version.c
|
||||
COMMAND ${CMAKE_COMMAND} -D PROJECT_TOP=${PROJECT_TOP} -P
|
||||
${PROJECT_TOP}/version.cmake
|
||||
)
|
||||
|
||||
include_directories(
|
||||
${PROJECT_TOP}
|
||||
${PROJECT_SOURCE_DIR}/include
|
||||
${CMAKE_BINARY_DIR}
|
||||
${CMAKE_BINARY_DIR}/include
|
||||
${PROJECT_TOP}/repos/nanosvg/src
|
||||
${PROJECT_TOP}
|
||||
${PROJECT_SOURCE_DIR}/include
|
||||
${CMAKE_BINARY_DIR}/include
|
||||
)
|
||||
|
||||
link_libraries(
|
||||
${CMAKE_DL_LIBS}
|
||||
rt
|
||||
m
|
||||
${CMAKE_DL_LIBS}
|
||||
rt
|
||||
m
|
||||
)
|
||||
|
||||
set(SOURCES
|
||||
${CMAKE_BINARY_DIR}/version.c
|
||||
src/main.c
|
||||
src/core.c
|
||||
src/app.c
|
||||
src/audio.c
|
||||
src/config.c
|
||||
src/keybind.c
|
||||
src/util.c
|
||||
src/clipboard.c
|
||||
src/kb.c
|
||||
src/gl_dynprocs.c
|
||||
src/egl_dynprocs.c
|
||||
src/eglutil.c
|
||||
src/overlay_utils.c
|
||||
src/render_queue.c
|
||||
${CMAKE_BINARY_DIR}/version.c
|
||||
src/main.c
|
||||
src/core.c
|
||||
src/app.c
|
||||
src/audio.c
|
||||
src/config.c
|
||||
src/keybind.c
|
||||
src/util.c
|
||||
src/clipboard.c
|
||||
src/kb.c
|
||||
src/gl_dynprocs.c
|
||||
src/egl_dynprocs.c
|
||||
src/eglutil.c
|
||||
src/overlay_utils.c
|
||||
|
||||
src/overlay/splash.c
|
||||
src/overlay/alert.c
|
||||
src/overlay/fps.c
|
||||
src/overlay/graphs.c
|
||||
src/overlay/help.c
|
||||
src/overlay/config.c
|
||||
src/overlay/msg.c
|
||||
src/overlay/status.c
|
||||
src/overlay/alert.c
|
||||
src/overlay/fps.c
|
||||
src/overlay/graphs.c
|
||||
src/overlay/help.c
|
||||
src/overlay/config.c
|
||||
src/overlay/msg.c
|
||||
src/overlay/record.c
|
||||
)
|
||||
|
||||
# Force cimgui to build as a static library.
|
||||
set(IMGUI_STATIC "yes" CACHE STRING "Build as a static library")
|
||||
|
||||
add_subdirectory("${PROJECT_TOP}/resources" "${CMAKE_BINARY_DIR}/resources")
|
||||
add_subdirectory("${PROJECT_TOP}/common" "${CMAKE_BINARY_DIR}/common" )
|
||||
add_subdirectory("${PROJECT_TOP}/repos/LGMP/lgmp" "${CMAKE_BINARY_DIR}/LGMP" )
|
||||
add_subdirectory("${PROJECT_TOP}/repos/PureSpice" "${CMAKE_BINARY_DIR}/PureSpice")
|
||||
@@ -165,29 +160,28 @@ add_executable(looking-glass-client ${SOURCES})
|
||||
target_compile_definitions(looking-glass-client PRIVATE CIMGUI_DEFINE_ENUMS_AND_STRUCTS=1)
|
||||
|
||||
target_link_libraries(looking-glass-client
|
||||
${EXE_FLAGS}
|
||||
PkgConfig::FONTCONFIG
|
||||
lg_resources
|
||||
lg_common
|
||||
displayservers
|
||||
lgmp
|
||||
purespice
|
||||
renderers
|
||||
cimgui
|
||||
${EXE_FLAGS}
|
||||
PkgConfig::FONTCONFIG
|
||||
lg_common
|
||||
displayservers
|
||||
lgmp
|
||||
purespice
|
||||
renderers
|
||||
cimgui
|
||||
)
|
||||
|
||||
if (ENABLE_PIPEWIRE OR ENABLE_PULSEAUDIO)
|
||||
add_definitions(-D ENABLE_AUDIO)
|
||||
add_subdirectory(audiodevs)
|
||||
pkg_check_modules(SAMPLERATE REQUIRED IMPORTED_TARGET samplerate)
|
||||
target_link_libraries(looking-glass-client
|
||||
PkgConfig::SAMPLERATE
|
||||
audiodevs
|
||||
)
|
||||
add_definitions(-D ENABLE_AUDIO)
|
||||
add_subdirectory(audiodevs)
|
||||
pkg_check_modules(SAMPLERATE REQUIRED IMPORTED_TARGET samplerate)
|
||||
target_link_libraries(looking-glass-client
|
||||
PkgConfig::SAMPLERATE
|
||||
audiodevs
|
||||
)
|
||||
endif()
|
||||
|
||||
install(TARGETS looking-glass-client
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
COMPONENT binary)
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
COMPONENT binary)
|
||||
|
||||
feature_summary(WHAT ENABLED_FEATURES DISABLED_FEATURES)
|
||||
|
||||
@@ -3,19 +3,19 @@ project(audiodev_PipeWire LANGUAGES C)
|
||||
|
||||
find_package(PkgConfig)
|
||||
pkg_check_modules(AUDIODEV_PipeWire REQUIRED IMPORTED_TARGET
|
||||
libpipewire-0.3
|
||||
libpipewire-0.3
|
||||
)
|
||||
|
||||
add_library(audiodev_PipeWire STATIC
|
||||
pipewire.c
|
||||
pipewire.c
|
||||
)
|
||||
|
||||
target_link_libraries(audiodev_PipeWire
|
||||
PkgConfig::AUDIODEV_PipeWire
|
||||
lg_common
|
||||
PkgConfig::AUDIODEV_PipeWire
|
||||
lg_common
|
||||
)
|
||||
|
||||
target_include_directories(audiodev_PipeWire
|
||||
PRIVATE
|
||||
src
|
||||
PRIVATE
|
||||
src
|
||||
)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Looking Glass
|
||||
* Copyright © 2017-2023 The Looking Glass Authors
|
||||
* Copyright © 2017-2022 The Looking Glass Authors
|
||||
* https://looking-glass.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
@@ -28,7 +28,6 @@
|
||||
#include "common/debug.h"
|
||||
#include "common/stringutils.h"
|
||||
#include "common/util.h"
|
||||
#include "common/option.h"
|
||||
|
||||
typedef enum
|
||||
{
|
||||
@@ -130,29 +129,6 @@ 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);
|
||||
@@ -245,8 +221,9 @@ static void pipewire_playbackSetup(int channels, int sampleRate,
|
||||
pw.playback.pullFn = pullFn;
|
||||
|
||||
pw_thread_loop_lock(pw.thread);
|
||||
|
||||
struct pw_properties * props =
|
||||
pw.playback.stream = pw_stream_new_simple(
|
||||
pw.loop,
|
||||
"Looking Glass",
|
||||
pw_properties_new(
|
||||
PW_KEY_NODE_NAME , "Looking Glass",
|
||||
PW_KEY_MEDIA_TYPE , "Audio",
|
||||
@@ -254,22 +231,7 @@ 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
|
||||
);
|
||||
@@ -487,30 +449,17 @@ static void pipewire_recordStart(int channels, int sampleRate,
|
||||
pw.record.stride = sizeof(uint16_t) * channels;
|
||||
pw.record.pushFn = pushFn;
|
||||
|
||||
struct pw_properties * props =
|
||||
pw_thread_loop_lock(pw.thread);
|
||||
pw.record.stream = pw_stream_new_simple(
|
||||
pw.loop,
|
||||
"Looking Glass",
|
||||
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
|
||||
);
|
||||
@@ -594,10 +543,9 @@ static void pipewire_free(void)
|
||||
|
||||
struct LG_AudioDevOps LGAD_PipeWire =
|
||||
{
|
||||
.name = "PipeWire",
|
||||
.earlyInit = pipewire_earlyInit,
|
||||
.init = pipewire_init,
|
||||
.free = pipewire_free,
|
||||
.name = "PipeWire",
|
||||
.init = pipewire_init,
|
||||
.free = pipewire_free,
|
||||
.playback =
|
||||
{
|
||||
.setup = pipewire_playbackSetup,
|
||||
|
||||
@@ -3,19 +3,19 @@ project(audiodev_PulseAudio LANGUAGES C)
|
||||
|
||||
find_package(PkgConfig)
|
||||
pkg_check_modules(AUDIODEV_PulseAudio REQUIRED IMPORTED_TARGET
|
||||
libpulse
|
||||
libpulse
|
||||
)
|
||||
|
||||
add_library(audiodev_PulseAudio STATIC
|
||||
pulseaudio.c
|
||||
pulseaudio.c
|
||||
)
|
||||
|
||||
target_link_libraries(audiodev_PulseAudio
|
||||
PkgConfig::AUDIODEV_PulseAudio
|
||||
lg_common
|
||||
PkgConfig::AUDIODEV_PulseAudio
|
||||
lg_common
|
||||
)
|
||||
|
||||
target_include_directories(audiodev_PulseAudio
|
||||
PRIVATE
|
||||
src
|
||||
PRIVATE
|
||||
src
|
||||
)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Looking Glass
|
||||
* Copyright © 2017-2023 The Looking Glass Authors
|
||||
* Copyright © 2017-2022 The Looking Glass Authors
|
||||
* https://looking-glass.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
|
||||
@@ -3,99 +3,99 @@ project(displayserver_Wayland LANGUAGES C)
|
||||
|
||||
find_package(PkgConfig)
|
||||
pkg_check_modules(DISPLAYSERVER_Wayland REQUIRED IMPORTED_TARGET
|
||||
wayland-client
|
||||
wayland-cursor
|
||||
xkbcommon
|
||||
wayland-client
|
||||
wayland-cursor
|
||||
xkbcommon
|
||||
)
|
||||
|
||||
set(DISPLAYSERVER_Wayland_OPT_PKGCONFIG_LIBRARIES "")
|
||||
set(displayserver_Wayland_SHELL_SRC "")
|
||||
|
||||
if (ENABLE_LIBDECOR)
|
||||
pkg_check_modules(DISPLAYSERVER_Wayland_LIBDECOR REQUIRED IMPORTED_TARGET
|
||||
libdecor-0
|
||||
)
|
||||
list(APPEND DISPLAYSERVER_Wayland_OPT_PKGCONFIG_LIBRARIES PkgConfig::DISPLAYSERVER_Wayland_LIBDECOR)
|
||||
list(APPEND displayserver_Wayland_SHELL_SRC shell_libdecor.c)
|
||||
add_compile_definitions(ENABLE_LIBDECOR)
|
||||
pkg_check_modules(DISPLAYSERVER_Wayland_LIBDECOR REQUIRED IMPORTED_TARGET
|
||||
libdecor-0
|
||||
)
|
||||
list(APPEND DISPLAYSERVER_Wayland_OPT_PKGCONFIG_LIBRARIES PkgConfig::DISPLAYSERVER_Wayland_LIBDECOR)
|
||||
list(APPEND displayserver_Wayland_SHELL_SRC shell_libdecor.c)
|
||||
add_compile_definitions(ENABLE_LIBDECOR)
|
||||
else()
|
||||
list(APPEND displayserver_Wayland_SHELL_SRC shell_xdg.c)
|
||||
list(APPEND displayserver_Wayland_SHELL_SRC shell_xdg.c)
|
||||
endif()
|
||||
|
||||
add_library(displayserver_Wayland STATIC
|
||||
activation.c
|
||||
clipboard.c
|
||||
cursor.c
|
||||
gl.c
|
||||
idle.c
|
||||
input.c
|
||||
output.c
|
||||
poll.c
|
||||
presentation.c
|
||||
state.c
|
||||
registry.c
|
||||
wayland.c
|
||||
window.c
|
||||
${displayserver_Wayland_SHELL_SRC}
|
||||
activation.c
|
||||
clipboard.c
|
||||
cursor.c
|
||||
gl.c
|
||||
idle.c
|
||||
input.c
|
||||
output.c
|
||||
poll.c
|
||||
presentation.c
|
||||
state.c
|
||||
registry.c
|
||||
wayland.c
|
||||
window.c
|
||||
${displayserver_Wayland_SHELL_SRC}
|
||||
)
|
||||
|
||||
target_link_libraries(displayserver_Wayland
|
||||
PkgConfig::DISPLAYSERVER_Wayland
|
||||
${DISPLAYSERVER_Wayland_OPT_PKGCONFIG_LIBRARIES}
|
||||
lg_common
|
||||
PkgConfig::DISPLAYSERVER_Wayland
|
||||
${DISPLAYSERVER_Wayland_OPT_PKGCONFIG_LIBRARIES}
|
||||
lg_common
|
||||
)
|
||||
|
||||
target_include_directories(displayserver_Wayland
|
||||
PRIVATE
|
||||
src
|
||||
PRIVATE
|
||||
src
|
||||
)
|
||||
|
||||
find_program(WAYLAND_SCANNER_EXECUTABLE NAMES wayland-scanner)
|
||||
|
||||
macro(wayland_generate protocol_file output_file)
|
||||
add_custom_command(OUTPUT "${output_file}.h"
|
||||
COMMAND "${WAYLAND_SCANNER_EXECUTABLE}" client-header "${protocol_file}" "${output_file}.h"
|
||||
DEPENDS "${protocol_file}"
|
||||
VERBATIM)
|
||||
add_custom_command(OUTPUT "${output_file}.h"
|
||||
COMMAND "${WAYLAND_SCANNER_EXECUTABLE}" client-header "${protocol_file}" "${output_file}.h"
|
||||
DEPENDS "${protocol_file}"
|
||||
VERBATIM)
|
||||
|
||||
add_custom_command(OUTPUT "${output_file}.c"
|
||||
COMMAND "${WAYLAND_SCANNER_EXECUTABLE}" private-code "${protocol_file}" "${output_file}.c"
|
||||
DEPENDS "${protocol_file}"
|
||||
VERBATIM)
|
||||
add_custom_command(OUTPUT "${output_file}.c"
|
||||
COMMAND "${WAYLAND_SCANNER_EXECUTABLE}" private-code "${protocol_file}" "${output_file}.c"
|
||||
DEPENDS "${protocol_file}"
|
||||
VERBATIM)
|
||||
|
||||
target_sources(displayserver_Wayland PRIVATE "${output_file}.h" "${output_file}.c")
|
||||
target_sources(displayserver_Wayland PRIVATE "${output_file}.h" "${output_file}.c")
|
||||
endmacro()
|
||||
|
||||
set(WAYLAND_PROTOCOLS_BASE "${PROJECT_TOP}/repos/wayland-protocols")
|
||||
file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/wayland")
|
||||
include_directories("${CMAKE_BINARY_DIR}/wayland")
|
||||
wayland_generate(
|
||||
"${WAYLAND_PROTOCOLS_BASE}/stable/xdg-shell/xdg-shell.xml"
|
||||
"${CMAKE_BINARY_DIR}/wayland/wayland-xdg-shell-client-protocol")
|
||||
"${WAYLAND_PROTOCOLS_BASE}/stable/xdg-shell/xdg-shell.xml"
|
||||
"${CMAKE_BINARY_DIR}/wayland/wayland-xdg-shell-client-protocol")
|
||||
wayland_generate(
|
||||
"${WAYLAND_PROTOCOLS_BASE}/stable/presentation-time/presentation-time.xml"
|
||||
"${CMAKE_BINARY_DIR}/wayland/wayland-presentation-time-client-protocol")
|
||||
"${WAYLAND_PROTOCOLS_BASE}/stable/presentation-time/presentation-time.xml"
|
||||
"${CMAKE_BINARY_DIR}/wayland/wayland-presentation-time-client-protocol")
|
||||
wayland_generate(
|
||||
"${WAYLAND_PROTOCOLS_BASE}/stable/viewporter/viewporter.xml"
|
||||
"${CMAKE_BINARY_DIR}/wayland/wayland-viewporter-client-protocol")
|
||||
"${WAYLAND_PROTOCOLS_BASE}/stable/viewporter/viewporter.xml"
|
||||
"${CMAKE_BINARY_DIR}/wayland/wayland-viewporter-client-protocol")
|
||||
wayland_generate(
|
||||
"${WAYLAND_PROTOCOLS_BASE}/unstable/xdg-decoration/xdg-decoration-unstable-v1.xml"
|
||||
"${CMAKE_BINARY_DIR}/wayland/wayland-xdg-decoration-unstable-v1-client-protocol")
|
||||
"${WAYLAND_PROTOCOLS_BASE}/unstable/xdg-decoration/xdg-decoration-unstable-v1.xml"
|
||||
"${CMAKE_BINARY_DIR}/wayland/wayland-xdg-decoration-unstable-v1-client-protocol")
|
||||
wayland_generate(
|
||||
"${WAYLAND_PROTOCOLS_BASE}/unstable/relative-pointer/relative-pointer-unstable-v1.xml"
|
||||
"${CMAKE_BINARY_DIR}/wayland/wayland-relative-pointer-unstable-v1-client-protocol")
|
||||
"${WAYLAND_PROTOCOLS_BASE}/unstable/relative-pointer/relative-pointer-unstable-v1.xml"
|
||||
"${CMAKE_BINARY_DIR}/wayland/wayland-relative-pointer-unstable-v1-client-protocol")
|
||||
wayland_generate(
|
||||
"${WAYLAND_PROTOCOLS_BASE}/unstable/pointer-constraints/pointer-constraints-unstable-v1.xml"
|
||||
"${CMAKE_BINARY_DIR}/wayland/wayland-pointer-constraints-unstable-v1-client-protocol")
|
||||
"${WAYLAND_PROTOCOLS_BASE}/unstable/pointer-constraints/pointer-constraints-unstable-v1.xml"
|
||||
"${CMAKE_BINARY_DIR}/wayland/wayland-pointer-constraints-unstable-v1-client-protocol")
|
||||
wayland_generate(
|
||||
"${WAYLAND_PROTOCOLS_BASE}/unstable/keyboard-shortcuts-inhibit/keyboard-shortcuts-inhibit-unstable-v1.xml"
|
||||
"${CMAKE_BINARY_DIR}/wayland/wayland-keyboard-shortcuts-inhibit-unstable-v1-client-protocol")
|
||||
"${WAYLAND_PROTOCOLS_BASE}/unstable/keyboard-shortcuts-inhibit/keyboard-shortcuts-inhibit-unstable-v1.xml"
|
||||
"${CMAKE_BINARY_DIR}/wayland/wayland-keyboard-shortcuts-inhibit-unstable-v1-client-protocol")
|
||||
wayland_generate(
|
||||
"${WAYLAND_PROTOCOLS_BASE}/unstable/idle-inhibit/idle-inhibit-unstable-v1.xml"
|
||||
"${CMAKE_BINARY_DIR}/wayland/wayland-idle-inhibit-unstable-v1-client-protocol")
|
||||
"${WAYLAND_PROTOCOLS_BASE}/unstable/idle-inhibit/idle-inhibit-unstable-v1.xml"
|
||||
"${CMAKE_BINARY_DIR}/wayland/wayland-idle-inhibit-unstable-v1-client-protocol")
|
||||
wayland_generate(
|
||||
"${WAYLAND_PROTOCOLS_BASE}/unstable/xdg-output/xdg-output-unstable-v1.xml"
|
||||
"${CMAKE_BINARY_DIR}/wayland/wayland-xdg-output-unstable-v1-client-protocol")
|
||||
"${WAYLAND_PROTOCOLS_BASE}/unstable/xdg-output/xdg-output-unstable-v1.xml"
|
||||
"${CMAKE_BINARY_DIR}/wayland/wayland-xdg-output-unstable-v1-client-protocol")
|
||||
wayland_generate(
|
||||
"${WAYLAND_PROTOCOLS_BASE}/staging/xdg-activation/xdg-activation-v1.xml"
|
||||
"${CMAKE_BINARY_DIR}/wayland/wayland-xdg-activation-v1-client-protocol")
|
||||
"${WAYLAND_PROTOCOLS_BASE}/staging/xdg-activation/xdg-activation-v1.xml"
|
||||
"${CMAKE_BINARY_DIR}/wayland/wayland-xdg-activation-v1-client-protocol")
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Looking Glass
|
||||
* Copyright © 2017-2023 The Looking Glass Authors
|
||||
* Copyright © 2017-2022 The Looking Glass Authors
|
||||
* https://looking-glass.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Looking Glass
|
||||
* Copyright © 2017-2023 The Looking Glass Authors
|
||||
* Copyright © 2017-2022 The Looking Glass Authors
|
||||
* https://looking-glass.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
@@ -512,13 +512,6 @@ error:
|
||||
free(data);
|
||||
}
|
||||
|
||||
static void dataSourceHandleTarget(void * data, struct wl_data_source * source,
|
||||
const char * mimetype)
|
||||
{
|
||||
// Certain Wayland clients send this for copy-paste operations even though
|
||||
// it only makes sense for drag-and-drop. We just do nothing.
|
||||
}
|
||||
|
||||
static void dataSourceHandleSend(void * data, struct wl_data_source * source,
|
||||
const char * mimetype, int fd)
|
||||
{
|
||||
@@ -554,8 +547,7 @@ static void dataSourceHandleCancelled(void * data,
|
||||
}
|
||||
|
||||
static const struct wl_data_source_listener dataSourceListener = {
|
||||
.target = dataSourceHandleTarget,
|
||||
.send = dataSourceHandleSend,
|
||||
.send = dataSourceHandleSend,
|
||||
.cancelled = dataSourceHandleCancelled,
|
||||
};
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Looking Glass
|
||||
* Copyright © 2017-2023 The Looking Glass Authors
|
||||
* Copyright © 2017-2022 The Looking Glass Authors
|
||||
* https://looking-glass.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Looking Glass
|
||||
* Copyright © 2017-2023 The Looking Glass Authors
|
||||
* Copyright © 2017-2022 The Looking Glass Authors
|
||||
* https://looking-glass.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
@@ -88,13 +88,10 @@ void waylandEGLSwapBuffers(EGLDisplay display, EGLSurface surface, const struct
|
||||
|
||||
if (wlWm.needsResize)
|
||||
{
|
||||
bool skipResize = false;
|
||||
wl_egl_window_resize(wlWm.eglWindow, wl_fixed_to_int(wlWm.width * wlWm.scale),
|
||||
wl_fixed_to_int(wlWm.height * wlWm.scale), 0, 0);
|
||||
|
||||
if (wlWm.width == 0 || wlWm.height == 0)
|
||||
skipResize = true;
|
||||
else if (wlWm.fractionalScale)
|
||||
if (wlWm.fractionalScale)
|
||||
{
|
||||
wl_surface_set_buffer_scale(wlWm.surface, 1);
|
||||
if (!wlWm.viewport)
|
||||
@@ -128,7 +125,7 @@ void waylandEGLSwapBuffers(EGLDisplay display, EGLSurface surface, const struct
|
||||
(struct Border) {0, 0, 0, 0});
|
||||
app_invalidateWindow(true);
|
||||
waylandStopWaitFrame();
|
||||
wlWm.needsResize = skipResize;
|
||||
wlWm.needsResize = false;
|
||||
}
|
||||
|
||||
waylandShellAckConfigureIfNeeded();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Looking Glass
|
||||
* Copyright © 2017-2023 The Looking Glass Authors
|
||||
* Copyright © 2017-2022 The Looking Glass Authors
|
||||
* https://looking-glass.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Looking Glass
|
||||
* Copyright © 2017-2023 The Looking Glass Authors
|
||||
* Copyright © 2017-2022 The Looking Glass Authors
|
||||
* https://looking-glass.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
@@ -209,17 +209,6 @@ done:
|
||||
close(fd);
|
||||
}
|
||||
|
||||
static int getCharcode(uint32_t key)
|
||||
{
|
||||
key += 8; // xkb scancode is evdev scancode + 8
|
||||
xkb_keysym_t sym = xkb_state_key_get_one_sym(wlWm.xkbState, key);
|
||||
if (sym == XKB_KEY_NoSymbol)
|
||||
return 0;
|
||||
|
||||
sym = xkb_keysym_to_upper(sym);
|
||||
return xkb_keysym_to_utf32(sym);
|
||||
}
|
||||
|
||||
static void keyboardEnterHandler(void * data, struct wl_keyboard * keyboard,
|
||||
uint32_t serial, struct wl_surface * surface, struct wl_array * keys)
|
||||
{
|
||||
@@ -232,7 +221,7 @@ static void keyboardEnterHandler(void * data, struct wl_keyboard * keyboard,
|
||||
|
||||
uint32_t * key;
|
||||
wl_array_for_each(key, keys)
|
||||
app_handleKeyPress(*key, getCharcode(*key));
|
||||
app_handleKeyPress(*key);
|
||||
}
|
||||
|
||||
static void keyboardLeaveHandler(void * data, struct wl_keyboard * keyboard,
|
||||
@@ -253,9 +242,9 @@ static void keyboardKeyHandler(void * data, struct wl_keyboard * keyboard,
|
||||
return;
|
||||
|
||||
if (state == WL_KEYBOARD_KEY_STATE_PRESSED)
|
||||
app_handleKeyPress(key, getCharcode(key));
|
||||
app_handleKeyPress(key);
|
||||
else
|
||||
app_handleKeyRelease(key, getCharcode(key));
|
||||
app_handleKeyRelease(key);
|
||||
|
||||
if (!wlWm.xkbState || !app_isOverlayMode() || state != WL_KEYBOARD_KEY_STATE_PRESSED)
|
||||
return;
|
||||
@@ -465,7 +454,7 @@ void waylandGrabPointer(void)
|
||||
|
||||
INTERLOCKED_SECTION(wlWm.confineLock,
|
||||
{
|
||||
if (!wlWm.confinedPointer && !wlWm.lockedPointer)
|
||||
if (!wlWm.confinedPointer)
|
||||
{
|
||||
wlWm.confinedPointer = zwp_pointer_constraints_v1_confine_pointer(
|
||||
wlWm.pointerConstraints, wlWm.surface, wlWm.pointer, NULL,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Looking Glass
|
||||
* Copyright © 2017-2023 The Looking Glass Authors
|
||||
* Copyright © 2017-2022 The Looking Glass Authors
|
||||
* https://looking-glass.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Looking Glass
|
||||
* Copyright © 2017-2023 The Looking Glass Authors
|
||||
* Copyright © 2017-2022 The Looking Glass Authors
|
||||
* https://looking-glass.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Looking Glass
|
||||
* Copyright © 2017-2023 The Looking Glass Authors
|
||||
* Copyright © 2017-2022 The Looking Glass Authors
|
||||
* https://looking-glass.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Looking Glass
|
||||
* Copyright © 2017-2023 The Looking Glass Authors
|
||||
* Copyright © 2017-2022 The Looking Glass Authors
|
||||
* https://looking-glass.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Looking Glass
|
||||
* Copyright © 2017-2023 The Looking Glass Authors
|
||||
* Copyright © 2017-2022 The Looking Glass Authors
|
||||
* https://looking-glass.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Looking Glass
|
||||
* Copyright © 2017-2023 The Looking Glass Authors
|
||||
* Copyright © 2017-2022 The Looking Glass Authors
|
||||
* https://looking-glass.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
@@ -65,30 +65,15 @@ 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)
|
||||
{
|
||||
switch (*state)
|
||||
{
|
||||
case XDG_TOPLEVEL_STATE_FULLSCREEN:
|
||||
if (*state == 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -171,14 +156,5 @@ void waylandMinimize(void)
|
||||
|
||||
void waylandShellResize(int w, int h)
|
||||
{
|
||||
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();
|
||||
//TODO: Implement resize for XDG.
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Looking Glass
|
||||
* Copyright © 2017-2023 The Looking Glass Authors
|
||||
* Copyright © 2017-2022 The Looking Glass Authors
|
||||
* https://looking-glass.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Looking Glass
|
||||
* Copyright © 2017-2023 The Looking Glass Authors
|
||||
* Copyright © 2017-2022 The Looking Glass Authors
|
||||
* https://looking-glass.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
@@ -71,16 +71,12 @@ 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;
|
||||
|
||||
@@ -158,7 +154,6 @@ static bool waylandGetProp(LG_DSProperty prop, void * ret)
|
||||
|
||||
struct LG_DisplayServerOps LGDS_Wayland =
|
||||
{
|
||||
.name = "Wayland",
|
||||
.setup = waylandSetup,
|
||||
.probe = waylandProbe,
|
||||
.earlyInit = waylandEarlyInit,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Looking Glass
|
||||
* Copyright © 2017-2023 The Looking Glass Authors
|
||||
* Copyright © 2017-2022 The Looking Glass Authors
|
||||
* https://looking-glass.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
@@ -112,7 +112,6 @@ struct WaylandDSState
|
||||
bool fractionalScale;
|
||||
bool needsResize;
|
||||
bool fullscreen;
|
||||
bool floating;
|
||||
uint32_t resizeSerial;
|
||||
bool configured;
|
||||
bool warpSupport;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Looking Glass
|
||||
* Copyright © 2017-2023 The Looking Glass Authors
|
||||
* Copyright © 2017-2022 The Looking Glass Authors
|
||||
* https://looking-glass.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
|
||||
@@ -3,35 +3,29 @@ project(displayserver_X11 LANGUAGES C)
|
||||
|
||||
find_package(PkgConfig)
|
||||
pkg_check_modules(DISPLAYSERVER_X11 REQUIRED IMPORTED_TARGET
|
||||
x11
|
||||
xi
|
||||
xfixes
|
||||
xscrnsaver
|
||||
xinerama
|
||||
xcursor
|
||||
xpresent
|
||||
xkbcommon
|
||||
x11
|
||||
xi
|
||||
xfixes
|
||||
xscrnsaver
|
||||
xinerama
|
||||
xcursor
|
||||
xpresent
|
||||
)
|
||||
|
||||
add_library(displayserver_X11 STATIC
|
||||
x11.c
|
||||
atoms.c
|
||||
clipboard.c
|
||||
cursor.c
|
||||
|
||||
wm/default.c
|
||||
wm/i3.c
|
||||
x11.c
|
||||
atoms.c
|
||||
clipboard.c
|
||||
)
|
||||
|
||||
add_definitions(-D GLX_GLXEXT_PROTOTYPES)
|
||||
|
||||
target_link_libraries(displayserver_X11
|
||||
PkgConfig::DISPLAYSERVER_X11
|
||||
lg_common
|
||||
lg_resources
|
||||
PkgConfig::DISPLAYSERVER_X11
|
||||
lg_common
|
||||
)
|
||||
|
||||
target_include_directories(displayserver_X11
|
||||
PRIVATE
|
||||
.
|
||||
PRIVATE
|
||||
src
|
||||
)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Looking Glass
|
||||
* Copyright © 2017-2023 The Looking Glass Authors
|
||||
* Copyright © 2017-2022 The Looking Glass Authors
|
||||
* https://looking-glass.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Looking Glass
|
||||
* Copyright © 2017-2023 The Looking Glass Authors
|
||||
* Copyright © 2017-2022 The Looking Glass Authors
|
||||
* https://looking-glass.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
@@ -38,7 +38,6 @@
|
||||
DEF_ATOM(_NET_WM_WINDOW_TYPE, True) \
|
||||
DEF_ATOM(_NET_WM_WINDOW_TYPE_NORMAL, True) \
|
||||
DEF_ATOM(_NET_WM_WINDOW_TYPE_UTILITY, True) \
|
||||
DEF_ATOM(_NET_WM_PID, True) \
|
||||
DEF_ATOM(WM_DELETE_WINDOW, True) \
|
||||
DEF_ATOM(_MOTIF_WM_HINTS, True) \
|
||||
\
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Looking Glass
|
||||
* Copyright © 2017-2023 The Looking Glass Authors
|
||||
* Copyright © 2017-2022 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(void)
|
||||
bool x11CBInit()
|
||||
{
|
||||
x11cb.aCurSelection = BadValue;
|
||||
for(int i = 0; i < LG_CLIPBOARD_DATA_NONE; ++i)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Looking Glass
|
||||
* Copyright © 2017-2023 The Looking Glass Authors
|
||||
* Copyright © 2017-2022 The Looking Glass Authors
|
||||
* https://looking-glass.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
|
||||
@@ -1,105 +0,0 @@
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
/**
|
||||
* 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
|
||||
@@ -1,71 +0,0 @@
|
||||
/**
|
||||
* 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
|
||||
@@ -1,194 +0,0 @@
|
||||
/**
|
||||
* 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
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Looking Glass
|
||||
* Copyright © 2017-2023 The Looking Glass Authors
|
||||
* Copyright © 2017-2022 The Looking Glass Authors
|
||||
* https://looking-glass.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
@@ -23,11 +23,7 @@
|
||||
#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>
|
||||
@@ -40,8 +36,6 @@
|
||||
#include <X11/extensions/Xpresent.h>
|
||||
#include <X11/Xcursor/Xcursor.h>
|
||||
|
||||
#include <xkbcommon/xkbcommon.h>
|
||||
|
||||
#include <GL/glx.h>
|
||||
#include <GL/glxext.h>
|
||||
|
||||
@@ -57,6 +51,10 @@
|
||||
#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,8 +164,6 @@ static void x11DoPresent(uint64_t msc)
|
||||
|
||||
static void x11Setup(void)
|
||||
{
|
||||
X11WM_Default.setup();
|
||||
X11WM_i3 .setup();
|
||||
}
|
||||
|
||||
static bool x11Probe(void)
|
||||
@@ -194,14 +190,14 @@ static void x11CheckEWMHSupport(void)
|
||||
|
||||
if (XGetWindowProperty(x11.display, DefaultRootWindow(x11.display),
|
||||
x11atoms._NET_SUPPORTING_WM_CHECK, 0, ~0L, False, XA_WINDOW,
|
||||
&type, &fmt, &num, &bytes, &data) != Success || !data)
|
||||
&type, &fmt, &num, &bytes, &data) != Success)
|
||||
goto out;
|
||||
|
||||
Window * windowFromRoot = (Window *)data;
|
||||
|
||||
if (XGetWindowProperty(x11.display, *windowFromRoot,
|
||||
x11atoms._NET_SUPPORTING_WM_CHECK, 0, ~0L, False, XA_WINDOW,
|
||||
&type, &fmt, &num, &bytes, &data) != Success || !data)
|
||||
&type, &fmt, &num, &bytes, &data) != Success)
|
||||
goto out_root;
|
||||
|
||||
Window * windowFromChild = (Window *)data;
|
||||
@@ -210,7 +206,7 @@ static void x11CheckEWMHSupport(void)
|
||||
|
||||
if (XGetWindowProperty(x11.display, DefaultRootWindow(x11.display),
|
||||
x11atoms._NET_SUPPORTED, 0, ~0L, False, AnyPropertyType,
|
||||
&type, &fmt, &num, &bytes, &data) != Success || !data)
|
||||
&type, &fmt, &num, &bytes, &data) != Success)
|
||||
goto out_child;
|
||||
|
||||
Atom * supported = (Atom *)data;
|
||||
@@ -218,7 +214,7 @@ static void x11CheckEWMHSupport(void)
|
||||
|
||||
if (XGetWindowProperty(x11.display, *windowFromRoot,
|
||||
x11atoms._NET_WM_NAME, 0, ~0L, False, AnyPropertyType,
|
||||
&type, &fmt, &num, &bytes, &data) != Success || !data)
|
||||
&type, &fmt, &num, &bytes, &data) != Success)
|
||||
goto out_supported;
|
||||
|
||||
char * wmName = (char *)data;
|
||||
@@ -232,8 +228,6 @@ 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:
|
||||
@@ -246,37 +240,17 @@ 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 =
|
||||
{
|
||||
@@ -374,31 +348,6 @@ 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();
|
||||
XChangeProperty(
|
||||
x11.display,
|
||||
x11.window,
|
||||
x11atoms._NET_WM_PID,
|
||||
XA_CARDINAL,
|
||||
32,
|
||||
PropModeReplace,
|
||||
(unsigned char *)&pid,
|
||||
1
|
||||
);
|
||||
}
|
||||
|
||||
if (params.borderless)
|
||||
{
|
||||
if (x11atoms._MOTIF_WM_HINTS)
|
||||
@@ -449,14 +398,23 @@ static bool x11Init(const LG_DSInitParams params)
|
||||
);
|
||||
}
|
||||
|
||||
Atom wmState[3] = {0};
|
||||
int wmStateCount = 0;
|
||||
|
||||
if (params.fullscreen)
|
||||
{
|
||||
x11.fullscreen = true;
|
||||
wmState[wmStateCount++] = x11atoms._NET_WM_STATE_FULLSCREEN;
|
||||
}
|
||||
|
||||
if (params.maximize)
|
||||
{
|
||||
Atom wmState[2] =
|
||||
{
|
||||
x11atoms._NET_WM_STATE_MAXIMIZED_HORZ,
|
||||
x11atoms._NET_WM_STATE_MAXIMIZED_VERT
|
||||
};
|
||||
wmState[wmStateCount++] = x11atoms._NET_WM_STATE_MAXIMIZED_HORZ;
|
||||
wmState[wmStateCount++] = x11atoms._NET_WM_STATE_MAXIMIZED_VERT;
|
||||
}
|
||||
|
||||
if (wmStateCount)
|
||||
{
|
||||
XChangeProperty(
|
||||
x11.display,
|
||||
x11.window,
|
||||
@@ -465,7 +423,7 @@ static bool x11Init(const LG_DSInitParams params)
|
||||
32,
|
||||
PropModeReplace,
|
||||
(unsigned char *)&wmState,
|
||||
2
|
||||
wmStateCount
|
||||
);
|
||||
}
|
||||
|
||||
@@ -491,7 +449,7 @@ static bool x11Init(const LG_DSInitParams params)
|
||||
if (XIQueryVersion(x11.display, &major, &minor) != Success)
|
||||
{
|
||||
DEBUG_ERROR("Failed to query the XInput version");
|
||||
goto fail_window;
|
||||
return false;
|
||||
}
|
||||
|
||||
DEBUG_INFO("X11 XInput %d.%d in use", major, minor);
|
||||
@@ -565,10 +523,6 @@ static bool x11Init(const LG_DSInitParams params)
|
||||
goto fail_window;
|
||||
}
|
||||
|
||||
XDisplayKeycodes(x11.display, &x11.minKeycode, &x11.maxKeycode);
|
||||
x11.keysyms = XGetKeyboardMapping(x11.display, x11.minKeycode,
|
||||
x11.maxKeycode - x11.minKeycode, &x11.symsPerKeycode);
|
||||
|
||||
XIFreeDeviceInfo(devinfo);
|
||||
|
||||
XQueryExtension(x11.display, "XInputExtension", &x11.xinputOp, &event, &error);
|
||||
@@ -630,17 +584,29 @@ static bool x11Init(const LG_DSInitParams params)
|
||||
XFreePixmap(x11.display, temp);
|
||||
}
|
||||
|
||||
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);
|
||||
/* create the square cursor */
|
||||
{
|
||||
static char data[] = { 0x07, 0x05, 0x07 };
|
||||
static char mask[] = { 0xff, 0xff, 0xff };
|
||||
|
||||
x11.cursors[LG_POINTER_SQUARE] =
|
||||
XcursorImagesLoadCursor(x11.display, images);
|
||||
XcursorImagesDestroy(images);
|
||||
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);
|
||||
}
|
||||
|
||||
/* initialize the rest of the cursors */
|
||||
const char * cursorLookup[LG_POINTER_COUNT] = {
|
||||
@@ -698,9 +664,6 @@ static bool x11Init(const LG_DSInitParams params)
|
||||
if (!params.center)
|
||||
XMoveWindow(x11.display, x11.window, params.x, params.y);
|
||||
|
||||
if (params.fullscreen)
|
||||
x11SetFullscreen(true);
|
||||
|
||||
XSetLocaleModifiers(""); // Load XMODIFIERS
|
||||
x11.xim = XOpenIM(x11.display, 0, 0, 0);
|
||||
|
||||
@@ -781,10 +744,6 @@ static void x11Free(void)
|
||||
if (x11.cursors[i])
|
||||
XFreeCursor(x11.display, x11.cursors[i]);
|
||||
|
||||
if (x11.keysyms)
|
||||
XFree(x11.keysyms);
|
||||
|
||||
x11.wm->deinit();
|
||||
XCloseDisplay(x11.display);
|
||||
}
|
||||
|
||||
@@ -1082,17 +1041,6 @@ static void setFocus(bool focused, double x, double y)
|
||||
app_handleFocusEvent(focused);
|
||||
}
|
||||
|
||||
static int getCharcode(int detail)
|
||||
{
|
||||
if (detail < x11.minKeycode || detail > x11.maxKeycode)
|
||||
return 0;
|
||||
|
||||
KeySym sym = x11.keysyms[(detail - x11.minKeycode) *
|
||||
x11.symsPerKeycode];
|
||||
sym = xkb_keysym_to_upper(sym);
|
||||
return xkb_keysym_to_utf32(sym);
|
||||
}
|
||||
|
||||
static void x11XInputEvent(XGenericEventCookie *cookie)
|
||||
{
|
||||
static int button_state = 0;
|
||||
@@ -1175,46 +1123,6 @@ 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;
|
||||
}
|
||||
|
||||
@@ -1224,8 +1132,7 @@ static void x11XInputEvent(XGenericEventCookie *cookie)
|
||||
return;
|
||||
|
||||
XIDeviceEvent *device = cookie->data;
|
||||
app_handleKeyPress(device->detail - x11.minKeycode,
|
||||
getCharcode(device->detail));
|
||||
app_handleKeyPress(device->detail - 8);
|
||||
|
||||
if (!x11.xic || !app_isOverlayMode())
|
||||
return;
|
||||
@@ -1275,8 +1182,7 @@ static void x11XInputEvent(XGenericEventCookie *cookie)
|
||||
return;
|
||||
|
||||
XIDeviceEvent *device = cookie->data;
|
||||
app_handleKeyRelease(device->detail - x11.minKeycode,
|
||||
getCharcode(device->detail));
|
||||
app_handleKeyRelease(device->detail - 8);
|
||||
|
||||
if (!x11.xic || !app_isOverlayMode())
|
||||
return;
|
||||
@@ -1305,8 +1211,7 @@ static void x11XInputEvent(XGenericEventCookie *cookie)
|
||||
return;
|
||||
|
||||
XIRawEvent *raw = cookie->data;
|
||||
app_handleKeyPress(raw->detail - x11.minKeycode,
|
||||
getCharcode(raw->detail));
|
||||
app_handleKeyPress(raw->detail - 8);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1316,8 +1221,7 @@ static void x11XInputEvent(XGenericEventCookie *cookie)
|
||||
return;
|
||||
|
||||
XIRawEvent *raw = cookie->data;
|
||||
app_handleKeyRelease(raw->detail - x11.minKeycode,
|
||||
getCharcode(raw->detail));
|
||||
app_handleKeyRelease(raw->detail - 8);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1968,7 +1872,24 @@ static void x11SetFullscreen(bool fs)
|
||||
if (x11.fullscreen == fs)
|
||||
return;
|
||||
|
||||
x11.wm->setFullscreen(fs);
|
||||
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);
|
||||
}
|
||||
|
||||
static bool x11GetFullscreen(void)
|
||||
@@ -1983,7 +1904,6 @@ static void x11Minimize(void)
|
||||
|
||||
struct LG_DisplayServerOps LGDS_X11 =
|
||||
{
|
||||
.name = "X11",
|
||||
.setup = x11Setup,
|
||||
.probe = x11Probe,
|
||||
.earlyInit = x11EarlyInit,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Looking Glass
|
||||
* Copyright © 2017-2023 The Looking Glass Authors
|
||||
* Copyright © 2017-2022 The Looking Glass Authors
|
||||
* https://looking-glass.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
@@ -33,7 +33,6 @@
|
||||
#include "interface/displayserver.h"
|
||||
#include "common/thread.h"
|
||||
#include "common/types.h"
|
||||
#include "wm.h"
|
||||
|
||||
enum Modifiers
|
||||
{
|
||||
@@ -49,20 +48,11 @@ 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;
|
||||
KeySym * keysyms;
|
||||
|
||||
//Extended Window Manager Hints
|
||||
//ref: https://specifications.freedesktop.org/wm-spec/latest/
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Looking Glass
|
||||
* Copyright © 2017-2023 The Looking Glass Authors
|
||||
* Copyright © 2017-2022 The Looking Glass Authors
|
||||
* https://looking-glass.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
@@ -58,9 +58,9 @@ void app_resyncMouseBasic(void);
|
||||
void app_handleButtonPress(int button);
|
||||
void app_handleButtonRelease(int button);
|
||||
void app_handleWheelMotion(double motion);
|
||||
void app_handleKeyPress(int scancode);
|
||||
void app_handleKeyRelease(int scancode);
|
||||
void app_handleKeyboardTyped(const char * typed);
|
||||
void app_handleKeyPress(int scancode, int charcode);
|
||||
void app_handleKeyRelease(int scancode, int charcode);
|
||||
void app_handleKeyboardModifiers(bool ctrl, bool shift, bool alt, bool super);
|
||||
void app_handleKeyboardLEDs(bool numLock, bool capsLock, bool scrollLock);
|
||||
void app_handleEnterEvent(bool entered);
|
||||
@@ -155,14 +155,12 @@ void app_showRecord(bool show);
|
||||
/**
|
||||
* Register a handler for the <super>+<key> combination
|
||||
* @param sc The scancode to register
|
||||
* @param charcode The charcode to register (used instead of sc if non zero)
|
||||
* @param callback The function to be called when the combination is pressed
|
||||
* @param opaque A pointer to be passed to the callback, may be NULL
|
||||
* @retval A handle for the binding or NULL on failure.
|
||||
* The caller is required to release the handle via `app_releaseKeybind` when it is no longer required
|
||||
*/
|
||||
KeybindHandle app_registerKeybind(int sc, int charcode, KeybindFn callback,
|
||||
void * opaque, const char * description);
|
||||
KeybindHandle app_registerKeybind(int sc, KeybindFn callback, void * opaque, const char * description);
|
||||
|
||||
/**
|
||||
* Release an existing key binding
|
||||
@@ -181,14 +179,5 @@ bool app_guestIsOSX(void);
|
||||
bool app_guestIsBSD(void);
|
||||
bool app_guestIsOther(void);
|
||||
|
||||
/**
|
||||
* Enable/disable the LG display
|
||||
*/
|
||||
void app_stopVideo(bool stop);
|
||||
|
||||
/**
|
||||
* Enable/disable the spice display
|
||||
*/
|
||||
bool app_useSpiceDisplay(bool enable);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Looking Glass
|
||||
* Copyright © 2017-2023 The Looking Glass Authors
|
||||
* Copyright © 2017-2022 The Looking Glass Authors
|
||||
* https://looking-glass.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Looking Glass
|
||||
* Copyright © 2017-2023 The Looking Glass Authors
|
||||
* Copyright © 2017-2022 The Looking Glass Authors
|
||||
* https://looking-glass.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Looking Glass
|
||||
* Copyright © 2017-2023 The Looking Glass Authors
|
||||
* Copyright © 2017-2022 The Looking Glass Authors
|
||||
* https://looking-glass.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Looking Glass
|
||||
* Copyright © 2017-2023 The Looking Glass Authors
|
||||
* Copyright © 2017-2022 The Looking Glass Authors
|
||||
* https://looking-glass.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Looking Glass
|
||||
* Copyright © 2017-2023 The Looking Glass Authors
|
||||
* Copyright © 2017-2022 The Looking Glass Authors
|
||||
* https://looking-glass.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
@@ -90,7 +90,6 @@ typedef struct LG_DSInitParams
|
||||
bool resizable;
|
||||
bool borderless;
|
||||
bool maximize;
|
||||
bool largeCursorDot;
|
||||
|
||||
// if true the renderer requires an OpenGL context
|
||||
bool opengl;
|
||||
@@ -111,8 +110,6 @@ typedef struct LGEvent LGEvent;
|
||||
|
||||
struct LG_DisplayServerOps
|
||||
{
|
||||
const char * name;
|
||||
|
||||
/* called before options are parsed, useful for registering options */
|
||||
void (*setup)(void);
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Looking Glass
|
||||
* Copyright © 2017-2023 The Looking Glass Authors
|
||||
* Copyright © 2017-2022 The Looking Glass Authors
|
||||
* https://looking-glass.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Looking Glass
|
||||
* Copyright © 2017-2023 The Looking Glass Authors
|
||||
* Copyright © 2017-2022 The Looking Glass Authors
|
||||
* https://looking-glass.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
@@ -25,8 +25,6 @@
|
||||
|
||||
#include "common/types.h"
|
||||
|
||||
#define TICK_RATE 25
|
||||
|
||||
struct LG_OverlayOps
|
||||
{
|
||||
/* internal name of the overlay for debugging */
|
||||
@@ -65,7 +63,7 @@ struct LG_OverlayOps
|
||||
int (*render)(void * udata, bool interactive, struct Rect * windowRects,
|
||||
int maxRects);
|
||||
|
||||
/* called TICK_RATE times a second by the application
|
||||
/* called 25 times a second by the application
|
||||
*
|
||||
* Note: This may not run in the same context as `render`!
|
||||
*
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Looking Glass
|
||||
* Copyright © 2017-2023 The Looking Glass Authors
|
||||
* Copyright © 2017-2022 The Looking Glass Authors
|
||||
* https://looking-glass.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
@@ -27,22 +27,17 @@
|
||||
#include "common/framebuffer.h"
|
||||
|
||||
#define IS_LG_RENDERER_VALID(x) \
|
||||
((x)->getName && \
|
||||
(x)->create && \
|
||||
(x)->initialize && \
|
||||
(x)->deinitialize && \
|
||||
(x)->onRestart && \
|
||||
(x)->onResize && \
|
||||
(x)->onMouseShape && \
|
||||
(x)->onMouseEvent && \
|
||||
(x)->renderStartup && \
|
||||
(x)->render && \
|
||||
(x)->createTexture && \
|
||||
(x)->freeTexture && \
|
||||
(x)->spiceConfigure && \
|
||||
(x)->spiceDrawFill && \
|
||||
(x)->spiceDrawBitmap && \
|
||||
(x)->spiceShow)
|
||||
((x)->getName && \
|
||||
(x)->create && \
|
||||
(x)->initialize && \
|
||||
(x)->deinitialize && \
|
||||
(x)->onRestart && \
|
||||
(x)->onResize && \
|
||||
(x)->onMouseShape && \
|
||||
(x)->onMouseEvent && \
|
||||
(x)->renderStartup && \
|
||||
(x)->needsRender && \
|
||||
(x)->render)
|
||||
|
||||
typedef struct LG_RendererParams
|
||||
{
|
||||
@@ -72,8 +67,6 @@ 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
|
||||
@@ -165,36 +158,15 @@ typedef struct LG_RendererOps
|
||||
* Context: renderThread */
|
||||
bool (*renderStartup)(LG_Renderer * renderer, bool useDMA);
|
||||
|
||||
/* returns if the render method must be called even if nothing has changed.
|
||||
* Context: renderThread */
|
||||
bool (*needsRender)(LG_Renderer * renderer);
|
||||
|
||||
/* called to render the scene
|
||||
* Context: renderThread */
|
||||
bool (*render)(LG_Renderer * renderer, LG_RendererRotate rotate,
|
||||
const bool newFrame, const bool invalidateWindow,
|
||||
void (*preSwap)(void * udata), void * udata);
|
||||
|
||||
/* called to create a texture from the specified 32-bit RGB image data. This
|
||||
* method is for use with Dear ImGui
|
||||
* Context: renderThread */
|
||||
void * (*createTexture)(LG_Renderer * renderer,
|
||||
int width, int height, uint8_t * data);
|
||||
|
||||
/* called to free a texture previously created by createTexture. This method
|
||||
* is for use with Dear ImGui
|
||||
* Context: renderThread */
|
||||
void (*freeTexture)(LG_Renderer * renderer, void * texture);
|
||||
|
||||
/* setup the spice display */
|
||||
void (*spiceConfigure)(LG_Renderer * renderer, int width, int height);
|
||||
|
||||
/* draw a filled rect on the spice display with the specified color */
|
||||
void (*spiceDrawFill)(LG_Renderer * renderer, int x, int y, int width,
|
||||
int height, uint32_t color);
|
||||
|
||||
/* draw an image on the spice display, data is RGBA32 */
|
||||
void (*spiceDrawBitmap)(LG_Renderer * renderer, int x, int y, int width,
|
||||
int height, int stride, uint8_t * data, bool topDown);
|
||||
|
||||
/* show the spice display */
|
||||
void (*spiceShow)(LG_Renderer * renderer, bool show);
|
||||
}
|
||||
LG_RendererOps;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Looking Glass
|
||||
* Copyright © 2017-2023 The Looking Glass Authors
|
||||
* Copyright © 2017-2022 The Looking Glass Authors
|
||||
* https://looking-glass.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
@@ -27,23 +27,9 @@
|
||||
|
||||
typedef struct ImVec2 ImVec2;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void * tex;
|
||||
int width;
|
||||
int height;
|
||||
}
|
||||
OverlayImage;
|
||||
|
||||
void overlayGetImGuiRect(struct Rect * rect);
|
||||
ImVec2 * overlayGetScreenSize(void);
|
||||
void overlayTextURL(const char * url, const char * text);
|
||||
void overlayTextMaybeURL(const char * text, bool wrapped);
|
||||
|
||||
// create a texture from a SVG and scale it to fit the supplied width & height
|
||||
bool overlayLoadSVG(const char * data, unsigned int size, OverlayImage * image,
|
||||
int width, int height);
|
||||
|
||||
void overlayFreeImage(OverlayImage * image);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Looking Glass
|
||||
* Copyright © 2017-2023 The Looking Glass Authors
|
||||
* Copyright © 2017-2022 The Looking Glass Authors
|
||||
* https://looking-glass.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
|
||||
@@ -3,114 +3,120 @@ project(renderer_EGL LANGUAGES C CXX)
|
||||
|
||||
find_package(PkgConfig)
|
||||
pkg_check_modules(RENDERER_EGL REQUIRED IMPORTED_TARGET
|
||||
egl
|
||||
gl
|
||||
egl
|
||||
gl
|
||||
)
|
||||
|
||||
pkg_check_modules(RENDERER_EGL_OPT IMPORTED_TARGET
|
||||
wayland-egl
|
||||
wayland-egl
|
||||
)
|
||||
|
||||
find_program(AWK NAMES gawk mawk original-awk awk)
|
||||
|
||||
if(AWK MATCHES ".+-NOTFOUND")
|
||||
message(FATAL_ERROR "FATAL: some known version of awk couldn't be found (${AWK}).")
|
||||
message(FATAL_ERROR "FATAL: some known version of awk couldn't be found (${AWK}).")
|
||||
else()
|
||||
message(STATUS "Using awk: ${AWK}")
|
||||
message(STATUS "Using awk: ${AWK}")
|
||||
endif()
|
||||
|
||||
include(MakeObject)
|
||||
function(build_shaders header_dir)
|
||||
file(GLOB headers "${header_dir}/*.h")
|
||||
set(EGL_SHADER_PROCESSED)
|
||||
foreach(shader ${ARGN})
|
||||
set(out_f "${CMAKE_CURRENT_BINARY_DIR}/${shader}")
|
||||
add_custom_command(OUTPUT "${out_f}"
|
||||
COMMAND "${AWK}" -f "${CMAKE_CURRENT_SOURCE_DIR}/glsl.include.awk"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/${shader}" > "${out_f}"
|
||||
MAIN_DEPENDENCY "${CMAKE_CURRENT_SOURCE_DIR}/${shader}"
|
||||
DEPENDS ${headers}
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/shader"
|
||||
COMMENT "Preprocessing shader ${shader}"
|
||||
VERBATIM
|
||||
)
|
||||
endforeach()
|
||||
file(GLOB headers "${header_dir}/*.h")
|
||||
set(EGL_SHADER_PROCESSED)
|
||||
foreach(shader ${ARGN})
|
||||
set(out_f "${CMAKE_CURRENT_BINARY_DIR}/${shader}")
|
||||
add_custom_command(OUTPUT "${out_f}"
|
||||
COMMAND "${AWK}" -f "${CMAKE_CURRENT_SOURCE_DIR}/glsl.include.awk"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/${shader}" > "${out_f}"
|
||||
MAIN_DEPENDENCY "${CMAKE_CURRENT_SOURCE_DIR}/${shader}"
|
||||
DEPENDS ${headers}
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/shader"
|
||||
COMMENT "Preprocessing shader ${shader}"
|
||||
VERBATIM
|
||||
)
|
||||
endforeach()
|
||||
|
||||
set(CMAKE_CURRENT_SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}")
|
||||
make_object(
|
||||
EGL_SHADER
|
||||
${ARGN}
|
||||
)
|
||||
set(CMAKE_CURRENT_SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}")
|
||||
make_object(
|
||||
EGL_SHADER
|
||||
${ARGN}
|
||||
)
|
||||
|
||||
set(EGL_SHADER_OBJS "${EGL_SHADER_OBJS}" PARENT_SCOPE)
|
||||
set(EGL_SHADER_INCS "${EGL_SHADER_INCS}" PARENT_SCOPE)
|
||||
set(EGL_SHADER_OBJS "${EGL_SHADER_OBJS}" PARENT_SCOPE)
|
||||
set(EGL_SHADER_INCS "${EGL_SHADER_INCS}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
build_shaders(
|
||||
shader
|
||||
shader/desktop.vert
|
||||
shader/desktop_rgb.frag
|
||||
shader/cursor.vert
|
||||
shader/cursor_rgb.frag
|
||||
shader/cursor_mono.frag
|
||||
shader/damage.vert
|
||||
shader/damage.frag
|
||||
shader/basic.vert
|
||||
shader/ffx_cas.frag
|
||||
shader/ffx_fsr1_easu.frag
|
||||
shader/ffx_fsr1_rcas.frag
|
||||
shader/downscale.frag
|
||||
shader/downscale_lanczos2.frag
|
||||
shader/downscale_linear.frag
|
||||
shader
|
||||
shader/desktop.vert
|
||||
shader/desktop_rgb.frag
|
||||
shader/cursor.vert
|
||||
shader/cursor_rgb.frag
|
||||
shader/cursor_mono.frag
|
||||
shader/damage.vert
|
||||
shader/damage.frag
|
||||
shader/splash_bg.vert
|
||||
shader/splash_bg.frag
|
||||
shader/splash_logo.vert
|
||||
shader/splash_logo.frag
|
||||
shader/basic.vert
|
||||
shader/ffx_cas.frag
|
||||
shader/ffx_fsr1_easu.frag
|
||||
shader/ffx_fsr1_rcas.frag
|
||||
shader/downscale.frag
|
||||
shader/downscale_lanczos2.frag
|
||||
shader/downscale_linear.frag
|
||||
)
|
||||
|
||||
make_defines(
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/shader/desktop_rgb.frag"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/shader/desktop_rgb.def.h"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/shader/desktop_rgb.frag"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/shader/desktop_rgb.def.h"
|
||||
)
|
||||
|
||||
add_library(renderer_EGL STATIC
|
||||
egl.c
|
||||
egldebug.c
|
||||
shader.c
|
||||
texture_util.c
|
||||
texture.c
|
||||
texture_buffer.c
|
||||
texture_framebuffer.c
|
||||
texture_dmabuf.c
|
||||
model.c
|
||||
desktop.c
|
||||
desktop_rects.c
|
||||
cursor.c
|
||||
damage.c
|
||||
framebuffer.c
|
||||
postprocess.c
|
||||
ffx.c
|
||||
filter.c
|
||||
filter_ffx_cas.c
|
||||
filter_ffx_fsr1.c
|
||||
filter_downscale.c
|
||||
${EGL_SHADER_OBJS}
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/shader/desktop_rgb.def.h"
|
||||
${PROJECT_TOP}/repos/cimgui/imgui/backends/imgui_impl_opengl3.cpp
|
||||
egl.c
|
||||
egldebug.c
|
||||
shader.c
|
||||
texture_util.c
|
||||
texture.c
|
||||
texture_buffer.c
|
||||
texture_framebuffer.c
|
||||
texture_dmabuf.c
|
||||
model.c
|
||||
desktop.c
|
||||
desktop_rects.c
|
||||
cursor.c
|
||||
draw.c
|
||||
splash.c
|
||||
damage.c
|
||||
framebuffer.c
|
||||
postprocess.c
|
||||
ffx.c
|
||||
filter.c
|
||||
filter_ffx_cas.c
|
||||
filter_ffx_fsr1.c
|
||||
filter_downscale.c
|
||||
${EGL_SHADER_OBJS}
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/shader/desktop_rgb.def.h"
|
||||
${PROJECT_TOP}/repos/cimgui/imgui/backends/imgui_impl_opengl3.cpp
|
||||
)
|
||||
|
||||
target_compile_definitions(renderer_EGL PRIVATE CIMGUI_DEFINE_ENUMS_AND_STRUCTS=1 IMGUI_IMPL_OPENGL_ES3)
|
||||
|
||||
target_link_libraries(renderer_EGL
|
||||
PkgConfig::RENDERER_EGL
|
||||
lg_common
|
||||
PkgConfig::RENDERER_EGL
|
||||
lg_common
|
||||
|
||||
cimgui
|
||||
cimgui
|
||||
)
|
||||
if(RENDERER_EGL_OPT_FOUND)
|
||||
target_link_libraries(renderer_EGL
|
||||
PkgConfig::RENDERER_EGL_OPT
|
||||
)
|
||||
target_link_libraries(renderer_EGL
|
||||
PkgConfig::RENDERER_EGL_OPT
|
||||
)
|
||||
endif()
|
||||
|
||||
target_include_directories(renderer_EGL
|
||||
PRIVATE
|
||||
src
|
||||
${EGL_SHADER_INCS}
|
||||
PRIVATE
|
||||
src
|
||||
${EGL_SHADER_INCS}
|
||||
)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Looking Glass
|
||||
* Copyright © 2017-2023 The Looking Glass Authors
|
||||
* Copyright © 2017-2022 The Looking Glass Authors
|
||||
* https://looking-glass.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
@@ -87,7 +87,7 @@ static bool cursorTexInit(struct CursorTex * t,
|
||||
const char * vertex_code , size_t vertex_size,
|
||||
const char * fragment_code, size_t fragment_size)
|
||||
{
|
||||
if (!egl_textureInit(&t->texture, NULL, EGL_TEXTYPE_BUFFER))
|
||||
if (!egl_textureInit(&t->texture, NULL, EGL_TEXTYPE_BUFFER, false))
|
||||
{
|
||||
DEBUG_ERROR("Failed to initialize the cursor texture");
|
||||
return false;
|
||||
@@ -100,7 +100,7 @@ static bool cursorTexInit(struct CursorTex * t,
|
||||
}
|
||||
|
||||
if (!egl_shaderCompile(t->shader,
|
||||
vertex_code, vertex_size, fragment_code, fragment_size, false))
|
||||
vertex_code, vertex_size, fragment_code, fragment_size))
|
||||
{
|
||||
DEBUG_ERROR("Failed to compile the cursor shader");
|
||||
return false;
|
||||
@@ -278,7 +278,7 @@ struct CursorState egl_cursorRender(EGL_Cursor * cursor,
|
||||
|
||||
egl_textureSetup(cursor->mono.texture, EGL_PF_BGRA,
|
||||
cursor->width, cursor->height, sizeof(xor[0]));
|
||||
egl_textureUpdate(cursor->mono.texture, (uint8_t *)xor, true);
|
||||
egl_textureUpdate(cursor->mono.texture, (uint8_t *)xor);
|
||||
}
|
||||
// fall through
|
||||
|
||||
@@ -286,7 +286,7 @@ struct CursorState egl_cursorRender(EGL_Cursor * cursor,
|
||||
{
|
||||
egl_textureSetup(cursor->norm.texture, EGL_PF_BGRA,
|
||||
cursor->width, cursor->height, cursor->stride);
|
||||
egl_textureUpdate(cursor->norm.texture, data, true);
|
||||
egl_textureUpdate(cursor->norm.texture, data);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -314,8 +314,8 @@ struct CursorState egl_cursorRender(EGL_Cursor * cursor,
|
||||
cursor->width, cursor->height, sizeof(and[0]));
|
||||
egl_textureSetup(cursor->mono.texture, EGL_PF_BGRA,
|
||||
cursor->width, cursor->height, sizeof(xor[0]));
|
||||
egl_textureUpdate(cursor->norm.texture, (uint8_t *)and, true);
|
||||
egl_textureUpdate(cursor->mono.texture, (uint8_t *)xor, true);
|
||||
egl_textureUpdate(cursor->norm.texture, (uint8_t *)and);
|
||||
egl_textureUpdate(cursor->mono.texture, (uint8_t *)xor);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Looking Glass
|
||||
* Copyright © 2017-2023 The Looking Glass Authors
|
||||
* Copyright © 2017-2022 The Looking Glass Authors
|
||||
* https://looking-glass.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Looking Glass
|
||||
* Copyright © 2017-2023 The Looking Glass Authors
|
||||
* Copyright © 2017-2022 The Looking Glass Authors
|
||||
* https://looking-glass.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
@@ -76,8 +76,7 @@ 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,
|
||||
false))
|
||||
b_shader_damage_frag, b_shader_damage_frag_size))
|
||||
{
|
||||
DEBUG_ERROR("Failed to compile the damage shader");
|
||||
return false;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Looking Glass
|
||||
* Copyright © 2017-2023 The Looking Glass Authors
|
||||
* Copyright © 2017-2022 The Looking Glass Authors
|
||||
* https://looking-glass.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Looking Glass
|
||||
* Copyright © 2017-2023 The Looking Glass Authors
|
||||
* Copyright © 2017-2022 The Looking Glass Authors
|
||||
* https://looking-glass.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
@@ -46,14 +46,9 @@ 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
|
||||
@@ -62,20 +57,14 @@ struct EGL_Desktop
|
||||
EGLDisplay * display;
|
||||
|
||||
EGL_Texture * texture;
|
||||
struct DesktopShader dmaShader, shader;
|
||||
struct DesktopShader shader;
|
||||
EGL_DesktopRects * mesh;
|
||||
CountedBuffer * matrix;
|
||||
|
||||
// internals
|
||||
int width, height;
|
||||
bool hdr;
|
||||
bool hdrPQ;
|
||||
LG_RendererRotate rotate;
|
||||
|
||||
bool useSpice;
|
||||
int spiceWidth, spiceHeight;
|
||||
EGL_Texture * spiceTexture;
|
||||
|
||||
// scale algorithm
|
||||
int scaleAlgo;
|
||||
|
||||
@@ -89,11 +78,6 @@ 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;
|
||||
};
|
||||
@@ -104,8 +88,7 @@ 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,
|
||||
bool useDMA
|
||||
const char * fragment_code, size_t fragment_size
|
||||
)
|
||||
{
|
||||
if (!egl_shaderInit(&shader->shader))
|
||||
@@ -113,21 +96,16 @@ static bool egl_initDesktopShader(
|
||||
|
||||
if (!egl_shaderCompile(shader->shader,
|
||||
vertex_code , vertex_size,
|
||||
fragment_code, fragment_size,
|
||||
useDMA))
|
||||
fragment_code, fragment_size))
|
||||
{
|
||||
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->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" );
|
||||
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" );
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -147,12 +125,21 @@ bool egl_desktopInit(EGL * egl, EGL_Desktop ** desktop_, EGLDisplay * display,
|
||||
desktop->display = display;
|
||||
|
||||
if (!egl_textureInit(&desktop->texture, display,
|
||||
useDMA ? EGL_TEXTYPE_DMABUF : EGL_TEXTYPE_FRAMEBUFFER))
|
||||
useDMA ? EGL_TEXTYPE_DMABUF : EGL_TEXTYPE_FRAMEBUFFER, true))
|
||||
{
|
||||
DEBUG_ERROR("Failed to initialize the desktop texture");
|
||||
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");
|
||||
@@ -166,28 +153,7 @@ 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,
|
||||
app_registerKeybind(KEY_N, toggleNV, desktop,
|
||||
"Toggle night vision mode");
|
||||
|
||||
desktop->nvMax = option_get_int("egl", "nvGainMax");
|
||||
@@ -196,10 +162,6 @@ 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");
|
||||
@@ -239,12 +201,10 @@ void egl_desktopFree(EGL_Desktop ** desktop)
|
||||
if (!*desktop)
|
||||
return;
|
||||
|
||||
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_textureFree (&(*desktop)->texture );
|
||||
egl_shaderFree (&(*desktop)->shader.shader);
|
||||
egl_desktopRectsFree(&(*desktop)->mesh );
|
||||
countedBufferRelease(&(*desktop)->matrix );
|
||||
|
||||
egl_postProcessFree(&(*desktop)->pp);
|
||||
|
||||
@@ -290,28 +250,6 @@ 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)
|
||||
@@ -344,8 +282,6 @@ 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,
|
||||
@@ -393,7 +329,7 @@ bool egl_desktopUpdate(EGL_Desktop * desktop, const FrameBuffer * frame, int dma
|
||||
|
||||
egl_textureFree(&desktop->texture);
|
||||
if (!egl_textureInit(&desktop->texture, desktop->display,
|
||||
EGL_TEXTYPE_FRAMEBUFFER))
|
||||
EGL_TEXTYPE_FRAMEBUFFER, true))
|
||||
{
|
||||
DEBUG_ERROR("Failed to initialize the desktop texture");
|
||||
return false;
|
||||
@@ -423,27 +359,11 @@ bool egl_desktopRender(EGL_Desktop * desktop, unsigned int outputWidth,
|
||||
const float scaleX, const float scaleY, enum EGL_DesktopScaleType scaleType,
|
||||
LG_RendererRotate rotate, const struct DamageRects * rects)
|
||||
{
|
||||
EGL_Texture * tex;
|
||||
int width, height;
|
||||
|
||||
if (desktop->useSpice)
|
||||
{
|
||||
tex = desktop->spiceTexture;
|
||||
width = desktop->spiceWidth;
|
||||
height = desktop->spiceHeight;
|
||||
}
|
||||
else
|
||||
{
|
||||
tex = desktop->texture;
|
||||
width = desktop->width;
|
||||
height = desktop->height;
|
||||
}
|
||||
|
||||
if (outputWidth == 0 && outputHeight == 0)
|
||||
DEBUG_FATAL("outputWidth || outputHeight == 0");
|
||||
|
||||
enum EGL_TexStatus status;
|
||||
if ((status = egl_textureProcess(tex)) != EGL_TEX_STATUS_OK)
|
||||
if ((status = egl_textureProcess(desktop->texture)) != EGL_TEX_STATUS_OK)
|
||||
{
|
||||
if (status != EGL_TEX_STATUS_NOTREADY)
|
||||
DEBUG_ERROR("Failed to process the desktop texture");
|
||||
@@ -452,25 +372,26 @@ bool egl_desktopRender(EGL_Desktop * desktop, unsigned int outputWidth,
|
||||
int scaleAlgo = EGL_SCALE_NEAREST;
|
||||
|
||||
egl_desktopRectsMatrix((float *)desktop->matrix->data,
|
||||
width, height, x, y, scaleX, scaleY, rotate);
|
||||
egl_desktopRectsUpdate(desktop->mesh, rects, width, height);
|
||||
desktop->width, desktop->height, x, y, scaleX, scaleY, rotate);
|
||||
egl_desktopRectsUpdate(desktop->mesh, rects, desktop->width, desktop->height);
|
||||
|
||||
if (atomic_exchange(&desktop->processFrame, false) ||
|
||||
egl_postProcessConfigModified(desktop->pp))
|
||||
egl_postProcessRun(desktop->pp, tex, desktop->mesh,
|
||||
width, height, outputWidth, outputHeight, desktop->useDMA);
|
||||
egl_postProcessRun(desktop->pp, desktop->texture, desktop->mesh,
|
||||
desktop->width, desktop->height, outputWidth, outputHeight);
|
||||
|
||||
unsigned int finalSizeX, finalSizeY;
|
||||
EGL_Texture * texture = egl_postProcessGetOutput(desktop->pp,
|
||||
GLuint texture = egl_postProcessGetOutput(desktop->pp,
|
||||
&finalSizeX, &finalSizeY);
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
egl_resetViewport(desktop->egl);
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
egl_textureBind(texture);
|
||||
glBindTexture(GL_TEXTURE_2D, texture);
|
||||
glBindSampler(0, desktop->texture->sampler);
|
||||
|
||||
if (finalSizeX > width || finalSizeY > height)
|
||||
if (finalSizeX > desktop->width || finalSizeY > desktop->height)
|
||||
scaleType = EGL_DESKTOP_DOWNSCALE;
|
||||
|
||||
switch (desktop->scaleAlgo)
|
||||
@@ -493,13 +414,7 @@ bool egl_desktopRender(EGL_Desktop * desktop, unsigned int outputWidth,
|
||||
scaleAlgo = desktop->scaleAlgo;
|
||||
}
|
||||
|
||||
const struct DesktopShader * shader =
|
||||
desktop->useDMA && texture == desktop->texture ?
|
||||
&desktop->dmaShader : &desktop->shader;
|
||||
|
||||
const float mapHDRGain =
|
||||
desktop->maxCLL / desktop->peakLuminance;
|
||||
|
||||
const struct DesktopShader * shader = &desktop->shader;
|
||||
EGL_Uniform uniforms[] =
|
||||
{
|
||||
{
|
||||
@@ -510,7 +425,7 @@ bool egl_desktopRender(EGL_Desktop * desktop, unsigned int outputWidth,
|
||||
{
|
||||
.type = EGL_UNIFORM_TYPE_2F,
|
||||
.location = shader->uDesktopSize,
|
||||
.f = { width, height },
|
||||
.f = { desktop->width, desktop->height },
|
||||
},
|
||||
{
|
||||
.type = EGL_UNIFORM_TYPE_M3x2FV,
|
||||
@@ -527,26 +442,6 @@ 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 }
|
||||
}
|
||||
};
|
||||
|
||||
@@ -556,59 +451,3 @@ bool egl_desktopRender(EGL_Desktop * desktop, unsigned int outputWidth,
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
void egl_desktopSpiceConfigure(EGL_Desktop * desktop, int width, int height)
|
||||
{
|
||||
if (!desktop->spiceTexture)
|
||||
if (!egl_textureInit(&desktop->spiceTexture, desktop->display,
|
||||
EGL_TEXTYPE_BUFFER_MAP))
|
||||
{
|
||||
DEBUG_ERROR("Failed to initialize the spice desktop texture");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!egl_textureSetup(
|
||||
desktop->spiceTexture,
|
||||
EGL_PF_BGRA,
|
||||
width,
|
||||
height,
|
||||
width * 4
|
||||
))
|
||||
{
|
||||
DEBUG_ERROR("Failed to setup the spice desktop texture");
|
||||
return;
|
||||
}
|
||||
|
||||
desktop->spiceWidth = width;
|
||||
desktop->spiceHeight = height;
|
||||
}
|
||||
|
||||
void egl_desktopSpiceDrawFill(EGL_Desktop * desktop, int x, int y, int width,
|
||||
int height, uint32_t color)
|
||||
{
|
||||
/* this is a fairly hacky way to do this, but since it's only for the fallback
|
||||
* spice display it's not really an issue */
|
||||
|
||||
uint32_t line[width];
|
||||
for(int x = 0; x < width; ++x)
|
||||
line[x] = color;
|
||||
|
||||
for(; y < height; ++y)
|
||||
egl_textureUpdateRect(desktop->spiceTexture,
|
||||
x, y, width, 1, sizeof(line), (uint8_t *)line, false);
|
||||
|
||||
atomic_store(&desktop->processFrame, true);
|
||||
}
|
||||
|
||||
void egl_desktopSpiceDrawBitmap(EGL_Desktop * desktop, int x, int y, int width,
|
||||
int height, int stride, uint8_t * data, bool topDown)
|
||||
{
|
||||
egl_textureUpdateRect(desktop->spiceTexture,
|
||||
x, y, width, height, stride, data, topDown);
|
||||
atomic_store(&desktop->processFrame, true);
|
||||
}
|
||||
|
||||
void egl_desktopSpiceShow(EGL_Desktop * desktop, bool show)
|
||||
{
|
||||
desktop->useSpice = show;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Looking Glass
|
||||
* Copyright © 2017-2023 The Looking Glass Authors
|
||||
* Copyright © 2017-2022 The Looking Glass Authors
|
||||
* https://looking-glass.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
@@ -50,10 +50,3 @@ bool egl_desktopRender(EGL_Desktop * desktop, unsigned int outputWidth,
|
||||
unsigned int outputHeight, const float x, const float y,
|
||||
const float scaleX, const float scaleY, enum EGL_DesktopScaleType scaleType,
|
||||
LG_RendererRotate rotate, const struct DamageRects * rects);
|
||||
|
||||
void egl_desktopSpiceConfigure(EGL_Desktop * desktop, int width, int height);
|
||||
void egl_desktopSpiceDrawFill(EGL_Desktop * desktop, int x, int y, int width,
|
||||
int height, uint32_t color);
|
||||
void egl_desktopSpiceDrawBitmap(EGL_Desktop * desktop, int x, int y, int width,
|
||||
int height, int stride, uint8_t * data, bool topDown);
|
||||
void egl_desktopSpiceShow(EGL_Desktop * desktop, bool show);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Looking Glass
|
||||
* Copyright © 2017-2023 The Looking Glass Authors
|
||||
* Copyright © 2017-2022 The Looking Glass Authors
|
||||
* https://looking-glass.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
@@ -32,10 +32,6 @@
|
||||
|
||||
struct EGL_DesktopRects
|
||||
{
|
||||
GLfloat * lastVertices;
|
||||
int lastVerticesCount;
|
||||
int lastVerticesSize;
|
||||
|
||||
GLuint buffers[2];
|
||||
GLuint vao;
|
||||
int count;
|
||||
@@ -92,7 +88,6 @@ void egl_desktopRectsFree(EGL_DesktopRects ** rects_)
|
||||
|
||||
glDeleteVertexArrays(1, &rects->vao);
|
||||
glDeleteBuffers(2, rects->buffers);
|
||||
free(rects->lastVertices);
|
||||
free(rects);
|
||||
*rects_ = NULL;
|
||||
}
|
||||
@@ -118,8 +113,7 @@ void egl_desktopRectsUpdate(EGL_DesktopRects * rects, const struct DamageRects *
|
||||
return;
|
||||
}
|
||||
|
||||
const int count = (!data || data->count < 0 ? 1 : data->count) * 8;
|
||||
GLfloat vertices[count];
|
||||
GLfloat vertices[(!data || data->count < 0 ? 1 : data->count) * 8];
|
||||
if (!data || data->count < 0)
|
||||
{
|
||||
FrameDamageRect full = {
|
||||
@@ -137,30 +131,6 @@ void egl_desktopRectsUpdate(EGL_DesktopRects * rects, const struct DamageRects *
|
||||
rectToVertices(vertices + i * 8, data->rects + i);
|
||||
}
|
||||
|
||||
// check if the value actually changed and needs updating
|
||||
if (count == rects->lastVerticesCount &&
|
||||
memcmp(rects->lastVertices, vertices, sizeof(GLfloat) * count) == 0)
|
||||
return;
|
||||
|
||||
// ensure the local storage is large enough
|
||||
if (count > rects->lastVerticesSize)
|
||||
{
|
||||
if (rects->lastVertices)
|
||||
free(rects->lastVertices);
|
||||
|
||||
rects->lastVertices = malloc(sizeof(GLfloat) * count);
|
||||
if (!rects->lastVertices)
|
||||
{
|
||||
DEBUG_ERROR("out of memory");
|
||||
return;
|
||||
}
|
||||
rects->lastVerticesSize = count;
|
||||
}
|
||||
|
||||
// copy the last value for later comparison
|
||||
rects->lastVerticesCount = count;
|
||||
memcpy(rects->lastVertices, vertices, sizeof(GLfloat) * count);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, rects->buffers[0]);
|
||||
glBufferSubData(GL_ARRAY_BUFFER, 0, rects->count * 8 * sizeof(GLfloat), vertices);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Looking Glass
|
||||
* Copyright © 2017-2023 The Looking Glass Authors
|
||||
* Copyright © 2017-2022 The Looking Glass Authors
|
||||
* https://looking-glass.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
|
||||
69
client/renderers/EGL/draw.c
Normal file
69
client/renderers/EGL/draw.c
Normal file
@@ -0,0 +1,69 @@
|
||||
/**
|
||||
* Looking Glass
|
||||
* Copyright © 2017-2022 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 "draw.h"
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
void egl_drawTorus(EGL_Model * model, unsigned int pts, float x, float y,
|
||||
float inner, float outer)
|
||||
{
|
||||
GLfloat * v = malloc(sizeof(*v) * (pts + 1) * 6);
|
||||
GLfloat * dst = v;
|
||||
|
||||
for(unsigned int i = 0; i <= pts; ++i)
|
||||
{
|
||||
const float angle = (i / (float)pts) * M_PI * 2.0f;
|
||||
const float c = cos(angle);
|
||||
const float s = sin(angle);
|
||||
*dst++ = x + (inner * c);
|
||||
*dst++ = y + (inner * s);
|
||||
*dst++ = 0.0f;
|
||||
*dst++ = x + (outer * c);
|
||||
*dst++ = y + (outer * s);
|
||||
*dst++ = 0.0f;
|
||||
}
|
||||
|
||||
egl_modelAddVerts(model, v, NULL, (pts + 1) * 2);
|
||||
free(v);
|
||||
}
|
||||
|
||||
void egl_drawTorusArc(EGL_Model * model, unsigned int pts, float x, float y,
|
||||
float inner, float outer, float s, float e)
|
||||
{
|
||||
GLfloat * v = malloc(sizeof(*v) * (pts + 1) * 6);
|
||||
GLfloat * dst = v;
|
||||
|
||||
for(unsigned int i = 0; i <= pts; ++i)
|
||||
{
|
||||
const float angle = s + ((i / (float)pts) * e);
|
||||
const float c = cos(angle);
|
||||
const float s = sin(angle);
|
||||
*dst++ = x + (inner * c);
|
||||
*dst++ = y + (inner * s);
|
||||
*dst++ = 0.0f;
|
||||
*dst++ = x + (outer * c);
|
||||
*dst++ = y + (outer * s);
|
||||
*dst++ = 0.0f;
|
||||
}
|
||||
|
||||
egl_modelAddVerts(model, v, NULL, (pts + 1) * 2);
|
||||
free(v);
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Looking Glass
|
||||
* Copyright © 2017-2023 The Looking Glass Authors
|
||||
* Copyright © 2017-2022 The Looking Glass Authors
|
||||
* https://looking-glass.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
@@ -20,9 +20,10 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Windows.h>
|
||||
#include <tchar.h>
|
||||
#include "model.h"
|
||||
|
||||
VOID _DBGPRINT(PCSTR kszFunction, INT iLineNumber, LPCSTR kszDebugFormatString, ...);
|
||||
#define DBGPRINT(kszDebugFormatString, ...) \
|
||||
_DBGPRINT(__FUNCTION__, __LINE__, kszDebugFormatString, __VA_ARGS__)
|
||||
void egl_drawTorus(EGL_Model * model, unsigned int pts, float x, float y,
|
||||
float inner, float outer);
|
||||
|
||||
void egl_drawTorusArc(EGL_Model * model, unsigned int pts, float x, float y,
|
||||
float inner, float outer, float s, float e);
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Looking Glass
|
||||
* Copyright © 2017-2023 The Looking Glass Authors
|
||||
* Copyright © 2017-2022 The Looking Glass Authors
|
||||
* https://looking-glass.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
@@ -45,9 +45,11 @@
|
||||
#include "damage.h"
|
||||
#include "desktop.h"
|
||||
#include "cursor.h"
|
||||
#include "splash.h"
|
||||
#include "postprocess.h"
|
||||
#include "util.h"
|
||||
|
||||
#define SPLASH_FADE_TIME 1000000
|
||||
#define MAX_BUFFER_AGE 3
|
||||
#define DESKTOP_DAMAGE_COUNT 4
|
||||
#define MAX_ACCUMULATED_DAMAGE ((KVMFR_MAX_DAMAGE_RECTS + MAX_OVERLAY_RECTS + 2) * MAX_BUFFER_AGE)
|
||||
@@ -75,11 +77,15 @@ struct Inst
|
||||
|
||||
EGL_Desktop * desktop; // the desktop
|
||||
EGL_Cursor * cursor; // the mouse cursor
|
||||
EGL_Splash * splash; // the splash screen
|
||||
EGL_Damage * damage; // the damage display
|
||||
bool imgui; // if imgui was initialized
|
||||
|
||||
LG_RendererFormat format;
|
||||
bool formatValid;
|
||||
bool start;
|
||||
uint64_t waitFadeTime;
|
||||
bool waitDone;
|
||||
|
||||
int width, height;
|
||||
float uiScale;
|
||||
@@ -117,9 +123,6 @@ struct Inst
|
||||
|
||||
RingBuffer importTimings;
|
||||
GraphHandle importGraph;
|
||||
|
||||
bool showSpice;
|
||||
int spiceWidth, spiceHeight;
|
||||
};
|
||||
|
||||
static struct Option egl_options[] =
|
||||
@@ -202,27 +205,6 @@ 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}
|
||||
};
|
||||
@@ -296,10 +278,12 @@ static void egl_deinitialize(LG_Renderer * renderer)
|
||||
if (this->imgui)
|
||||
ImGui_ImplOpenGL3_Shutdown();
|
||||
|
||||
app_unregisterGraph(this->importGraph);
|
||||
ringbuffer_free(&this->importTimings);
|
||||
|
||||
egl_desktopFree(&this->desktop);
|
||||
egl_cursorFree (&this->cursor);
|
||||
egl_splashFree (&this->splash);
|
||||
egl_damageFree (&this->damage);
|
||||
|
||||
LG_LOCK_FREE(this->lock);
|
||||
@@ -338,6 +322,7 @@ static void egl_onRestart(LG_Renderer * renderer)
|
||||
|
||||
eglDestroyContext(this->display, this->frameContext);
|
||||
this->frameContext = NULL;
|
||||
this->start = false;
|
||||
|
||||
INTERLOCKED_SECTION(this->desktopDamageLock, {
|
||||
this->desktopDamage[this->desktopDamageIdx].count = -1;
|
||||
@@ -346,17 +331,6 @@ static void egl_onRestart(LG_Renderer * renderer)
|
||||
|
||||
static void egl_calc_mouse_size(struct Inst * this)
|
||||
{
|
||||
if (this->showSpice)
|
||||
{
|
||||
this->mouseScaleX = 2.0f / this->spiceWidth;
|
||||
this->mouseScaleY = 2.0f / this->spiceHeight;
|
||||
egl_cursorSetSize(this->cursor,
|
||||
(this->mouseWidth * (1.0f / this->spiceWidth )) * this->scaleX,
|
||||
(this->mouseHeight * (1.0f / this->spiceHeight)) * this->scaleY
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this->formatValid)
|
||||
return;
|
||||
|
||||
@@ -406,19 +380,6 @@ static void egl_calc_mouse_size(struct Inst * this)
|
||||
|
||||
static void egl_calc_mouse_state(struct Inst * this)
|
||||
{
|
||||
if (this->showSpice)
|
||||
{
|
||||
egl_cursorSetState(
|
||||
this->cursor,
|
||||
this->cursorVisible,
|
||||
(((float)this->cursorX * this->mouseScaleX) - 1.0f) * this->scaleX,
|
||||
(((float)this->cursorY * this->mouseScaleY) - 1.0f) * this->scaleY,
|
||||
((float)this->cursorHX * this->mouseScaleX) * this->scaleX,
|
||||
((float)this->cursorHY * this->mouseScaleY) * this->scaleY
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this->formatValid)
|
||||
return;
|
||||
|
||||
@@ -501,8 +462,8 @@ static void egl_onResize(LG_Renderer * renderer, const int width, const int heig
|
||||
|
||||
if (destRect.valid)
|
||||
{
|
||||
this->translateX = -1.0f + (((this->destRect.w / 2) + this->destRect.x) * 2) / (float)this->width;
|
||||
this->translateY = 1.0f - (((this->destRect.h / 2) + this->destRect.y) * 2) / (float)this->height;
|
||||
this->translateX = 1.0f - (((this->destRect.w / 2) + this->destRect.x) * 2) / (float)this->width;
|
||||
this->translateY = 1.0f - (((this->destRect.h / 2) + this->destRect.y) * 2) / (float)this->height;
|
||||
this->scaleX = (float)this->destRect.w / (float)this->width;
|
||||
this->scaleY = (float)this->destRect.h / (float)this->height;
|
||||
this->viewportWidth = this->destRect.w;
|
||||
@@ -630,6 +591,8 @@ static bool egl_onFrame(LG_Renderer * renderer, const FrameBuffer * frame, int d
|
||||
}
|
||||
ringbuffer_push(this->importTimings, &(float){ (nanotime() - start) * 1e-6f });
|
||||
|
||||
this->start = true;
|
||||
|
||||
INTERLOCKED_SECTION(this->desktopDamageLock, {
|
||||
struct DesktopDamage * damage = this->desktopDamage + this->desktopDamageIdx;
|
||||
if (damage->count == -1 || damageRectsCount == 0 ||
|
||||
@@ -769,7 +732,7 @@ static bool egl_renderStartup(LG_Renderer * renderer, bool useDMA)
|
||||
|
||||
EGLint attr[] =
|
||||
{
|
||||
EGL_BUFFER_SIZE , 30,
|
||||
EGL_BUFFER_SIZE , 24,
|
||||
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
|
||||
EGL_SAMPLE_BUFFERS , maxSamples > 0 ? 1 : 0,
|
||||
EGL_SAMPLES , maxSamples,
|
||||
@@ -964,6 +927,12 @@ static bool egl_renderStartup(LG_Renderer * renderer, bool useDMA)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!egl_splashInit(&this->splash))
|
||||
{
|
||||
DEBUG_ERROR("Failed to initialize the splash screen");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!egl_damageInit(&this->damage))
|
||||
{
|
||||
DEBUG_ERROR("Failed to initialize the damage display");
|
||||
@@ -982,6 +951,12 @@ static bool egl_renderStartup(LG_Renderer * renderer, bool useDMA)
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool egl_needsRender(LG_Renderer * renderer)
|
||||
{
|
||||
struct Inst * this = UPCAST(struct Inst, renderer);
|
||||
return !this->waitDone;
|
||||
}
|
||||
|
||||
inline static EGLint egl_bufferAge(struct Inst * this)
|
||||
{
|
||||
if (!this->hasBufferAge)
|
||||
@@ -1008,26 +983,21 @@ inline static void renderLetterBox(struct Inst * this)
|
||||
|
||||
if (hLB)
|
||||
{
|
||||
// left
|
||||
glScissor(0, 0, this->destRect.x, this->height);
|
||||
glScissor(0.0f, 0.0f, this->destRect.x + 0.5f, this->height + 0.5f);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
// right
|
||||
float x2 = this->destRect.x + this->destRect.w;
|
||||
glScissor(x2, 0, this->width - x2, this->height);
|
||||
glScissor(x2 - 0.5f, 0.0f, this->width - x2 + 1.0f, this->height + 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
}
|
||||
|
||||
if (vLB)
|
||||
{
|
||||
// top
|
||||
glScissor(0, this->height - this->destRect.y,
|
||||
this->width, this->destRect.y);
|
||||
glScissor(0.0f, 0.0f, this->width + 0.5f, this->destRect.y + 0.5f);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
// bottom
|
||||
int y2 = this->destRect.y + this->destRect.h;
|
||||
glScissor(0, 0, this->width, this->height - y2);
|
||||
float y2 = this->destRect.y + this->destRect.h;
|
||||
glScissor(0.0f, y2 - 0.5f, this->width + 1.0f, this->height - y2 + 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
}
|
||||
|
||||
@@ -1041,9 +1011,8 @@ static bool egl_render(LG_Renderer * renderer, LG_RendererRotate rotate,
|
||||
{
|
||||
struct Inst * this = UPCAST(struct Inst, renderer);
|
||||
EGLint bufferAge = egl_bufferAge(this);
|
||||
bool renderAll = invalidateWindow || this->hadOverlay ||
|
||||
bufferAge <= 0 || bufferAge > MAX_BUFFER_AGE ||
|
||||
this->showSpice;
|
||||
bool renderAll = invalidateWindow || !this->start || this->hadOverlay ||
|
||||
bufferAge <= 0 || bufferAge > MAX_BUFFER_AGE;
|
||||
|
||||
bool hasOverlay = false;
|
||||
struct CursorState cursorState = { .visible = false };
|
||||
@@ -1118,7 +1087,7 @@ static bool egl_render(LG_Renderer * renderer, LG_RendererRotate rotate,
|
||||
}
|
||||
++this->overlayHistoryIdx;
|
||||
|
||||
if (this->destRect.w > 0 && this->destRect.h > 0)
|
||||
if (this->start && this->destRect.w > 0 && this->destRect.h > 0)
|
||||
{
|
||||
if (egl_desktopRender(this->desktop,
|
||||
this->destRect.w, this->destRect.h,
|
||||
@@ -1126,6 +1095,14 @@ static bool egl_render(LG_Renderer * renderer, LG_RendererRotate rotate,
|
||||
this->scaleX , this->scaleY ,
|
||||
this->scaleType , rotate, renderAll ? NULL : accumulated))
|
||||
{
|
||||
if (!this->waitFadeTime)
|
||||
{
|
||||
if (!this->params.quickSplash)
|
||||
this->waitFadeTime = microtime() + SPLASH_FADE_TIME;
|
||||
else
|
||||
this->waitDone = true;
|
||||
}
|
||||
|
||||
cursorState = egl_cursorRender(this->cursor,
|
||||
(this->format.rotate + rotate) % LG_ROTATE_MAX,
|
||||
this->width, this->height);
|
||||
@@ -1136,6 +1113,35 @@ static bool egl_render(LG_Renderer * renderer, LG_RendererRotate rotate,
|
||||
|
||||
renderLetterBox(this);
|
||||
|
||||
if (!this->waitDone)
|
||||
{
|
||||
float a = 1.0f;
|
||||
if (!this->waitFadeTime)
|
||||
a = 1.0f;
|
||||
else
|
||||
{
|
||||
uint64_t t = microtime();
|
||||
if (t > this->waitFadeTime)
|
||||
this->waitDone = true;
|
||||
else
|
||||
{
|
||||
uint64_t delta = this->waitFadeTime - t;
|
||||
a = 1.0f / SPLASH_FADE_TIME * delta;
|
||||
}
|
||||
}
|
||||
|
||||
if (!this->waitDone)
|
||||
{
|
||||
egl_splashRender(this->splash, a, this->splashRatio);
|
||||
hasOverlay = true;
|
||||
}
|
||||
}
|
||||
else if (!this->start)
|
||||
{
|
||||
egl_splashRender(this->splash, 1.0f, this->splashRatio);
|
||||
hasOverlay = true;
|
||||
}
|
||||
|
||||
hasOverlay |= egl_damageRender(this->damage, rotate, newFrame ? desktopDamage : NULL);
|
||||
hasOverlay |= invalidateWindow;
|
||||
|
||||
@@ -1201,72 +1207,6 @@ static bool egl_render(LG_Renderer * renderer, LG_RendererRotate rotate,
|
||||
return true;
|
||||
}
|
||||
|
||||
static void * egl_createTexture(LG_Renderer * renderer,
|
||||
int width, int height, uint8_t * data)
|
||||
{
|
||||
GLuint tex;
|
||||
glGenTextures(1, &tex);
|
||||
glBindTexture(GL_TEXTURE_2D, tex);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, width);
|
||||
glTexImage2D(
|
||||
GL_TEXTURE_2D,
|
||||
0,
|
||||
GL_RGBA,
|
||||
width,
|
||||
height,
|
||||
0,
|
||||
GL_RGBA,
|
||||
GL_UNSIGNED_BYTE,
|
||||
data);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
return (void*)(intptr_t)tex;
|
||||
}
|
||||
|
||||
static void egl_freeTexture(LG_Renderer * renderer, void * texture)
|
||||
{
|
||||
GLuint tex = (GLuint)(intptr_t)texture;
|
||||
glDeleteTextures(1, &tex);
|
||||
}
|
||||
|
||||
static void egl_spiceConfigure(LG_Renderer * renderer, int width, int height)
|
||||
{
|
||||
struct Inst * this = UPCAST(struct Inst, renderer);
|
||||
this->spiceWidth = width;
|
||||
this->spiceHeight = height;
|
||||
egl_desktopSpiceConfigure(this->desktop, width, height);
|
||||
}
|
||||
|
||||
static void egl_spiceDrawFill(LG_Renderer * renderer, int x, int y, int width,
|
||||
int height, uint32_t color)
|
||||
{
|
||||
struct Inst * this = UPCAST(struct Inst, renderer);
|
||||
egl_desktopSpiceDrawFill(this->desktop, x, y, width, height, color);
|
||||
}
|
||||
|
||||
static void egl_spiceDrawBitmap(LG_Renderer * renderer, int x, int y, int width,
|
||||
int height, int stride, uint8_t * data, bool topDown)
|
||||
{
|
||||
struct Inst * this = UPCAST(struct Inst, renderer);
|
||||
egl_desktopSpiceDrawBitmap(this->desktop, x, y, width, height, stride,
|
||||
data, topDown);
|
||||
}
|
||||
|
||||
static void egl_spiceShow(LG_Renderer * renderer, bool show)
|
||||
{
|
||||
struct Inst * this = UPCAST(struct Inst, renderer);
|
||||
this->showSpice = show;
|
||||
egl_calc_mouse_size(this);
|
||||
egl_desktopSpiceShow(this->desktop, show);
|
||||
}
|
||||
|
||||
struct LG_RendererOps LGR_EGL =
|
||||
{
|
||||
.getName = egl_getName,
|
||||
@@ -1282,12 +1222,6 @@ struct LG_RendererOps LGR_EGL =
|
||||
.onFrameFormat = egl_onFrameFormat,
|
||||
.onFrame = egl_onFrame,
|
||||
.renderStartup = egl_renderStartup,
|
||||
.render = egl_render,
|
||||
.createTexture = egl_createTexture,
|
||||
.freeTexture = egl_freeTexture,
|
||||
|
||||
.spiceConfigure = egl_spiceConfigure,
|
||||
.spiceDrawFill = egl_spiceDrawFill,
|
||||
.spiceDrawBitmap = egl_spiceDrawBitmap,
|
||||
.spiceShow = egl_spiceShow
|
||||
.needsRender = egl_needsRender,
|
||||
.render = egl_render
|
||||
};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Looking Glass
|
||||
* Copyright © 2017-2023 The Looking Glass Authors
|
||||
* Copyright © 2017-2022 The Looking Glass Authors
|
||||
* https://looking-glass.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Looking Glass
|
||||
* Copyright © 2017-2023 The Looking Glass Authors
|
||||
* Copyright © 2017-2022 The Looking Glass Authors
|
||||
* https://looking-glass.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Looking Glass
|
||||
* Copyright © 2017-2023 The Looking Glass Authors
|
||||
* Copyright © 2017-2022 The Looking Glass Authors
|
||||
* https://looking-glass.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Looking Glass
|
||||
* Copyright © 2017-2023 The Looking Glass Authors
|
||||
* Copyright © 2017-2022 The Looking Glass Authors
|
||||
* https://looking-glass.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
@@ -25,8 +25,6 @@
|
||||
typedef enum EGL_TexType
|
||||
{
|
||||
EGL_TEXTYPE_BUFFER,
|
||||
EGL_TEXTYPE_BUFFER_MAP,
|
||||
EGL_TEXTYPE_BUFFER_STREAM,
|
||||
EGL_TEXTYPE_FRAMEBUFFER,
|
||||
EGL_TEXTYPE_DMABUF
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Looking Glass
|
||||
* Copyright © 2017-2023 The Looking Glass Authors
|
||||
* Copyright © 2017-2022 The Looking Glass Authors
|
||||
* https://looking-glass.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Looking Glass
|
||||
* Copyright © 2017-2023 The Looking Glass Authors
|
||||
* Copyright © 2017-2022 The Looking Glass Authors
|
||||
* https://looking-glass.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Looking Glass
|
||||
* Copyright © 2017-2023 The Looking Glass Authors
|
||||
* Copyright © 2017-2022 The Looking Glass Authors
|
||||
* https://looking-glass.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Looking Glass
|
||||
* Copyright © 2017-2023 The Looking Glass Authors
|
||||
* Copyright © 2017-2022 The Looking Glass Authors
|
||||
* https://looking-glass.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
@@ -68,11 +68,9 @@ typedef struct EGL_FilterOps
|
||||
/* reads filter state from options */
|
||||
void (*loadState)(EGL_Filter * filter);
|
||||
|
||||
/* set the input format of the filter
|
||||
* useDMA will be true if the texture provided needs to use samplerExternalOES
|
||||
*/
|
||||
/* set the input format of the filter */
|
||||
bool (*setup)(EGL_Filter * filter, enum EGL_PixelFormat pixFmt,
|
||||
unsigned int width, unsigned int height, bool useDMA);
|
||||
unsigned int width, unsigned int height);
|
||||
|
||||
/* set the output resolution hint for the filter
|
||||
* this is optional and only a hint */
|
||||
@@ -89,8 +87,8 @@ typedef struct EGL_FilterOps
|
||||
|
||||
/* runs the filter on the provided texture
|
||||
* returns the processed texture as the output */
|
||||
EGL_Texture * (*run)(EGL_Filter * filter, EGL_FilterRects * rects,
|
||||
EGL_Texture * texture);
|
||||
GLuint (*run)(EGL_Filter * filter, EGL_FilterRects * rects,
|
||||
GLuint texture);
|
||||
|
||||
/* called when the filter output is no loger needed so it can release memory
|
||||
* this is optional */
|
||||
@@ -135,10 +133,9 @@ 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,
|
||||
bool useDMA)
|
||||
enum EGL_PixelFormat pixFmt, unsigned int width, unsigned int height)
|
||||
{
|
||||
return filter->ops.setup(filter, pixFmt, width, height, useDMA);
|
||||
return filter->ops.setup(filter, pixFmt, width, height);
|
||||
}
|
||||
|
||||
static inline void egl_filterSetOutputResHint(EGL_Filter * filter,
|
||||
@@ -159,8 +156,8 @@ static inline bool egl_filterPrepare(EGL_Filter * filter)
|
||||
return filter->ops.prepare(filter);
|
||||
}
|
||||
|
||||
static inline EGL_Texture * egl_filterRun(EGL_Filter * filter,
|
||||
EGL_FilterRects * rects, EGL_Texture * texture)
|
||||
static inline GLuint egl_filterRun(EGL_Filter * filter,
|
||||
EGL_FilterRects * rects, GLuint texture)
|
||||
{
|
||||
return filter->ops.run(filter, rects, texture);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Looking Glass
|
||||
* Copyright © 2017-2023 The Looking Glass Authors
|
||||
* Copyright © 2017-2022 The Looking Glass Authors
|
||||
* https://looking-glass.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
@@ -60,7 +60,6 @@ typedef struct EGL_FilterDownscale
|
||||
EGL_Shader * lanczos2;
|
||||
|
||||
DownscaleFilter filter;
|
||||
int useDMA;
|
||||
enum EGL_PixelFormat pixFmt;
|
||||
unsigned int width, height;
|
||||
float pixelSize;
|
||||
@@ -158,26 +157,55 @@ 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");
|
||||
@@ -298,8 +326,7 @@ static bool egl_filterDownscaleImguiConfig(EGL_Filter * filter)
|
||||
}
|
||||
|
||||
static bool egl_filterDownscaleSetup(EGL_Filter * filter,
|
||||
enum EGL_PixelFormat pixFmt, unsigned int width, unsigned int height,
|
||||
bool useDMA)
|
||||
enum EGL_PixelFormat pixFmt, unsigned int width, unsigned int height)
|
||||
{
|
||||
EGL_FilterDownscale * this = UPCAST(EGL_FilterDownscale, filter);
|
||||
|
||||
@@ -309,48 +336,6 @@ 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 &&
|
||||
@@ -400,15 +385,15 @@ static bool egl_filterDownscalePrepare(EGL_Filter * filter)
|
||||
return true;
|
||||
}
|
||||
|
||||
static EGL_Texture * egl_filterDownscaleRun(EGL_Filter * filter,
|
||||
EGL_FilterRects * rects, EGL_Texture * texture)
|
||||
static GLuint egl_filterDownscaleRun(EGL_Filter * filter,
|
||||
EGL_FilterRects * rects, GLuint texture)
|
||||
{
|
||||
EGL_FilterDownscale * this = UPCAST(EGL_FilterDownscale, filter);
|
||||
|
||||
egl_framebufferBind(this->fb);
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
egl_textureBind(texture);
|
||||
glBindTexture(GL_TEXTURE_2D, texture);
|
||||
|
||||
EGL_Shader * shader;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Looking Glass
|
||||
* Copyright © 2017-2023 The Looking Glass Authors
|
||||
* Copyright © 2017-2022 The Looking Glass Authors
|
||||
* https://looking-glass.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
@@ -37,7 +37,6 @@ typedef struct EGL_FilterFFXCAS
|
||||
EGL_Shader * shader;
|
||||
bool enable;
|
||||
|
||||
int useDMA;
|
||||
enum EGL_PixelFormat pixFmt;
|
||||
unsigned int width, height;
|
||||
float sharpness;
|
||||
@@ -107,14 +106,21 @@ 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)
|
||||
{
|
||||
@@ -122,6 +128,12 @@ 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))
|
||||
@@ -208,35 +220,13 @@ static bool egl_filterFFXCASImguiConfig(EGL_Filter * filter)
|
||||
}
|
||||
|
||||
static bool egl_filterFFXCASSetup(EGL_Filter * filter,
|
||||
enum EGL_PixelFormat pixFmt, unsigned int width, unsigned int height,
|
||||
bool useDMA)
|
||||
enum EGL_PixelFormat pixFmt, unsigned int width, unsigned int height)
|
||||
{
|
||||
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;
|
||||
|
||||
@@ -272,15 +262,15 @@ static bool egl_filterFFXCASPrepare(EGL_Filter * filter)
|
||||
return true;
|
||||
}
|
||||
|
||||
static EGL_Texture * egl_filterFFXCASRun(EGL_Filter * filter,
|
||||
EGL_FilterRects * rects, EGL_Texture * texture)
|
||||
static GLuint egl_filterFFXCASRun(EGL_Filter * filter,
|
||||
EGL_FilterRects * rects, GLuint texture)
|
||||
{
|
||||
EGL_FilterFFXCAS * this = UPCAST(EGL_FilterFFXCAS, filter);
|
||||
|
||||
egl_framebufferBind(this->fb);
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
egl_textureBind(texture);
|
||||
glBindTexture(GL_TEXTURE_2D, texture);
|
||||
glBindSampler(0, this->sampler);
|
||||
|
||||
egl_shaderUse(this->shader);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Looking Glass
|
||||
* Copyright © 2017-2023 The Looking Glass Authors
|
||||
* Copyright © 2017-2022 The Looking Glass Authors
|
||||
* https://looking-glass.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
@@ -42,7 +42,6 @@ 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;
|
||||
@@ -110,8 +109,6 @@ 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");
|
||||
@@ -124,10 +121,18 @@ 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,
|
||||
false)
|
||||
b_shader_ffx_fsr1_rcas_frag, b_shader_ffx_fsr1_rcas_frag_size)
|
||||
)
|
||||
{
|
||||
DEBUG_ERROR("Failed to compile the Rcas shader");
|
||||
@@ -143,6 +148,14 @@ 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);
|
||||
@@ -322,37 +335,13 @@ static void egl_filterFFXFSR1SetOutputResHint(EGL_Filter * filter,
|
||||
}
|
||||
|
||||
static bool egl_filterFFXFSR1Setup(EGL_Filter * filter,
|
||||
enum EGL_PixelFormat pixFmt, unsigned int width, unsigned int height,
|
||||
bool useDMA)
|
||||
enum EGL_PixelFormat pixFmt, unsigned int width, unsigned int height)
|
||||
{
|
||||
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;
|
||||
@@ -406,15 +395,15 @@ static bool egl_filterFFXFSR1Prepare(EGL_Filter * filter)
|
||||
return true;
|
||||
}
|
||||
|
||||
static EGL_Texture * egl_filterFFXFSR1Run(EGL_Filter * filter,
|
||||
EGL_FilterRects * rects, EGL_Texture * texture)
|
||||
static GLuint egl_filterFFXFSR1Run(EGL_Filter * filter,
|
||||
EGL_FilterRects * rects, GLuint texture)
|
||||
{
|
||||
EGL_FilterFFXFSR1 * this = UPCAST(EGL_FilterFFXFSR1, filter);
|
||||
|
||||
// pass 1, Easu
|
||||
egl_framebufferBind(this->easuFb);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
egl_textureBind(texture);
|
||||
glBindTexture(GL_TEXTURE_2D, texture);
|
||||
glBindSampler(0, this->sampler);
|
||||
egl_shaderUse(this->easu);
|
||||
egl_filterRectsRender(this->easu, rects);
|
||||
@@ -423,7 +412,7 @@ static EGL_Texture * egl_filterFFXFSR1Run(EGL_Filter * filter,
|
||||
// pass 2, Rcas
|
||||
egl_framebufferBind(this->rcasFb);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
egl_textureBind(texture);
|
||||
glBindTexture(GL_TEXTURE_2D, texture);
|
||||
glBindSampler(0, this->sampler);
|
||||
egl_shaderUse(this->rcas);
|
||||
egl_filterRectsRender(this->rcas, rects);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Looking Glass
|
||||
* Copyright © 2017-2023 The Looking Glass Authors
|
||||
* Copyright © 2017-2022 The Looking Glass Authors
|
||||
* https://looking-glass.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Looking Glass
|
||||
* Copyright © 2017-2023 The Looking Glass Authors
|
||||
* Copyright © 2017-2022 The Looking Glass Authors
|
||||
* https://looking-glass.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
@@ -40,7 +40,7 @@ bool egl_framebufferInit(EGL_Framebuffer ** fb)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!egl_textureInit(&this->tex, NULL, EGL_TEXTYPE_BUFFER))
|
||||
if (!egl_textureInit(&this->tex, NULL, EGL_TEXTYPE_BUFFER, false))
|
||||
{
|
||||
DEBUG_ERROR("Failed to initialize the texture");
|
||||
return false;
|
||||
@@ -100,7 +100,9 @@ void egl_framebufferBind(EGL_Framebuffer * this)
|
||||
glViewport(0, 0, this->tex->format.width, this->tex->format.height);
|
||||
}
|
||||
|
||||
EGL_Texture * egl_framebufferGetTexture(EGL_Framebuffer * this)
|
||||
GLuint egl_framebufferGetTexture(EGL_Framebuffer * this)
|
||||
{
|
||||
return this->tex;
|
||||
GLuint output;
|
||||
egl_textureGet(this->tex, &output, NULL, NULL);
|
||||
return output;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Looking Glass
|
||||
* Copyright © 2017-2023 The Looking Glass Authors
|
||||
* Copyright © 2017-2022 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);
|
||||
|
||||
EGL_Texture * egl_framebufferGetTexture(EGL_Framebuffer * this);
|
||||
GLuint egl_framebufferGetTexture(EGL_Framebuffer * this);
|
||||
|
||||
@@ -10,4 +10,4 @@ function process(line, second) {
|
||||
}
|
||||
}
|
||||
|
||||
{ process($0, $2) } END { print "\0"; }
|
||||
{ process($0, $2) }
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Looking Glass
|
||||
* Copyright © 2017-2023 The Looking Glass Authors
|
||||
* Copyright © 2017-2022 The Looking Glass Authors
|
||||
* https://looking-glass.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Looking Glass
|
||||
* Copyright © 2017-2023 The Looking Glass Authors
|
||||
* Copyright © 2017-2022 The Looking Glass Authors
|
||||
* https://looking-glass.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Looking Glass
|
||||
* Copyright © 2017-2023 The Looking Glass Authors
|
||||
* Copyright © 2017-2022 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;
|
||||
EGL_Texture * output;
|
||||
GLuint output;
|
||||
unsigned int outputX, outputY;
|
||||
_Atomic(bool) modified;
|
||||
|
||||
@@ -527,7 +527,7 @@ static void configUI(void * opaque, int * id)
|
||||
if (redraw)
|
||||
{
|
||||
atomic_store(&this->modified, true);
|
||||
app_invalidateWindow(true);
|
||||
app_invalidateWindow(false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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, bool useDMA)
|
||||
unsigned int targetX, unsigned int targetY)
|
||||
{
|
||||
if (targetX == 0 && targetY == 0)
|
||||
DEBUG_FATAL("targetX || targetY == 0");
|
||||
@@ -614,9 +614,8 @@ bool egl_postProcessRun(EGL_PostProcess * this, EGL_Texture * tex,
|
||||
EGL_Filter * lastFilter = NULL;
|
||||
unsigned int sizeX, sizeY;
|
||||
|
||||
//TODO: clean this up
|
||||
GLuint _unused;
|
||||
if (egl_textureGet(tex, &_unused, &sizeX, &sizeY) != EGL_TEX_STATUS_OK)
|
||||
GLuint texture;
|
||||
if (egl_textureGet(tex, &texture, &sizeX, &sizeY) != EGL_TEX_STATUS_OK)
|
||||
return false;
|
||||
|
||||
if (atomic_exchange(&this->modified, false))
|
||||
@@ -637,12 +636,11 @@ 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, useDMA) ||
|
||||
if (!egl_filterSetup(filter, tex->format.pixFmt, sizeX, sizeY) ||
|
||||
!egl_filterPrepare(filter))
|
||||
continue;
|
||||
|
||||
@@ -653,9 +651,6 @@ 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;
|
||||
@@ -664,7 +659,7 @@ bool egl_postProcessRun(EGL_PostProcess * this, EGL_Texture * tex,
|
||||
return true;
|
||||
}
|
||||
|
||||
EGL_Texture * egl_postProcessGetOutput(EGL_PostProcess * this,
|
||||
GLuint egl_postProcessGetOutput(EGL_PostProcess * this,
|
||||
unsigned int * outputX, unsigned int * outputY)
|
||||
{
|
||||
*outputX = this->outputX;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Looking Glass
|
||||
* Copyright © 2017-2023 The Looking Glass Authors
|
||||
* Copyright © 2017-2022 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, bool useDMA);
|
||||
unsigned int targetX, unsigned int targetY);
|
||||
|
||||
EGL_Texture * egl_postProcessGetOutput(EGL_PostProcess * this,
|
||||
GLuint egl_postProcessGetOutput(EGL_PostProcess * this,
|
||||
unsigned int * outputX, unsigned int * outputY);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Looking Glass
|
||||
* Copyright © 2017-2023 The Looking Glass Authors
|
||||
* Copyright © 2017-2022 The Looking Glass Authors
|
||||
* https://looking-glass.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
@@ -64,8 +64,7 @@ void egl_shaderFree(EGL_Shader ** shader)
|
||||
*shader = NULL;
|
||||
}
|
||||
|
||||
bool egl_shaderLoad(EGL_Shader * this,
|
||||
const char * vertex_file, const char * fragment_file, bool useDMA)
|
||||
bool egl_shaderLoad(EGL_Shader * this, const char * vertex_file, const char * fragment_file)
|
||||
{
|
||||
char * vertex_code, * fragment_code;
|
||||
size_t vertex_size, fragment_size;
|
||||
@@ -87,16 +86,13 @@ bool egl_shaderLoad(EGL_Shader * this,
|
||||
|
||||
DEBUG_INFO("Loaded fragment shader: %s", fragment_file);
|
||||
|
||||
bool ret = egl_shaderCompile(this,
|
||||
vertex_code, vertex_size, fragment_code, fragment_size,
|
||||
useDMA);
|
||||
|
||||
bool ret = egl_shaderCompile(this, vertex_code, vertex_size, fragment_code, fragment_size);
|
||||
free(vertex_code);
|
||||
free(fragment_code);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool shaderCompile(EGL_Shader * this, const char * vertex_code,
|
||||
bool egl_shaderCompile(EGL_Shader * this, const char * vertex_code,
|
||||
size_t vertex_size, const char * fragment_code, size_t fragment_size)
|
||||
{
|
||||
if (this->hasShader)
|
||||
@@ -208,64 +204,6 @@ static bool 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);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Looking Glass
|
||||
* Copyright © 2017-2023 The Looking Glass Authors
|
||||
* Copyright © 2017-2022 The Looking Glass Authors
|
||||
* https://looking-glass.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
@@ -97,11 +97,10 @@ 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, bool useDMA);
|
||||
const char * fragment_file);
|
||||
|
||||
bool egl_shaderCompile(EGL_Shader * model, const char * vertex_code,
|
||||
size_t vertex_size, const char * fragment_code, size_t fragment_size,
|
||||
bool useDMA);
|
||||
size_t vertex_size, const char * fragment_code, size_t fragment_size);
|
||||
|
||||
void egl_shaderSetUniforms(EGL_Shader * shader, EGL_Uniform * uniforms,
|
||||
int count);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#version 300 es
|
||||
precision highp float;
|
||||
precision mediump float;
|
||||
|
||||
layout(location = 0) in vec2 vertex;
|
||||
out vec2 fragCoord;
|
||||
|
||||
@@ -1,21 +1,16 @@
|
||||
#if __VERSION__ == 300
|
||||
vec4 textureGather(sampler2D tex, vec2 uv, int comp)
|
||||
{
|
||||
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);
|
||||
|
||||
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));
|
||||
return vec4(c0[comp], c1[comp], c2[comp],c3[comp]);
|
||||
}
|
||||
#elif __VERSION__ < 300
|
||||
vec4 textureGather(sampler2D tex, vec2 uv, int comp)
|
||||
{
|
||||
vec4 c3 = texture(tex, uv);
|
||||
vec4 c3 = texture2D(tex, uv);
|
||||
return vec4(c3[comp], c3[comp], c3[comp],c3[comp]);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#version 300 es
|
||||
precision highp float;
|
||||
precision mediump float;
|
||||
|
||||
layout(location = 0) in vec3 vertexPosition_modelspace;
|
||||
layout(location = 1) in vec2 vertexUV;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#version 300 es
|
||||
precision highp float;
|
||||
precision mediump float;
|
||||
|
||||
in vec2 uv;
|
||||
out vec4 color;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#version 300 es
|
||||
precision highp float;
|
||||
precision mediump float;
|
||||
|
||||
#include "color_blind.h"
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#version 300 es
|
||||
precision highp float;
|
||||
precision mediump float;
|
||||
|
||||
out vec4 color;
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#version 300 es
|
||||
precision highp float;
|
||||
precision mediump float;
|
||||
|
||||
layout(location = 0) in vec2 vertex;
|
||||
out vec2 uv;
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
#version 300 es
|
||||
#extension GL_OES_EGL_image_external_essl3 : enable
|
||||
|
||||
precision highp float;
|
||||
precision mediump float;
|
||||
|
||||
#define EGL_SCALE_AUTO 0
|
||||
#define EGL_SCALE_NEAREST 1
|
||||
@@ -9,7 +7,6 @@ precision highp float;
|
||||
#define EGL_SCALE_MAX 3
|
||||
|
||||
#include "color_blind.h"
|
||||
#include "hdr.h"
|
||||
|
||||
in vec2 uv;
|
||||
out vec4 color;
|
||||
@@ -20,32 +17,21 @@ 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);
|
||||
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
#version 300 es
|
||||
#extension GL_OES_EGL_image_external_essl3 : enable
|
||||
|
||||
precision highp float;
|
||||
precision mediump float;
|
||||
|
||||
in vec2 fragCoord;
|
||||
out vec4 fragColor;
|
||||
|
||||
uniform sampler2D sampler1;
|
||||
uniform sampler2D texture;
|
||||
uniform vec3 uConfig;
|
||||
|
||||
void main()
|
||||
@@ -15,7 +13,7 @@ void main()
|
||||
float vOffset = uConfig.y;
|
||||
float hOffset = uConfig.z;
|
||||
|
||||
vec2 inRes = vec2(textureSize(sampler1, 0));
|
||||
vec2 inRes = vec2(textureSize(texture, 0));
|
||||
ivec2 point = ivec2(
|
||||
(floor((fragCoord * inRes) / pixelSize) * pixelSize) +
|
||||
pixelSize / 2.0f
|
||||
@@ -24,5 +22,5 @@ void main()
|
||||
point.x += int(pixelSize * hOffset);
|
||||
point.y += int(pixelSize * vOffset);
|
||||
|
||||
fragColor = texelFetch(sampler1, point, 0);
|
||||
fragColor = texelFetch(texture, point, 0);
|
||||
}
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
#version 300 es
|
||||
#extension GL_OES_EGL_image_external_essl3 : enable
|
||||
|
||||
precision highp float;
|
||||
precision mediump float;
|
||||
|
||||
#define PI 3.141592653589793
|
||||
|
||||
in vec2 fragCoord;
|
||||
out vec4 fragColor;
|
||||
|
||||
uniform sampler2D sampler1;
|
||||
uniform sampler2D texture;
|
||||
float sinc(float x)
|
||||
{
|
||||
return x == 0.0 ? 1.0 : sin(x * PI) / (x * PI);
|
||||
@@ -26,7 +24,7 @@ float lanczos(vec2 v)
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 size = vec2(textureSize(sampler1, 0));
|
||||
vec2 size = vec2(textureSize(texture, 0));
|
||||
vec2 pos = fragCoord * size;
|
||||
vec2 invSize = 1.0 / size;
|
||||
vec2 uvc = floor(pos) + vec2(0.5, 0.5);
|
||||
@@ -56,7 +54,7 @@ void main()
|
||||
|
||||
vec3 color = vec3(0.0);
|
||||
for (int i = 0; i < 9; ++i)
|
||||
color += texture(sampler1, uvs[i] * invSize).rgb * factors[i];
|
||||
color += texture2D(texture, uvs[i] * invSize).rgb * factors[i];
|
||||
|
||||
fragColor = vec4(color, 1.0);
|
||||
}
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
#version 300 es
|
||||
#extension GL_OES_EGL_image_external_essl3 : enable
|
||||
|
||||
precision highp float;
|
||||
precision mediump float;
|
||||
|
||||
in vec2 fragCoord;
|
||||
out vec4 fragColor;
|
||||
|
||||
uniform sampler2D sampler1;
|
||||
uniform sampler2D texture;
|
||||
|
||||
void main()
|
||||
{
|
||||
fragColor = texture(sampler1, fragCoord);
|
||||
fragColor = texture2D(texture, fragCoord);
|
||||
}
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
#version 300 es
|
||||
#extension GL_OES_EGL_image_external_essl3 : enable
|
||||
|
||||
precision highp float;
|
||||
precision mediump float;
|
||||
|
||||
#include "compat.h"
|
||||
|
||||
in vec2 fragCoord;
|
||||
out vec4 fragColor;
|
||||
|
||||
uniform sampler2D sampler1;
|
||||
uniform sampler2D texture;
|
||||
uniform uvec4 uConsts[2];
|
||||
|
||||
#define A_GPU 1
|
||||
@@ -18,7 +16,7 @@ uniform uvec4 uConsts[2];
|
||||
|
||||
vec3 imageLoad(ivec2 point)
|
||||
{
|
||||
return texelFetch(sampler1, point, 0).rgb;
|
||||
return texelFetch(texture, point, 0).rgb;
|
||||
}
|
||||
|
||||
AF3 CasLoad(ASU2 p)
|
||||
@@ -32,7 +30,7 @@ void CasInput(inout AF1 r,inout AF1 g,inout AF1 b) {}
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 res = vec2(textureSize(sampler1, 0));
|
||||
vec2 res = vec2(textureSize(texture, 0));
|
||||
uvec2 point = uvec2(fragCoord * res);
|
||||
|
||||
CasFilter(
|
||||
|
||||
@@ -747,12 +747,12 @@ AF1 sharpness){
|
||||
// Immediate constants for peak range.
|
||||
AF2 peakC=AF2(1.0,-1.0*4.0);
|
||||
// Limiters, these need to be high precision RCPs.
|
||||
AF1 hitMinR=min(mn4R,eR)*ARcpF1(AF1_(4.0)*mx4R);
|
||||
AF1 hitMinG=min(mn4G,eG)*ARcpF1(AF1_(4.0)*mx4G);
|
||||
AF1 hitMinB=min(mn4B,eB)*ARcpF1(AF1_(4.0)*mx4B);
|
||||
AF1 hitMaxR=(peakC.x-max(mx4R,eR))*ARcpF1(AF1_(4.0)*mn4R+peakC.y);
|
||||
AF1 hitMaxG=(peakC.x-max(mx4G,eG))*ARcpF1(AF1_(4.0)*mn4G+peakC.y);
|
||||
AF1 hitMaxB=(peakC.x-max(mx4B,eB))*ARcpF1(AF1_(4.0)*mn4B+peakC.y);
|
||||
AF1 hitMinR=mn4R*ARcpF1(AF1_(4.0)*mx4R);
|
||||
AF1 hitMinG=mn4G*ARcpF1(AF1_(4.0)*mx4G);
|
||||
AF1 hitMinB=mn4B*ARcpF1(AF1_(4.0)*mx4B);
|
||||
AF1 hitMaxR=(peakC.x-mx4R)*ARcpF1(AF1_(4.0)*mn4R+peakC.y);
|
||||
AF1 hitMaxG=(peakC.x-mx4G)*ARcpF1(AF1_(4.0)*mn4G+peakC.y);
|
||||
AF1 hitMaxB=(peakC.x-mx4B)*ARcpF1(AF1_(4.0)*mn4B+peakC.y);
|
||||
AF1 lobeR=max(-hitMinR,hitMaxR);
|
||||
AF1 lobeG=max(-hitMinG,hitMaxG);
|
||||
AF1 lobeB=max(-hitMinB,hitMaxB);
|
||||
@@ -845,12 +845,12 @@ AF1 sharpness){
|
||||
// Immediate constants for peak range.
|
||||
AH2 peakC=AH2(1.0,-1.0*4.0);
|
||||
// Limiters, these need to be high precision RCPs.
|
||||
AH1 hitMinR=min(mn4R,eR)*ARcpH1(AH1_(4.0)*mx4R);
|
||||
AH1 hitMinG=min(mn4G,eG)*ARcpH1(AH1_(4.0)*mx4G);
|
||||
AH1 hitMinB=min(mn4B,eB)*ARcpH1(AH1_(4.0)*mx4B);
|
||||
AH1 hitMaxR=(peakC.x-max(mx4R,eR))*ARcpH1(AH1_(4.0)*mn4R+peakC.y);
|
||||
AH1 hitMaxG=(peakC.x-max(mx4G,eG))*ARcpH1(AH1_(4.0)*mn4G+peakC.y);
|
||||
AH1 hitMaxB=(peakC.x-max(mx4B,eB))*ARcpH1(AH1_(4.0)*mn4B+peakC.y);
|
||||
AH1 hitMinR=mn4R*ARcpH1(AH1_(4.0)*mx4R);
|
||||
AH1 hitMinG=mn4G*ARcpH1(AH1_(4.0)*mx4G);
|
||||
AH1 hitMinB=mn4B*ARcpH1(AH1_(4.0)*mx4B);
|
||||
AH1 hitMaxR=(peakC.x-mx4R)*ARcpH1(AH1_(4.0)*mn4R+peakC.y);
|
||||
AH1 hitMaxG=(peakC.x-mx4G)*ARcpH1(AH1_(4.0)*mn4G+peakC.y);
|
||||
AH1 hitMaxB=(peakC.x-mx4B)*ARcpH1(AH1_(4.0)*mn4B+peakC.y);
|
||||
AH1 lobeR=max(-hitMinR,hitMaxR);
|
||||
AH1 lobeG=max(-hitMinG,hitMaxG);
|
||||
AH1 lobeB=max(-hitMinB,hitMaxB);
|
||||
@@ -963,12 +963,12 @@ AF1 sharpness){
|
||||
// Immediate constants for peak range.
|
||||
AH2 peakC=AH2(1.0,-1.0*4.0);
|
||||
// Limiters, these need to be high precision RCPs.
|
||||
AH2 hitMinR=min(mn4R,eR)*ARcpH2(AH2_(4.0)*mx4R);
|
||||
AH2 hitMinG=min(mn4G,eG)*ARcpH2(AH2_(4.0)*mx4G);
|
||||
AH2 hitMinB=min(mn4B,eB)*ARcpH2(AH2_(4.0)*mx4B);
|
||||
AH2 hitMaxR=(peakC.x-max(mx4R,eR))*ARcpH2(AH2_(4.0)*mn4R+peakC.y);
|
||||
AH2 hitMaxG=(peakC.x-max(mx4G,eG))*ARcpH2(AH2_(4.0)*mn4G+peakC.y);
|
||||
AH2 hitMaxB=(peakC.x-max(mx4B,eB))*ARcpH2(AH2_(4.0)*mn4B+peakC.y);
|
||||
AH2 hitMinR=mn4R*ARcpH2(AH2_(4.0)*mx4R);
|
||||
AH2 hitMinG=mn4G*ARcpH2(AH2_(4.0)*mx4G);
|
||||
AH2 hitMinB=mn4B*ARcpH2(AH2_(4.0)*mx4B);
|
||||
AH2 hitMaxR=(peakC.x-mx4R)*ARcpH2(AH2_(4.0)*mn4R+peakC.y);
|
||||
AH2 hitMaxG=(peakC.x-mx4G)*ARcpH2(AH2_(4.0)*mn4G+peakC.y);
|
||||
AH2 hitMaxB=(peakC.x-mx4B)*ARcpH2(AH2_(4.0)*mn4B+peakC.y);
|
||||
AH2 lobeR=max(-hitMinR,hitMaxR);
|
||||
AH2 lobeG=max(-hitMinG,hitMaxG);
|
||||
AH2 lobeB=max(-hitMinB,hitMaxB);
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
#version 300 es
|
||||
#extension GL_OES_EGL_image_external_essl3 : enable
|
||||
|
||||
precision highp float;
|
||||
precision mediump float;
|
||||
|
||||
#include "compat.h"
|
||||
|
||||
in vec2 fragCoord;
|
||||
out vec4 fragColor;
|
||||
|
||||
uniform sampler2D sampler1;
|
||||
uniform sampler2D texture;
|
||||
uniform vec2 uOutRes;
|
||||
uniform uvec4 uConsts[4];
|
||||
|
||||
@@ -20,9 +18,20 @@ uniform uvec4 uConsts[4];
|
||||
|
||||
#define FSR_EASU_F 1
|
||||
|
||||
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));}
|
||||
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));}
|
||||
|
||||
#include "ffx_fsr1.h"
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
#version 300 es
|
||||
precision highp float;
|
||||
precision mediump float;
|
||||
|
||||
#include "compat.h"
|
||||
|
||||
in vec2 fragCoord;
|
||||
out vec4 fragColor;
|
||||
|
||||
uniform sampler2D sampler1;
|
||||
uniform sampler2D texture;
|
||||
uniform uvec4 uConsts;
|
||||
|
||||
#define A_GPU 1
|
||||
@@ -15,7 +15,7 @@ uniform uvec4 uConsts;
|
||||
|
||||
#include "ffx_a.h"
|
||||
|
||||
AF4 FsrRcasLoadF(ASU2 p) { return texelFetch(sampler1, ASU2(p), 0); }
|
||||
AF4 FsrRcasLoadF(ASU2 p) { return texelFetch(texture, 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(sampler1, 0));
|
||||
vec2 inRes = vec2(textureSize(texture, 0));
|
||||
uvec2 point = uvec2(fragCoord * (inRes + 0.5f));
|
||||
|
||||
FsrRcasF(fragColor.r, fragColor.g, fragColor.b, point, uConsts);
|
||||
|
||||
@@ -1,108 +0,0 @@
|
||||
/*
|
||||
_______ _____ __ __ ____ __
|
||||
/ ____(_)___ ___ ____ ___ ____ _ / ___// /_ ____ _____/ /__ _____ / __ \____ ______/ /__
|
||||
/ / / / __ \/ _ \/ __ `__ \/ __ `/ \__ \/ __ \/ __ `/ __ / _ \/ ___/ / /_/ / __ `/ ___/ //_/
|
||||
/ /___/ / / / / __/ / / / / / /_/ / ___/ / / / / /_/ / /_/ / __/ / / ____/ /_/ / /__/ ,<
|
||||
\____/_/_/ /_/\___/_/ /_/ /_/\__,_/ /____/_/ /_/\__,_/\__,_/\___/_/ /_/ \__,_/\___/_/|_|
|
||||
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));
|
||||
}
|
||||
13
client/renderers/EGL/shader/splash_bg.frag
Normal file
13
client/renderers/EGL/shader/splash_bg.frag
Normal file
@@ -0,0 +1,13 @@
|
||||
#version 300 es
|
||||
precision mediump float;
|
||||
|
||||
in vec3 pos;
|
||||
out vec4 color;
|
||||
|
||||
uniform sampler2D sampler1;
|
||||
|
||||
void main()
|
||||
{
|
||||
highp float d = 1.0 - 0.5 * length(pos.xy);
|
||||
color = vec4(0.234375 * d, 0.015625 * d, 0.425781 * d, 1.0);
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user