mirror of
https://github.com/Almamu/linux-wallpaperengine.git
synced 2025-09-14 05:46:48 +08:00
Merge branch 'vaxerski-main'
This commit is contained in:
commit
5016a9d873
24
.github/workflows/cmake.yml
vendored
24
.github/workflows/cmake.yml
vendored
@ -34,3 +34,27 @@ jobs:
|
|||||||
- name: Build
|
- name: Build
|
||||||
# Build your program with the given configuration
|
# Build your program with the given configuration
|
||||||
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}}
|
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}}
|
||||||
|
|
||||||
|
build-wayland:
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
os: [ubuntu-22.04]
|
||||||
|
# The CMake configure and build commands are platform agnostic and should work equally well on Windows or Mac.
|
||||||
|
# You can convert this to a matrix build if you need cross-platform coverage.
|
||||||
|
# See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: sudo apt-get update && sudo apt-get -y install libxrandr-dev libfreeimage-dev libxinerama-dev libxcursor-dev libxi-dev libgl-dev libglew-dev freeglut3-dev libsdl2-dev liblz4-dev libavcodec-dev libavformat-dev libavutil-dev libswscale-dev libxxf86vm-dev libglm-dev libglfw3-dev libmpv-dev mpv libmpv1 libpulse-dev libpulse0 wayland-scanner++ wayland-protocols libwayland-dev libwayland-egl-backend-dev
|
||||||
|
|
||||||
|
- name: Configure CMake
|
||||||
|
# Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make.
|
||||||
|
# See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type
|
||||||
|
run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DENABLE_WAYLAND=True
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
# Build your program with the given configuration
|
||||||
|
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}}
|
||||||
|
8
.gitignore
vendored
8
.gitignore
vendored
@ -1,2 +1,8 @@
|
|||||||
cmake-build-debug*
|
cmake-build-debug*
|
||||||
.idea
|
.idea
|
||||||
|
build/
|
||||||
|
.vscode/
|
||||||
|
|
||||||
|
*-protocol.o
|
||||||
|
*-protocol.c
|
||||||
|
*-protocol.h
|
@ -41,8 +41,55 @@ include_directories(
|
|||||||
${FREEIMAGE_INCLUDE_DIR}
|
${FREEIMAGE_INCLUDE_DIR}
|
||||||
${PULSEAUDIO_INCLUDE_DIR}
|
${PULSEAUDIO_INCLUDE_DIR}
|
||||||
src
|
src
|
||||||
|
${CMAKE_SOURCE_DIR}
|
||||||
include)
|
include)
|
||||||
|
|
||||||
|
if (ENABLE_WAYLAND)
|
||||||
|
message(STATUS "Wayland support is enabled!")
|
||||||
|
|
||||||
|
pkg_check_modules(wayland-cursor wayland-protocols egl wayland-egl)
|
||||||
|
|
||||||
|
find_program(WaylandScanner NAMES wayland-scanner)
|
||||||
|
message(STATUS "Found WaylandScanner at ${WaylandScanner}")
|
||||||
|
execute_process(
|
||||||
|
COMMAND pkg-config --variable=pkgdatadir wayland-protocols
|
||||||
|
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||||
|
OUTPUT_VARIABLE WAYLAND_PROTOCOLS_DIR
|
||||||
|
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||||
|
message(STATUS "Found wayland-protocols at ${WAYLAND_PROTOCOLS_DIR}")
|
||||||
|
|
||||||
|
message(STATUS "Building protocols...")
|
||||||
|
execute_process(
|
||||||
|
COMMAND ${WaylandScanner} client-header ${CMAKE_SOURCE_DIR}/protocols/wlr-layer-shell-unstable-v1.xml wlr-layer-shell-unstable-v1-protocol.h
|
||||||
|
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
|
||||||
|
execute_process(
|
||||||
|
COMMAND ${WaylandScanner} private-code ${CMAKE_SOURCE_DIR}/protocols/wlr-layer-shell-unstable-v1.xml wlr-layer-shell-unstable-v1-protocol.c
|
||||||
|
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
|
||||||
|
execute_process(
|
||||||
|
COMMAND ${WaylandScanner} client-header ${WAYLAND_PROTOCOLS_DIR}/stable/xdg-shell/xdg-shell.xml xdg-shell-protocol.h
|
||||||
|
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
|
||||||
|
execute_process(
|
||||||
|
COMMAND ${WaylandScanner} private-code ${WAYLAND_PROTOCOLS_DIR}/stable/xdg-shell/xdg-shell.xml xdg-shell-protocol.c
|
||||||
|
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
|
||||||
|
|
||||||
|
add_compile_definitions(ENABLE_WAYLAND)
|
||||||
|
set(WAYLAND_SOURCES
|
||||||
|
"src/WallpaperEngine/Render/Drivers/CWaylandOpenGLDriver.h"
|
||||||
|
"src/WallpaperEngine/Render/Drivers/CWaylandOpenGLDriver.cpp"
|
||||||
|
"src/WallpaperEngine/Render/Drivers/Detectors/CWaylandFullScreenDetector.cpp"
|
||||||
|
"src/WallpaperEngine/Render/Drivers/Detectors/CWaylandFullScreenDetector.h"
|
||||||
|
"src/WallpaperEngine/Render/Drivers/Output/CWaylandOutput.cpp"
|
||||||
|
"src/WallpaperEngine/Render/Drivers/Output/CWaylandOutput.h"
|
||||||
|
"src/WallpaperEngine/Render/Drivers/Output/CWaylandOutputViewport.cpp"
|
||||||
|
"src/WallpaperEngine/Render/Drivers/Output/CWaylandOutputViewport.h"
|
||||||
|
"src/WallpaperEngine/Input/Drivers/CWaylandMouseInput.cpp"
|
||||||
|
"src/WallpaperEngine/Input/Drivers/CWaylandMouseInput.h"
|
||||||
|
"xdg-shell-protocol.c"
|
||||||
|
"wlr-layer-shell-unstable-v1-protocol.c")
|
||||||
|
else()
|
||||||
|
set(WAYLAND_SOURCES "")
|
||||||
|
endif()
|
||||||
|
|
||||||
add_executable(
|
add_executable(
|
||||||
linux-wallpaperengine
|
linux-wallpaperengine
|
||||||
main.cpp
|
main.cpp
|
||||||
@ -105,6 +152,8 @@ add_executable(
|
|||||||
src/WallpaperEngine/Input/CInputContext.h
|
src/WallpaperEngine/Input/CInputContext.h
|
||||||
src/WallpaperEngine/Input/CMouseInput.cpp
|
src/WallpaperEngine/Input/CMouseInput.cpp
|
||||||
src/WallpaperEngine/Input/CMouseInput.h
|
src/WallpaperEngine/Input/CMouseInput.h
|
||||||
|
src/WallpaperEngine/Input/Drivers/CGLFWMouseInput.cpp
|
||||||
|
src/WallpaperEngine/Input/Drivers/CGLFWMouseInput.h
|
||||||
|
|
||||||
src/WallpaperEngine/Render/Shaders/Variables/CShaderVariable.h
|
src/WallpaperEngine/Render/Shaders/Variables/CShaderVariable.h
|
||||||
src/WallpaperEngine/Render/Shaders/Variables/CShaderVariable.cpp
|
src/WallpaperEngine/Render/Shaders/Variables/CShaderVariable.cpp
|
||||||
@ -136,6 +185,10 @@ add_executable(
|
|||||||
src/WallpaperEngine/Render/Drivers/Output/CX11Output.h
|
src/WallpaperEngine/Render/Drivers/Output/CX11Output.h
|
||||||
src/WallpaperEngine/Render/Drivers/Output/CGLFWWindowOutput.cpp
|
src/WallpaperEngine/Render/Drivers/Output/CGLFWWindowOutput.cpp
|
||||||
src/WallpaperEngine/Render/Drivers/Output/CGLFWWindowOutput.h
|
src/WallpaperEngine/Render/Drivers/Output/CGLFWWindowOutput.h
|
||||||
|
src/WallpaperEngine/Render/Drivers/Output/COutputViewport.cpp
|
||||||
|
src/WallpaperEngine/Render/Drivers/Output/COutputViewport.h
|
||||||
|
src/WallpaperEngine/Render/Drivers/Output/CX11OutputViewport.cpp
|
||||||
|
src/WallpaperEngine/Render/Drivers/Output/CX11OutputViewport.h
|
||||||
src/WallpaperEngine/Render/Drivers/CX11OpenGLDriver.h
|
src/WallpaperEngine/Render/Drivers/CX11OpenGLDriver.h
|
||||||
src/WallpaperEngine/Render/Drivers/CX11OpenGLDriver.cpp
|
src/WallpaperEngine/Render/Drivers/CX11OpenGLDriver.cpp
|
||||||
src/WallpaperEngine/Render/Drivers/CVideoDriver.h
|
src/WallpaperEngine/Render/Drivers/CVideoDriver.h
|
||||||
@ -268,6 +321,8 @@ add_executable(
|
|||||||
|
|
||||||
src/WallpaperEngine/Core/Objects/Images/Materials/CPass.cpp
|
src/WallpaperEngine/Core/Objects/Images/Materials/CPass.cpp
|
||||||
src/WallpaperEngine/Core/Objects/Images/Materials/CPass.h
|
src/WallpaperEngine/Core/Objects/Images/Materials/CPass.h
|
||||||
|
|
||||||
|
${WAYLAND_SOURCES}
|
||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries(linux-wallpaperengine
|
target_link_libraries(linux-wallpaperengine
|
||||||
@ -286,6 +341,14 @@ target_link_libraries(linux-wallpaperengine
|
|||||||
${PULSEAUDIO_LIBRARY}
|
${PULSEAUDIO_LIBRARY}
|
||||||
glfw)
|
glfw)
|
||||||
|
|
||||||
|
if (ENABLE_WAYLAND)
|
||||||
|
target_link_libraries(linux-wallpaperengine pthread
|
||||||
|
wayland-cursor
|
||||||
|
wayland-client
|
||||||
|
wayland-egl
|
||||||
|
${OPENGL_egl_LIBRARY})
|
||||||
|
endif()
|
||||||
|
|
||||||
file(CREATE_LINK linux-wallpaperengine wallengine SYMBOLIC)
|
file(CREATE_LINK linux-wallpaperengine wallengine SYMBOLIC)
|
||||||
|
|
||||||
set(CMAKE_REQUIRED_LIBRARIES ${X11_LIBRARIES})
|
set(CMAKE_REQUIRED_LIBRARIES ${X11_LIBRARIES})
|
||||||
|
285
protocols/wlr-layer-shell-unstable-v1.xml
Normal file
285
protocols/wlr-layer-shell-unstable-v1.xml
Normal file
@ -0,0 +1,285 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<protocol name="wlr_layer_shell_v1_unstable_v1">
|
||||||
|
<copyright>
|
||||||
|
Copyright © 2017 Drew DeVault
|
||||||
|
|
||||||
|
Permission to use, copy, modify, distribute, and sell this
|
||||||
|
software and its documentation for any purpose is hereby granted
|
||||||
|
without fee, provided that the above copyright notice appear in
|
||||||
|
all copies and that both that copyright notice and this permission
|
||||||
|
notice appear in supporting documentation, and that the name of
|
||||||
|
the copyright holders not be used in advertising or publicity
|
||||||
|
pertaining to distribution of the software without specific,
|
||||||
|
written prior permission. The copyright holders make no
|
||||||
|
representations about the suitability of this software for any
|
||||||
|
purpose. It is provided "as is" without express or implied
|
||||||
|
warranty.
|
||||||
|
|
||||||
|
THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
|
||||||
|
SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
|
FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
|
SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
|
||||||
|
AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
|
||||||
|
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||||||
|
THIS SOFTWARE.
|
||||||
|
</copyright>
|
||||||
|
|
||||||
|
<interface name="zwlr_layer_shell_v1" version="1">
|
||||||
|
<description summary="create surfaces that are layers of the desktop">
|
||||||
|
Clients can use this interface to assign the surface_layer role to
|
||||||
|
wl_surfaces. Such surfaces are assigned to a "layer" of the output and
|
||||||
|
rendered with a defined z-depth respective to each other. They may also be
|
||||||
|
anchored to the edges and corners of a screen and specify input handling
|
||||||
|
semantics. This interface should be suitable for the implementation of
|
||||||
|
many desktop shell components, and a broad number of other applications
|
||||||
|
that interact with the desktop.
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<request name="get_layer_surface">
|
||||||
|
<description summary="create a layer_surface from a surface">
|
||||||
|
Create a layer surface for an existing surface. This assigns the role of
|
||||||
|
layer_surface, or raises a protocol error if another role is already
|
||||||
|
assigned.
|
||||||
|
|
||||||
|
Creating a layer surface from a wl_surface which has a buffer attached
|
||||||
|
or committed is a client error, and any attempts by a client to attach
|
||||||
|
or manipulate a buffer prior to the first layer_surface.configure call
|
||||||
|
must also be treated as errors.
|
||||||
|
|
||||||
|
You may pass NULL for output to allow the compositor to decide which
|
||||||
|
output to use. Generally this will be the one that the user most
|
||||||
|
recently interacted with.
|
||||||
|
|
||||||
|
Clients can specify a namespace that defines the purpose of the layer
|
||||||
|
surface.
|
||||||
|
</description>
|
||||||
|
<arg name="id" type="new_id" interface="zwlr_layer_surface_v1"/>
|
||||||
|
<arg name="surface" type="object" interface="wl_surface"/>
|
||||||
|
<arg name="output" type="object" interface="wl_output" allow-null="true"/>
|
||||||
|
<arg name="layer" type="uint" enum="layer" summary="layer to add this surface to"/>
|
||||||
|
<arg name="namespace" type="string" summary="namespace for the layer surface"/>
|
||||||
|
</request>
|
||||||
|
|
||||||
|
<enum name="error">
|
||||||
|
<entry name="role" value="0" summary="wl_surface has another role"/>
|
||||||
|
<entry name="invalid_layer" value="1" summary="layer value is invalid"/>
|
||||||
|
<entry name="already_constructed" value="2" summary="wl_surface has a buffer attached or committed"/>
|
||||||
|
</enum>
|
||||||
|
|
||||||
|
<enum name="layer">
|
||||||
|
<description summary="available layers for surfaces">
|
||||||
|
These values indicate which layers a surface can be rendered in. They
|
||||||
|
are ordered by z depth, bottom-most first. Traditional shell surfaces
|
||||||
|
will typically be rendered between the bottom and top layers.
|
||||||
|
Fullscreen shell surfaces are typically rendered at the top layer.
|
||||||
|
Multiple surfaces can share a single layer, and ordering within a
|
||||||
|
single layer is undefined.
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<entry name="background" value="0"/>
|
||||||
|
<entry name="bottom" value="1"/>
|
||||||
|
<entry name="top" value="2"/>
|
||||||
|
<entry name="overlay" value="3"/>
|
||||||
|
</enum>
|
||||||
|
</interface>
|
||||||
|
|
||||||
|
<interface name="zwlr_layer_surface_v1" version="1">
|
||||||
|
<description summary="layer metadata interface">
|
||||||
|
An interface that may be implemented by a wl_surface, for surfaces that
|
||||||
|
are designed to be rendered as a layer of a stacked desktop-like
|
||||||
|
environment.
|
||||||
|
|
||||||
|
Layer surface state (size, anchor, exclusive zone, margin, interactivity)
|
||||||
|
is double-buffered, and will be applied at the time wl_surface.commit of
|
||||||
|
the corresponding wl_surface is called.
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<request name="set_size">
|
||||||
|
<description summary="sets the size of the surface">
|
||||||
|
Sets the size of the surface in surface-local coordinates. The
|
||||||
|
compositor will display the surface centered with respect to its
|
||||||
|
anchors.
|
||||||
|
|
||||||
|
If you pass 0 for either value, the compositor will assign it and
|
||||||
|
inform you of the assignment in the configure event. You must set your
|
||||||
|
anchor to opposite edges in the dimensions you omit; not doing so is a
|
||||||
|
protocol error. Both values are 0 by default.
|
||||||
|
|
||||||
|
Size is double-buffered, see wl_surface.commit.
|
||||||
|
</description>
|
||||||
|
<arg name="width" type="uint"/>
|
||||||
|
<arg name="height" type="uint"/>
|
||||||
|
</request>
|
||||||
|
|
||||||
|
<request name="set_anchor">
|
||||||
|
<description summary="configures the anchor point of the surface">
|
||||||
|
Requests that the compositor anchor the surface to the specified edges
|
||||||
|
and corners. If two orthoginal edges are specified (e.g. 'top' and
|
||||||
|
'left'), then the anchor point will be the intersection of the edges
|
||||||
|
(e.g. the top left corner of the output); otherwise the anchor point
|
||||||
|
will be centered on that edge, or in the center if none is specified.
|
||||||
|
|
||||||
|
Anchor is double-buffered, see wl_surface.commit.
|
||||||
|
</description>
|
||||||
|
<arg name="anchor" type="uint" enum="anchor"/>
|
||||||
|
</request>
|
||||||
|
|
||||||
|
<request name="set_exclusive_zone">
|
||||||
|
<description summary="configures the exclusive geometry of this surface">
|
||||||
|
Requests that the compositor avoids occluding an area of the surface
|
||||||
|
with other surfaces. The compositor's use of this information is
|
||||||
|
implementation-dependent - do not assume that this region will not
|
||||||
|
actually be occluded.
|
||||||
|
|
||||||
|
A positive value is only meaningful if the surface is anchored to an
|
||||||
|
edge, rather than a corner. The zone is the number of surface-local
|
||||||
|
coordinates from the edge that are considered exclusive.
|
||||||
|
|
||||||
|
Surfaces that do not wish to have an exclusive zone may instead specify
|
||||||
|
how they should interact with surfaces that do. If set to zero, the
|
||||||
|
surface indicates that it would like to be moved to avoid occluding
|
||||||
|
surfaces with a positive excluzive zone. If set to -1, the surface
|
||||||
|
indicates that it would not like to be moved to accommodate for other
|
||||||
|
surfaces, and the compositor should extend it all the way to the edges
|
||||||
|
it is anchored to.
|
||||||
|
|
||||||
|
For example, a panel might set its exclusive zone to 10, so that
|
||||||
|
maximized shell surfaces are not shown on top of it. A notification
|
||||||
|
might set its exclusive zone to 0, so that it is moved to avoid
|
||||||
|
occluding the panel, but shell surfaces are shown underneath it. A
|
||||||
|
wallpaper or lock screen might set their exclusive zone to -1, so that
|
||||||
|
they stretch below or over the panel.
|
||||||
|
|
||||||
|
The default value is 0.
|
||||||
|
|
||||||
|
Exclusive zone is double-buffered, see wl_surface.commit.
|
||||||
|
</description>
|
||||||
|
<arg name="zone" type="int"/>
|
||||||
|
</request>
|
||||||
|
|
||||||
|
<request name="set_margin">
|
||||||
|
<description summary="sets a margin from the anchor point">
|
||||||
|
Requests that the surface be placed some distance away from the anchor
|
||||||
|
point on the output, in surface-local coordinates. Setting this value
|
||||||
|
for edges you are not anchored to has no effect.
|
||||||
|
|
||||||
|
The exclusive zone includes the margin.
|
||||||
|
|
||||||
|
Margin is double-buffered, see wl_surface.commit.
|
||||||
|
</description>
|
||||||
|
<arg name="top" type="int"/>
|
||||||
|
<arg name="right" type="int"/>
|
||||||
|
<arg name="bottom" type="int"/>
|
||||||
|
<arg name="left" type="int"/>
|
||||||
|
</request>
|
||||||
|
|
||||||
|
<request name="set_keyboard_interactivity">
|
||||||
|
<description summary="requests keyboard events">
|
||||||
|
Set to 1 to request that the seat send keyboard events to this layer
|
||||||
|
surface. For layers below the shell surface layer, the seat will use
|
||||||
|
normal focus semantics. For layers above the shell surface layers, the
|
||||||
|
seat will always give exclusive keyboard focus to the top-most layer
|
||||||
|
which has keyboard interactivity set to true.
|
||||||
|
|
||||||
|
Layer surfaces receive pointer, touch, and tablet events normally. If
|
||||||
|
you do not want to receive them, set the input region on your surface
|
||||||
|
to an empty region.
|
||||||
|
|
||||||
|
Events is double-buffered, see wl_surface.commit.
|
||||||
|
</description>
|
||||||
|
<arg name="keyboard_interactivity" type="uint"/>
|
||||||
|
</request>
|
||||||
|
|
||||||
|
<request name="get_popup">
|
||||||
|
<description summary="assign this layer_surface as an xdg_popup parent">
|
||||||
|
This assigns an xdg_popup's parent to this layer_surface. This popup
|
||||||
|
should have been created via xdg_surface::get_popup with the parent set
|
||||||
|
to NULL, and this request must be invoked before committing the popup's
|
||||||
|
initial state.
|
||||||
|
|
||||||
|
See the documentation of xdg_popup for more details about what an
|
||||||
|
xdg_popup is and how it is used.
|
||||||
|
</description>
|
||||||
|
<arg name="popup" type="object" interface="xdg_popup"/>
|
||||||
|
</request>
|
||||||
|
|
||||||
|
<request name="ack_configure">
|
||||||
|
<description summary="ack a configure event">
|
||||||
|
When a configure event is received, if a client commits the
|
||||||
|
surface in response to the configure event, then the client
|
||||||
|
must make an ack_configure request sometime before the commit
|
||||||
|
request, passing along the serial of the configure event.
|
||||||
|
|
||||||
|
If the client receives multiple configure events before it
|
||||||
|
can respond to one, it only has to ack the last configure event.
|
||||||
|
|
||||||
|
A client is not required to commit immediately after sending
|
||||||
|
an ack_configure request - it may even ack_configure several times
|
||||||
|
before its next surface commit.
|
||||||
|
|
||||||
|
A client may send multiple ack_configure requests before committing, but
|
||||||
|
only the last request sent before a commit indicates which configure
|
||||||
|
event the client really is responding to.
|
||||||
|
</description>
|
||||||
|
<arg name="serial" type="uint" summary="the serial from the configure event"/>
|
||||||
|
</request>
|
||||||
|
|
||||||
|
<request name="destroy" type="destructor">
|
||||||
|
<description summary="destroy the layer_surface">
|
||||||
|
This request destroys the layer surface.
|
||||||
|
</description>
|
||||||
|
</request>
|
||||||
|
|
||||||
|
<event name="configure">
|
||||||
|
<description summary="suggest a surface change">
|
||||||
|
The configure event asks the client to resize its surface.
|
||||||
|
|
||||||
|
Clients should arrange their surface for the new states, and then send
|
||||||
|
an ack_configure request with the serial sent in this configure event at
|
||||||
|
some point before committing the new surface.
|
||||||
|
|
||||||
|
The client is free to dismiss all but the last configure event it
|
||||||
|
received.
|
||||||
|
|
||||||
|
The width and height arguments specify the size of the window in
|
||||||
|
surface-local coordinates.
|
||||||
|
|
||||||
|
The size is a hint, in the sense that the client is free to ignore it if
|
||||||
|
it doesn't resize, pick a smaller size (to satisfy aspect ratio or
|
||||||
|
resize in steps of NxM pixels). If the client picks a smaller size and
|
||||||
|
is anchored to two opposite anchors (e.g. 'top' and 'bottom'), the
|
||||||
|
surface will be centered on this axis.
|
||||||
|
|
||||||
|
If the width or height arguments are zero, it means the client should
|
||||||
|
decide its own window dimension.
|
||||||
|
</description>
|
||||||
|
<arg name="serial" type="uint"/>
|
||||||
|
<arg name="width" type="uint"/>
|
||||||
|
<arg name="height" type="uint"/>
|
||||||
|
</event>
|
||||||
|
|
||||||
|
<event name="closed">
|
||||||
|
<description summary="surface should be closed">
|
||||||
|
The closed event is sent by the compositor when the surface will no
|
||||||
|
longer be shown. The output may have been destroyed or the user may
|
||||||
|
have asked for it to be removed. Further changes to the surface will be
|
||||||
|
ignored. The client should destroy the resource after receiving this
|
||||||
|
event, and create a new surface if they so choose.
|
||||||
|
</description>
|
||||||
|
</event>
|
||||||
|
|
||||||
|
<enum name="error">
|
||||||
|
<entry name="invalid_surface_state" value="0" summary="provided surface state is invalid"/>
|
||||||
|
<entry name="invalid_size" value="1" summary="size is invalid"/>
|
||||||
|
<entry name="invalid_anchor" value="2" summary="anchor bitfield is invalid"/>
|
||||||
|
</enum>
|
||||||
|
|
||||||
|
<enum name="anchor" bitfield="true">
|
||||||
|
<entry name="top" value="1" summary="the top edge of the anchor rectangle"/>
|
||||||
|
<entry name="bottom" value="2" summary="the bottom edge of the anchor rectangle"/>
|
||||||
|
<entry name="left" value="4" summary="the left edge of the anchor rectangle"/>
|
||||||
|
<entry name="right" value="8" summary="the right edge of the anchor rectangle"/>
|
||||||
|
</enum>
|
||||||
|
</interface>
|
||||||
|
</protocol>
|
4
src/External/Android/fft.cpp
vendored
4
src/External/Android/fft.cpp
vendored
@ -26,8 +26,8 @@ namespace External::Android
|
|||||||
* half of the twiddle factors are stored. Although there are still ways to make
|
* half of the twiddle factors are stored. Although there are still ways to make
|
||||||
* it even faster or smaller, it costs too much on one of the aspects.
|
* it even faster or smaller, it costs too much on one of the aspects.
|
||||||
*/
|
*/
|
||||||
#include <stdio.h>
|
#include <cstdio>
|
||||||
#include <stdint.h>
|
#include <cstdint>
|
||||||
#ifdef __arm__
|
#ifdef __arm__
|
||||||
#include <machine/cpu-features.h>
|
#include <machine/cpu-features.h>
|
||||||
#endif
|
#endif
|
||||||
|
@ -12,22 +12,22 @@
|
|||||||
using namespace WallpaperEngine::Application;
|
using namespace WallpaperEngine::Application;
|
||||||
|
|
||||||
struct option long_options[] = {
|
struct option long_options[] = {
|
||||||
{ "screen-root", required_argument, nullptr, 'r' },
|
{ "screen-root", required_argument, nullptr, 'r' },
|
||||||
{ "bg", required_argument, nullptr, 'b' },
|
{ "bg", required_argument, nullptr, 'b' },
|
||||||
{ "window", required_argument, nullptr, 'w' },
|
{ "window", required_argument, nullptr, 'w' },
|
||||||
{ "pkg", required_argument, nullptr, 'p' },
|
{ "pkg", required_argument, nullptr, 'p' },
|
||||||
{ "dir", required_argument, nullptr, 'd' },
|
{ "dir", required_argument, nullptr, 'd' },
|
||||||
{ "silent", no_argument, nullptr, 's' },
|
{ "silent", no_argument, nullptr, 's' },
|
||||||
{ "volume", required_argument, nullptr, 'v' },
|
{ "volume", required_argument, nullptr, 'v' },
|
||||||
{ "help", no_argument, nullptr, 'h' },
|
{ "help", no_argument, nullptr, 'h' },
|
||||||
{ "fps", required_argument, nullptr, 'f' },
|
{ "fps", required_argument, nullptr, 'f' },
|
||||||
{ "assets-dir", required_argument, nullptr, 'a' },
|
{ "assets-dir", required_argument, nullptr, 'a' },
|
||||||
{ "screenshot", required_argument, nullptr, 'c' },
|
{ "screenshot", required_argument, nullptr, 'c' },
|
||||||
{ "list-properties", no_argument, nullptr, 'l' },
|
{ "list-properties", no_argument, nullptr, 'l' },
|
||||||
{ "set-property", required_argument, nullptr, 'o' },
|
{ "set-property", required_argument, nullptr, 'o' },
|
||||||
{ "noautomute", no_argument, nullptr, 'm' },
|
{ "noautomute", no_argument, nullptr, 'm' },
|
||||||
{ "no-fullscreen-pause", no_argument,nullptr, 'n' },
|
{ "no-fullscreen-pause", no_argument, nullptr, 'n' },
|
||||||
{ nullptr, 0, nullptr, 0 }
|
{ nullptr, 0, nullptr, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
std::string stringPathFixes (const std::string& s)
|
std::string stringPathFixes (const std::string& s)
|
||||||
@ -124,13 +124,13 @@ CApplicationContext::CApplicationContext (int argc, char* argv[])
|
|||||||
if (this->settings.render.mode == EXPLICIT_WINDOW)
|
if (this->settings.render.mode == EXPLICIT_WINDOW)
|
||||||
sLog.exception ("Cannot run in both background and window mode");
|
sLog.exception ("Cannot run in both background and window mode");
|
||||||
|
|
||||||
this->settings.render.mode = X11_BACKGROUND;
|
this->settings.render.mode = DESKTOP_BACKGROUND;
|
||||||
lastScreen = optarg;
|
lastScreen = optarg;
|
||||||
this->settings.general.screenBackgrounds[lastScreen] = "";
|
this->settings.general.screenBackgrounds[lastScreen] = "";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'w':
|
case 'w':
|
||||||
if (this->settings.render.mode == X11_BACKGROUND)
|
if (this->settings.render.mode == DESKTOP_BACKGROUND)
|
||||||
sLog.exception ("Cannot run in both background and window mode");
|
sLog.exception ("Cannot run in both background and window mode");
|
||||||
|
|
||||||
if (optarg != nullptr)
|
if (optarg != nullptr)
|
||||||
|
@ -25,8 +25,8 @@ namespace WallpaperEngine::Application
|
|||||||
{
|
{
|
||||||
/** Default window mode */
|
/** Default window mode */
|
||||||
NORMAL_WINDOW = 0,
|
NORMAL_WINDOW = 0,
|
||||||
/** Draw to X11 background */
|
/** Draw to the window server desktop */
|
||||||
X11_BACKGROUND = 1,
|
DESKTOP_BACKGROUND = 1,
|
||||||
/** Explicit window mode with specified geometry */
|
/** Explicit window mode with specified geometry */
|
||||||
EXPLICIT_WINDOW = 2,
|
EXPLICIT_WINDOW = 2,
|
||||||
};
|
};
|
||||||
|
@ -3,17 +3,15 @@
|
|||||||
#include "Steam/FileSystem/FileSystem.h"
|
#include "Steam/FileSystem/FileSystem.h"
|
||||||
#include "WallpaperEngine/Assets/CDirectory.h"
|
#include "WallpaperEngine/Assets/CDirectory.h"
|
||||||
#include "WallpaperEngine/Assets/CVirtualContainer.h"
|
#include "WallpaperEngine/Assets/CVirtualContainer.h"
|
||||||
#include "WallpaperEngine/Audio/Drivers/CSDLAudioDriver.h"
|
|
||||||
#include "WallpaperEngine/Core/CVideo.h"
|
#include "WallpaperEngine/Core/CVideo.h"
|
||||||
#include "WallpaperEngine/Logging/CLog.h"
|
#include "WallpaperEngine/Logging/CLog.h"
|
||||||
#include "WallpaperEngine/Render/CRenderContext.h"
|
#include "WallpaperEngine/Render/CRenderContext.h"
|
||||||
#include "WallpaperEngine/Render/Drivers/Output/CGLFWWindowOutput.h"
|
|
||||||
#include "WallpaperEngine/Render/Drivers/Output/CX11Output.h"
|
|
||||||
#include "WallpaperEngine/Application/CApplicationState.h"
|
#include "WallpaperEngine/Application/CApplicationState.h"
|
||||||
#include "WallpaperEngine/Render/Drivers/Detectors/CX11FullScreenDetector.h"
|
|
||||||
#include "WallpaperEngine/Audio/Drivers/Detectors/CPulseAudioPlayingDetector.h"
|
#include "WallpaperEngine/Audio/Drivers/Detectors/CPulseAudioPlayingDetector.h"
|
||||||
|
#include "WallpaperEngine/Input/Drivers/CGLFWMouseInput.h"
|
||||||
|
|
||||||
#include <unistd.h>
|
#include "WallpaperEngine/Input/Drivers/CWaylandMouseInput.h"
|
||||||
|
#include "WallpaperEngine/Render/Drivers/CWaylandOpenGLDriver.h"
|
||||||
|
|
||||||
float g_Time;
|
float g_Time;
|
||||||
float g_TimeLast;
|
float g_TimeLast;
|
||||||
@ -29,6 +27,15 @@ namespace WallpaperEngine::Application
|
|||||||
this->setupProperties ();
|
this->setupProperties ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CWallpaperApplication::~CWallpaperApplication ()
|
||||||
|
{
|
||||||
|
delete context;
|
||||||
|
delete videoDriver;
|
||||||
|
delete audioContext;
|
||||||
|
delete audioDriver;
|
||||||
|
delete inputContext;
|
||||||
|
}
|
||||||
|
|
||||||
void CWallpaperApplication::setupContainer (CCombinedContainer& container, const std::string& bg) const
|
void CWallpaperApplication::setupContainer (CCombinedContainer& container, const std::string& bg) const
|
||||||
{
|
{
|
||||||
std::filesystem::path basepath = bg;
|
std::filesystem::path basepath = bg;
|
||||||
@ -227,126 +234,128 @@ namespace WallpaperEngine::Application
|
|||||||
)
|
)
|
||||||
{
|
{
|
||||||
// this should be getting called at the end of the frame, so the right thing should be bound already
|
// this should be getting called at the end of the frame, so the right thing should be bound already
|
||||||
|
int width = context.getOutput ().getFullWidth ();
|
||||||
int width = context.getOutput ()->getFullWidth ();
|
int height = context.getOutput ().getFullHeight ();
|
||||||
int height = context.getOutput ()->getFullHeight ();
|
|
||||||
|
|
||||||
// make room for storing the pixel data
|
|
||||||
uint8_t* buffer = new uint8_t[width * height * sizeof (uint8_t) * 3];
|
|
||||||
uint8_t* pixel = buffer;
|
|
||||||
|
|
||||||
// read the image into the buffer
|
|
||||||
glReadPixels (0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, buffer);
|
|
||||||
|
|
||||||
// build the output file with FreeImage
|
// build the output file with FreeImage
|
||||||
FIBITMAP* bitmap = FreeImage_Allocate (width, height, 24);
|
static FIBITMAP* bitmap = FreeImage_Allocate (width, height, 24);
|
||||||
RGBQUAD color;
|
RGBQUAD color;
|
||||||
|
int xoffset = 0;
|
||||||
|
|
||||||
// now get access to the pixels
|
for (const auto& viewport : context.getOutput ().getViewports ())
|
||||||
for (int y = height; y > 0; y--)
|
|
||||||
{
|
{
|
||||||
for (int x = 0; x < width; x++)
|
// activate opengl context so we can read from the framebuffer
|
||||||
{
|
viewport.second->makeCurrent ();
|
||||||
color.rgbRed = *pixel++;
|
// make room for storing the pixel of this viewport
|
||||||
color.rgbGreen = *pixel++;
|
uint8_t* buffer = new uint8_t[viewport.second->viewport.z * viewport.second->viewport.w * sizeof (uint8_t) * 3];
|
||||||
color.rgbBlue = *pixel++;
|
uint8_t* pixel = buffer;
|
||||||
|
|
||||||
// set the pixel in the destination
|
// read the viewport data into the pixel buffer
|
||||||
FreeImage_SetPixelColor (bitmap, x, y, &color);
|
glReadPixels (
|
||||||
|
viewport.second->viewport.x, viewport.second->viewport.y,
|
||||||
|
viewport.second->viewport.z, viewport.second->viewport.w,
|
||||||
|
GL_RGB, GL_UNSIGNED_BYTE, buffer
|
||||||
|
);
|
||||||
|
|
||||||
|
// now get access to the pixels
|
||||||
|
for (int y = viewport.second->viewport.w; y > 0; y--)
|
||||||
|
{
|
||||||
|
for (int x = 0; x < viewport.second->viewport.z; x++)
|
||||||
|
{
|
||||||
|
color.rgbRed = *pixel++;
|
||||||
|
color.rgbGreen = *pixel++;
|
||||||
|
color.rgbBlue = *pixel++;
|
||||||
|
|
||||||
|
// set the pixel in the destination
|
||||||
|
FreeImage_SetPixelColor (bitmap, x + xoffset, context.getOutput ().renderVFlip() ? (viewport.second->viewport.w - y) : y, &color);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (viewport.second->single)
|
||||||
|
xoffset += viewport.second->viewport.z;
|
||||||
|
|
||||||
|
// free the buffer allocated for the viewport
|
||||||
|
delete[] buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
// finally save the file
|
// finally save the file
|
||||||
FreeImage_Save (format, bitmap, filename.c_str (), 0);
|
FreeImage_Save (format, bitmap, filename.c_str (), 0);
|
||||||
|
|
||||||
// free all the used memory
|
|
||||||
delete[] buffer;
|
|
||||||
|
|
||||||
FreeImage_Unload (bitmap);
|
FreeImage_Unload (bitmap);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CWallpaperApplication::show ()
|
void CWallpaperApplication::show ()
|
||||||
{
|
{
|
||||||
// initialize OpenGL driver
|
#ifdef ENABLE_WAYLAND
|
||||||
WallpaperEngine::Render::Drivers::CX11OpenGLDriver videoDriver ("wallpaperengine", this->m_context);
|
const bool WAYLAND_DISPLAY = getenv ("WAYLAND_DISPLAY");
|
||||||
// initialize the input subsystem
|
|
||||||
WallpaperEngine::Input::CInputContext inputContext (videoDriver);
|
// setup the right video driver based on the environment and the startup mode requested
|
||||||
// output requested
|
if (WAYLAND_DISPLAY && this->m_context.settings.render.mode == CApplicationContext::DESKTOP_BACKGROUND)
|
||||||
WallpaperEngine::Render::Drivers::Output::COutput* output;
|
{
|
||||||
// fullscreen detector is common for the different render modes
|
auto waylandDriver = new WallpaperEngine::Render::Drivers::CWaylandOpenGLDriver (this->m_context, *this);
|
||||||
WallpaperEngine::Render::Drivers::Detectors::CX11FullScreenDetector fullscreenDetector (this->m_context, videoDriver);
|
inputContext = new WallpaperEngine::Input::CInputContext (new WallpaperEngine::Input::Drivers::CWaylandMouseInput (waylandDriver));
|
||||||
|
|
||||||
|
videoDriver = waylandDriver;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
auto x11Driver = new WallpaperEngine::Render::Drivers::CX11OpenGLDriver ("wallpaperengine", this->m_context, *this);
|
||||||
|
// no wayland detected, try the old X11 method
|
||||||
|
inputContext = new WallpaperEngine::Input::CInputContext (new WallpaperEngine::Input::Drivers::CGLFWMouseInput (x11Driver));
|
||||||
|
|
||||||
|
videoDriver = x11Driver;
|
||||||
|
}
|
||||||
|
|
||||||
// stereo mix recorder for audio processing
|
// stereo mix recorder for audio processing
|
||||||
WallpaperEngine::Audio::Drivers::Recorders::CPulseAudioPlaybackRecorder audioRecorder;
|
WallpaperEngine::Audio::Drivers::Recorders::CPulseAudioPlaybackRecorder audioRecorder;
|
||||||
// audio playing detector
|
// audio playing detector
|
||||||
WallpaperEngine::Audio::Drivers::Detectors::CPulseAudioPlayingDetector audioDetector (this->m_context, fullscreenDetector);
|
WallpaperEngine::Audio::Drivers::Detectors::CPulseAudioPlayingDetector audioDetector (this->m_context, videoDriver->getFullscreenDetector ());
|
||||||
// initialize sdl audio driver
|
// initialize sdl audio driver
|
||||||
WallpaperEngine::Audio::Drivers::CSDLAudioDriver audioDriver (this->m_context, audioDetector, audioRecorder);
|
audioDriver = new WallpaperEngine::Audio::Drivers::CSDLAudioDriver (this->m_context, audioDetector, audioRecorder);
|
||||||
// initialize audio context
|
// initialize audio context
|
||||||
WallpaperEngine::Audio::CAudioContext audioContext (audioDriver);
|
audioContext = new WallpaperEngine::Audio::CAudioContext (*audioDriver);
|
||||||
|
|
||||||
// initialize the requested output
|
|
||||||
switch (this->m_context.settings.render.mode)
|
|
||||||
{
|
|
||||||
case CApplicationContext::EXPLICIT_WINDOW:
|
|
||||||
case CApplicationContext::NORMAL_WINDOW:
|
|
||||||
output = new WallpaperEngine::Render::Drivers::Output::CGLFWWindowOutput (this->m_context, videoDriver, fullscreenDetector);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CApplicationContext::X11_BACKGROUND:
|
|
||||||
output = new WallpaperEngine::Render::Drivers::Output::CX11Output (this->m_context, videoDriver, fullscreenDetector);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// initialize render context
|
// initialize render context
|
||||||
WallpaperEngine::Render::CRenderContext context (output, videoDriver, inputContext, *this);
|
context = new WallpaperEngine::Render::CRenderContext (*videoDriver, *inputContext, *this);
|
||||||
|
|
||||||
// set all the specific wallpapers required
|
// set all the specific wallpapers required
|
||||||
for (const auto& it : this->m_backgrounds)
|
for (const auto& it : this->m_backgrounds)
|
||||||
context.setWallpaper (
|
context->setWallpaper (
|
||||||
it.first,
|
it.first,
|
||||||
WallpaperEngine::Render::CWallpaper::fromWallpaper (it.second->getWallpaper (), context, audioContext)
|
WallpaperEngine::Render::CWallpaper::fromWallpaper (it.second->getWallpaper (), *context, *audioContext)
|
||||||
);
|
);
|
||||||
|
|
||||||
// set the default rendering wallpaper if available
|
// set the default rendering wallpaper if available
|
||||||
if (this->m_defaultBackground != nullptr)
|
if (this->m_defaultBackground != nullptr)
|
||||||
context.setDefaultWallpaper (WallpaperEngine::Render::CWallpaper::fromWallpaper (
|
context->setDefaultWallpaper (WallpaperEngine::Render::CWallpaper::fromWallpaper (
|
||||||
this->m_defaultBackground->getWallpaper (), context, audioContext
|
this->m_defaultBackground->getWallpaper (), *context, *audioContext
|
||||||
));
|
));
|
||||||
|
|
||||||
float startTime, endTime, minimumTime = 1.0f / this->m_context.settings.render.maximumFPS;
|
static time_t seconds;
|
||||||
time_t seconds;
|
static struct tm* timeinfo;
|
||||||
struct tm* timeinfo;
|
|
||||||
|
|
||||||
while (!videoDriver.closeRequested () && this->m_context.state.general.keepRunning)
|
while (this->m_context.state.general.keepRunning && !videoDriver->closeRequested ())
|
||||||
{
|
{
|
||||||
// update g_Daytime
|
// update g_Daytime
|
||||||
time (&seconds);
|
time (&seconds);
|
||||||
timeinfo = localtime(&seconds);
|
timeinfo = localtime(&seconds);
|
||||||
g_Daytime = ((timeinfo->tm_hour * 60) + timeinfo->tm_min) / (24.0 * 60.0);
|
g_Daytime = ((timeinfo->tm_hour * 60) + timeinfo->tm_min) / (24.0 * 60.0);
|
||||||
// update audio recorder
|
|
||||||
audioDriver.update ();
|
|
||||||
// update input information
|
|
||||||
inputContext.update ();
|
|
||||||
// keep track of the previous frame's time
|
// keep track of the previous frame's time
|
||||||
g_TimeLast = g_Time;
|
g_TimeLast = g_Time;
|
||||||
// calculate the current time value
|
// calculate the current time value
|
||||||
g_Time = videoDriver.getRenderTime ();
|
g_Time = videoDriver->getRenderTime ();
|
||||||
// get the start time of the frame
|
// update audio recorder
|
||||||
startTime = g_Time;
|
audioDriver->update ();
|
||||||
// render the scene
|
// update input information
|
||||||
context.render ();
|
inputContext->update ();
|
||||||
// get the end time of the frame
|
// process driver events
|
||||||
endTime = videoDriver.getRenderTime ();
|
videoDriver->dispatchEventQueue ();
|
||||||
|
|
||||||
// ensure the frame time is correct to not overrun FPS
|
if (!this->m_context.settings.screenshot.take || videoDriver->getFrameCounter () < 5)
|
||||||
if ((endTime - startTime) < minimumTime)
|
|
||||||
usleep ((minimumTime - (endTime - startTime)) * CLOCKS_PER_SEC);
|
|
||||||
|
|
||||||
if (!this->m_context.settings.screenshot.take || videoDriver.getFrameCounter () != 5)
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
this->takeScreenshot (context, this->m_context.settings.screenshot.path, this->m_context.settings.screenshot.format);
|
this->takeScreenshot (*context, this->m_context.settings.screenshot.path, this->m_context.settings.screenshot.format);
|
||||||
// disable screenshot just in case the counter overflows
|
|
||||||
this->m_context.settings.screenshot.take = false;
|
this->m_context.settings.screenshot.take = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -358,6 +367,12 @@ namespace WallpaperEngine::Application
|
|||||||
SDL_Quit ();
|
SDL_Quit ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CWallpaperApplication::update(Render::Drivers::Output::COutputViewport* viewport)
|
||||||
|
{
|
||||||
|
// render the scene
|
||||||
|
context->render (viewport);
|
||||||
|
}
|
||||||
|
|
||||||
void CWallpaperApplication::signal (int signal)
|
void CWallpaperApplication::signal (int signal)
|
||||||
{
|
{
|
||||||
this->m_context.state.general.keepRunning = false;
|
this->m_context.state.general.keepRunning = false;
|
||||||
|
@ -9,6 +9,24 @@
|
|||||||
#include "WallpaperEngine/Render/CWallpaper.h"
|
#include "WallpaperEngine/Render/CWallpaper.h"
|
||||||
#include "WallpaperEngine/Render/CRenderContext.h"
|
#include "WallpaperEngine/Render/CRenderContext.h"
|
||||||
#include "WallpaperEngine/Render/Drivers/CX11OpenGLDriver.h"
|
#include "WallpaperEngine/Render/Drivers/CX11OpenGLDriver.h"
|
||||||
|
#ifdef ENABLE_WAYLAND
|
||||||
|
#include "WallpaperEngine/Render/Drivers/CWaylandOpenGLDriver.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "WallpaperEngine/Render/Drivers/Detectors/CX11FullScreenDetector.h"
|
||||||
|
#ifdef ENABLE_WAYLAND
|
||||||
|
#include "WallpaperEngine/Render/Drivers/Detectors/CWaylandFullScreenDetector.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "WallpaperEngine/Render/Drivers/Output/CGLFWWindowOutput.h"
|
||||||
|
#include "WallpaperEngine/Render/Drivers/Output/CX11Output.h"
|
||||||
|
#ifdef ENABLE_WAYLAND
|
||||||
|
#include "WallpaperEngine/Render/Drivers/Output/CWaylandOutput.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "WallpaperEngine/Audio/Drivers/CSDLAudioDriver.h"
|
||||||
|
|
||||||
|
#include "WallpaperEngine/Input/CInputContext.h"
|
||||||
|
|
||||||
namespace WallpaperEngine::Application
|
namespace WallpaperEngine::Application
|
||||||
{
|
{
|
||||||
@ -21,6 +39,7 @@ namespace WallpaperEngine::Application
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit CWallpaperApplication (CApplicationContext& context);
|
explicit CWallpaperApplication (CApplicationContext& context);
|
||||||
|
~CWallpaperApplication ();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shows the application until it's closed
|
* Shows the application until it's closed
|
||||||
@ -44,6 +63,14 @@ namespace WallpaperEngine::Application
|
|||||||
* @return The current application context
|
* @return The current application context
|
||||||
*/
|
*/
|
||||||
[[nodiscard]] CApplicationContext& getContext () const;
|
[[nodiscard]] CApplicationContext& getContext () const;
|
||||||
|
/**
|
||||||
|
* Renders a frame
|
||||||
|
*/
|
||||||
|
void update(Render::Drivers::Output::COutputViewport* viewport);
|
||||||
|
/**
|
||||||
|
* Gets the output
|
||||||
|
*/
|
||||||
|
WallpaperEngine::Render::Drivers::Output::COutput* getOutput() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
@ -89,5 +116,11 @@ namespace WallpaperEngine::Application
|
|||||||
CApplicationContext& m_context;
|
CApplicationContext& m_context;
|
||||||
/** Maps screens to backgrounds */
|
/** Maps screens to backgrounds */
|
||||||
std::map <std::string, Core::CProject*> m_backgrounds;
|
std::map <std::string, Core::CProject*> m_backgrounds;
|
||||||
|
|
||||||
|
WallpaperEngine::Render::Drivers::CVideoDriver* videoDriver;
|
||||||
|
WallpaperEngine::Input::CInputContext* inputContext;
|
||||||
|
WallpaperEngine::Audio::Drivers::CSDLAudioDriver* audioDriver;
|
||||||
|
WallpaperEngine::Render::CRenderContext* context;
|
||||||
|
WallpaperEngine::Audio::CAudioContext* audioContext;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
namespace WallpaperEngine::Assets
|
namespace WallpaperEngine::Assets
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
|
@ -4,7 +4,7 @@ namespace WallpaperEngine::Audio::Drivers::Detectors
|
|||||||
{
|
{
|
||||||
CAudioPlayingDetector::CAudioPlayingDetector (
|
CAudioPlayingDetector::CAudioPlayingDetector (
|
||||||
Application::CApplicationContext& appContext,
|
Application::CApplicationContext& appContext,
|
||||||
Render::Drivers::Detectors::CFullScreenDetector& fullscreenDetector) :
|
const Render::Drivers::Detectors::CFullScreenDetector& fullscreenDetector) :
|
||||||
m_applicationContext (appContext),
|
m_applicationContext (appContext),
|
||||||
m_fullscreenDetector (fullscreenDetector),
|
m_fullscreenDetector (fullscreenDetector),
|
||||||
m_isPlaying (false)
|
m_isPlaying (false)
|
||||||
@ -21,7 +21,7 @@ namespace WallpaperEngine::Audio::Drivers::Detectors
|
|||||||
return this->m_applicationContext;
|
return this->m_applicationContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
Render::Drivers::Detectors::CFullScreenDetector& CAudioPlayingDetector::getFullscreenDetector ()
|
const Render::Drivers::Detectors::CFullScreenDetector& CAudioPlayingDetector::getFullscreenDetector () const
|
||||||
{
|
{
|
||||||
return this->m_fullscreenDetector;
|
return this->m_fullscreenDetector;
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@ namespace WallpaperEngine
|
|||||||
class CAudioPlayingDetector
|
class CAudioPlayingDetector
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CAudioPlayingDetector (Application::CApplicationContext& appContext, Render::Drivers::Detectors::CFullScreenDetector& fullscreenDetector);
|
CAudioPlayingDetector (Application::CApplicationContext& appContext, const Render::Drivers::Detectors::CFullScreenDetector& fullscreenDetector);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return If any kind of sound is currently playing on the default audio device
|
* @return If any kind of sound is currently playing on the default audio device
|
||||||
@ -48,13 +48,13 @@ namespace WallpaperEngine
|
|||||||
/**
|
/**
|
||||||
* @return The fullscreen detector used
|
* @return The fullscreen detector used
|
||||||
*/
|
*/
|
||||||
[[nodiscard]] Render::Drivers::Detectors::CFullScreenDetector& getFullscreenDetector ();
|
[[nodiscard]] const Render::Drivers::Detectors::CFullScreenDetector& getFullscreenDetector () const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool m_isPlaying;
|
bool m_isPlaying;
|
||||||
|
|
||||||
Application::CApplicationContext& m_applicationContext;
|
Application::CApplicationContext& m_applicationContext;
|
||||||
Render::Drivers::Detectors::CFullScreenDetector& m_fullscreenDetector;
|
const Render::Drivers::Detectors::CFullScreenDetector& m_fullscreenDetector;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@ namespace WallpaperEngine::Audio::Drivers::Detectors
|
|||||||
// get processid
|
// get processid
|
||||||
const char* value = pa_proplist_gets (info->proplist, PA_PROP_APPLICATION_PROCESS_ID);
|
const char* value = pa_proplist_gets (info->proplist, PA_PROP_APPLICATION_PROCESS_ID);
|
||||||
|
|
||||||
if (atoi (value) != getpid () && pa_cvolume_avg (&info->volume) != PA_VOLUME_MUTED)
|
if (value && atoi (value) != getpid () && pa_cvolume_avg (&info->volume) != PA_VOLUME_MUTED)
|
||||||
detector->setIsPlaying (true);
|
detector->setIsPlaying (true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -34,7 +34,7 @@ namespace WallpaperEngine::Audio::Drivers::Detectors
|
|||||||
|
|
||||||
CPulseAudioPlayingDetector::CPulseAudioPlayingDetector (
|
CPulseAudioPlayingDetector::CPulseAudioPlayingDetector (
|
||||||
Application::CApplicationContext& appContext,
|
Application::CApplicationContext& appContext,
|
||||||
Render::Drivers::Detectors::CFullScreenDetector& fullscreenDetector) :
|
const Render::Drivers::Detectors::CFullScreenDetector& fullscreenDetector) :
|
||||||
CAudioPlayingDetector (appContext, fullscreenDetector),
|
CAudioPlayingDetector (appContext, fullscreenDetector),
|
||||||
m_mainloop (nullptr),
|
m_mainloop (nullptr),
|
||||||
m_mainloopApi (nullptr),
|
m_mainloopApi (nullptr),
|
||||||
|
@ -10,7 +10,7 @@ namespace WallpaperEngine::Audio::Drivers::Detectors
|
|||||||
class CPulseAudioPlayingDetector : public CAudioPlayingDetector
|
class CPulseAudioPlayingDetector : public CAudioPlayingDetector
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit CPulseAudioPlayingDetector (Application::CApplicationContext& appContext, Render::Drivers::Detectors::CFullScreenDetector&);
|
explicit CPulseAudioPlayingDetector (Application::CApplicationContext& appContext, const Render::Drivers::Detectors::CFullScreenDetector&);
|
||||||
~CPulseAudioPlayingDetector ();
|
~CPulseAudioPlayingDetector ();
|
||||||
|
|
||||||
void update () override;
|
void update () override;
|
||||||
|
@ -1,20 +1,19 @@
|
|||||||
#include "CInputContext.h"
|
#include "CInputContext.h"
|
||||||
#include "WallpaperEngine/Render/Drivers/CX11OpenGLDriver.h"
|
|
||||||
|
|
||||||
using namespace WallpaperEngine::Input;
|
using namespace WallpaperEngine::Input;
|
||||||
using namespace WallpaperEngine::Render::Drivers;
|
using namespace WallpaperEngine::Render::Drivers;
|
||||||
|
|
||||||
CInputContext::CInputContext (CX11OpenGLDriver& videoDriver) :
|
CInputContext::CInputContext (CMouseInput* mouseInput) :
|
||||||
m_mouse (videoDriver.getWindow ())
|
m_mouse (mouseInput)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void CInputContext::update ()
|
void CInputContext::update ()
|
||||||
{
|
{
|
||||||
this->m_mouse.update ();
|
this->m_mouse->update ();
|
||||||
}
|
}
|
||||||
|
|
||||||
const CMouseInput& CInputContext::getMouseInput () const
|
const CMouseInput& CInputContext::getMouseInput () const
|
||||||
{
|
{
|
||||||
return this->m_mouse;
|
return *this->m_mouse;
|
||||||
}
|
}
|
@ -1,11 +1,10 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "WallpaperEngine/Render/Drivers/CX11OpenGLDriver.h"
|
|
||||||
#include "CMouseInput.h"
|
#include "CMouseInput.h"
|
||||||
|
|
||||||
namespace WallpaperEngine::Render::Drivers
|
namespace WallpaperEngine::Render::Drivers
|
||||||
{
|
{
|
||||||
class CX11OpenGLDriver;
|
class CVideoDriver;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace WallpaperEngine::Input
|
namespace WallpaperEngine::Input
|
||||||
@ -13,12 +12,16 @@ namespace WallpaperEngine::Input
|
|||||||
class CInputContext
|
class CInputContext
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit CInputContext (Render::Drivers::CX11OpenGLDriver& videoDriver);
|
explicit CInputContext (CMouseInput* mouseInput);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates input information
|
||||||
|
*/
|
||||||
void update ();
|
void update ();
|
||||||
|
|
||||||
[[nodiscard]] const CMouseInput& getMouseInput () const;
|
[[nodiscard]] const CMouseInput& getMouseInput () const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CMouseInput m_mouse;
|
CMouseInput* m_mouse;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -1,14 +0,0 @@
|
|||||||
#include <glm/common.hpp>
|
|
||||||
#include "CMouseInput.h"
|
|
||||||
|
|
||||||
using namespace WallpaperEngine::Input;
|
|
||||||
|
|
||||||
CMouseInput::CMouseInput (GLFWwindow* window) : position (), m_mousePosition (), m_window (window) {}
|
|
||||||
|
|
||||||
void CMouseInput::update ()
|
|
||||||
{
|
|
||||||
// update current mouse position
|
|
||||||
glfwGetCursorPos (this->m_window, &this->m_mousePosition.x, &this->m_mousePosition.y);
|
|
||||||
// interpolate to the new position
|
|
||||||
this->position = glm::mix (this->position, this->m_mousePosition, 1.0);
|
|
||||||
}
|
|
@ -1,7 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <glm/vec2.hpp>
|
#include <glm/vec2.hpp>
|
||||||
#include "GLFW/glfw3.h"
|
|
||||||
|
|
||||||
namespace WallpaperEngine::Input
|
namespace WallpaperEngine::Input
|
||||||
{
|
{
|
||||||
@ -11,28 +10,15 @@ namespace WallpaperEngine::Input
|
|||||||
class CMouseInput
|
class CMouseInput
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit CMouseInput(GLFWwindow* window);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Takes current mouse position and updates it
|
* Takes current mouse position and updates it
|
||||||
*/
|
*/
|
||||||
void update ();
|
virtual void update () = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The virtual pointer's position
|
* The virtual pointer's position
|
||||||
*/
|
*/
|
||||||
glm::dvec2 position;
|
virtual glm::dvec2 position () const = 0;
|
||||||
|
|
||||||
private:
|
|
||||||
/**
|
|
||||||
* The GLFW window to get mouse position from
|
|
||||||
*/
|
|
||||||
GLFWwindow* m_window;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The current mouse position
|
|
||||||
*/
|
|
||||||
glm::dvec2 m_mousePosition;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
24
src/WallpaperEngine/Input/Drivers/CGLFWMouseInput.cpp
Normal file
24
src/WallpaperEngine/Input/Drivers/CGLFWMouseInput.cpp
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
#include <glm/common.hpp>
|
||||||
|
#include "CGLFWMouseInput.h"
|
||||||
|
|
||||||
|
#include "WallpaperEngine/Render/Drivers/CX11OpenGLDriver.h"
|
||||||
|
|
||||||
|
using namespace WallpaperEngine::Input::Drivers;
|
||||||
|
|
||||||
|
CGLFWMouseInput::CGLFWMouseInput (Render::Drivers::CX11OpenGLDriver* driver) :
|
||||||
|
m_reportedPosition (),
|
||||||
|
m_mousePosition (),
|
||||||
|
m_driver (driver) {}
|
||||||
|
|
||||||
|
void CGLFWMouseInput::update ()
|
||||||
|
{
|
||||||
|
// update current mouse position
|
||||||
|
glfwGetCursorPos (this->m_driver->getWindow (), &this->m_mousePosition.x, &this->m_mousePosition.y);
|
||||||
|
// interpolate to the new position
|
||||||
|
this->m_reportedPosition = glm::mix (this->m_reportedPosition, this->m_mousePosition, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::dvec2 CGLFWMouseInput::position() const
|
||||||
|
{
|
||||||
|
return this->m_reportedPosition;
|
||||||
|
}
|
42
src/WallpaperEngine/Input/Drivers/CGLFWMouseInput.h
Normal file
42
src/WallpaperEngine/Input/Drivers/CGLFWMouseInput.h
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "WallpaperEngine/Input/CMouseInput.h"
|
||||||
|
|
||||||
|
#include <glm/vec2.hpp>
|
||||||
|
|
||||||
|
namespace WallpaperEngine::Render::Drivers
|
||||||
|
{
|
||||||
|
class CX11OpenGLDriver;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace WallpaperEngine::Input::Drivers
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Handles mouse input for the background
|
||||||
|
*/
|
||||||
|
class CGLFWMouseInput : public CMouseInput
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit CGLFWMouseInput(Render::Drivers::CX11OpenGLDriver* driver);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Takes current mouse position and updates it
|
||||||
|
*/
|
||||||
|
void update () override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The virtual pointer's position
|
||||||
|
*/
|
||||||
|
glm::dvec2 position () const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Render::Drivers::CX11OpenGLDriver* m_driver;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The current mouse position
|
||||||
|
*/
|
||||||
|
glm::dvec2 m_mousePosition;
|
||||||
|
glm::dvec2 m_reportedPosition;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
21
src/WallpaperEngine/Input/Drivers/CWaylandMouseInput.cpp
Normal file
21
src/WallpaperEngine/Input/Drivers/CWaylandMouseInput.cpp
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
#include <glm/common.hpp>
|
||||||
|
#include "CWaylandMouseInput.h"
|
||||||
|
|
||||||
|
using namespace WallpaperEngine::Input::Drivers;
|
||||||
|
|
||||||
|
CWaylandMouseInput::CWaylandMouseInput(WallpaperEngine::Render::Drivers::CWaylandOpenGLDriver* driver) :
|
||||||
|
waylandDriver (driver)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void CWaylandMouseInput::update ()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::dvec2 CWaylandMouseInput::position() const
|
||||||
|
{
|
||||||
|
if (waylandDriver->viewportInFocus && waylandDriver->viewportInFocus->rendering)
|
||||||
|
return waylandDriver->viewportInFocus->mousePos;
|
||||||
|
|
||||||
|
return {0, 0};
|
||||||
|
}
|
41
src/WallpaperEngine/Input/Drivers/CWaylandMouseInput.h
Normal file
41
src/WallpaperEngine/Input/Drivers/CWaylandMouseInput.h
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
#ifdef ENABLE_WAYLAND
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "WallpaperEngine/Input/CMouseInput.h"
|
||||||
|
#include "WallpaperEngine/Render/Drivers/CWaylandOpenGLDriver.h"
|
||||||
|
|
||||||
|
#include <glm/vec2.hpp>
|
||||||
|
#include "GLFW/glfw3.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace WallpaperEngine::Input::Drivers
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Handles mouse input for the background
|
||||||
|
*/
|
||||||
|
class CWaylandMouseInput : public CMouseInput
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit CWaylandMouseInput(WallpaperEngine::Render::Drivers::CWaylandOpenGLDriver* driver);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Takes current mouse position and updates it
|
||||||
|
*/
|
||||||
|
void update () override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The virtual pointer's position
|
||||||
|
*/
|
||||||
|
glm::dvec2 position () const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
/**
|
||||||
|
* Wayland: Driver
|
||||||
|
*/
|
||||||
|
WallpaperEngine::Render::Drivers::CWaylandOpenGLDriver* waylandDriver = nullptr;
|
||||||
|
|
||||||
|
glm::dvec2 pos;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* ENABLE_WAYLAND */
|
@ -10,11 +10,10 @@
|
|||||||
namespace WallpaperEngine::Render
|
namespace WallpaperEngine::Render
|
||||||
{
|
{
|
||||||
CRenderContext::CRenderContext (
|
CRenderContext::CRenderContext (
|
||||||
const Drivers::Output::COutput* output, Drivers::CVideoDriver& driver, Input::CInputContext& input,
|
Drivers::CVideoDriver& driver, Input::CInputContext& input,
|
||||||
CWallpaperApplication& app
|
CWallpaperApplication& app
|
||||||
) :
|
) :
|
||||||
m_defaultWallpaper (nullptr),
|
m_defaultWallpaper (nullptr),
|
||||||
m_output (output),
|
|
||||||
m_driver (driver),
|
m_driver (driver),
|
||||||
m_app (app),
|
m_app (app),
|
||||||
m_input (input),
|
m_input (input),
|
||||||
@ -22,48 +21,30 @@ namespace WallpaperEngine::Render
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void CRenderContext::render ()
|
void CRenderContext::render (Drivers::Output::COutputViewport* viewport)
|
||||||
{
|
{
|
||||||
bool firstFrame = true;
|
viewport->makeCurrent ();
|
||||||
bool renderFrame = true;
|
|
||||||
|
|
||||||
for (const auto& cur : this->m_output->getViewports ())
|
|
||||||
{
|
|
||||||
#if !NDEBUG
|
#if !NDEBUG
|
||||||
std::string str = "Rendering to output " + cur.first;
|
std::string str = "Rendering to output " + viewport->name;
|
||||||
|
|
||||||
glPushDebugGroup (GL_DEBUG_SOURCE_APPLICATION, 0, -1, str.c_str ());
|
glPushDebugGroup (GL_DEBUG_SOURCE_APPLICATION, 0, -1, str.c_str ());
|
||||||
#endif /* DEBUG */
|
#endif /* DEBUG */
|
||||||
|
|
||||||
// search the background in the viewport selection
|
// search the background in the viewport selection
|
||||||
auto ref = this->m_wallpapers.find (cur.first);
|
auto ref = this->m_wallpapers.find (viewport->name);
|
||||||
|
|
||||||
|
// render the background
|
||||||
|
if (ref != this->m_wallpapers.end ())
|
||||||
|
ref->second->render (viewport->viewport, this->getOutput ().renderVFlip ());
|
||||||
|
else
|
||||||
|
this->m_defaultWallpaper->render (viewport->viewport, this->getOutput ().renderVFlip ());
|
||||||
|
|
||||||
// render the background
|
|
||||||
if (ref != this->m_wallpapers.end ())
|
|
||||||
ref->second->render (cur.second.viewport, this->m_output->renderVFlip (), renderFrame, firstFrame);
|
|
||||||
else
|
|
||||||
this->m_defaultWallpaper->render (
|
|
||||||
cur.second.viewport, this->m_output->renderVFlip (), renderFrame, firstFrame
|
|
||||||
);
|
|
||||||
// scenes need to render a new frame for each viewport as they produce different results
|
|
||||||
// but videos should only be rendered once per group of viewports
|
|
||||||
firstFrame = false;
|
|
||||||
#if !NDEBUG
|
#if !NDEBUG
|
||||||
glPopDebugGroup ();
|
glPopDebugGroup ();
|
||||||
#endif /* DEBUG */
|
#endif /* DEBUG */
|
||||||
}
|
|
||||||
|
|
||||||
// read the full texture into the image
|
viewport->swapOutput ();
|
||||||
if (this->m_output->haveImageBuffer ())
|
|
||||||
glReadPixels (
|
|
||||||
0, 0, this->m_output->getFullWidth (), this->m_output->getFullHeight (), GL_BGRA, GL_UNSIGNED_BYTE,
|
|
||||||
this->m_output->getImageBuffer ()
|
|
||||||
);
|
|
||||||
|
|
||||||
// update the output with the given image
|
|
||||||
this->m_output->updateRender ();
|
|
||||||
// finally swap buffers
|
|
||||||
this->m_driver.swapBuffers ();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CRenderContext::setDefaultWallpaper (CWallpaper* wallpaper)
|
void CRenderContext::setDefaultWallpaper (CWallpaper* wallpaper)
|
||||||
@ -91,9 +72,9 @@ namespace WallpaperEngine::Render
|
|||||||
return this->m_driver;
|
return this->m_driver;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Drivers::Output::COutput* CRenderContext::getOutput () const
|
const Drivers::Output::COutput& CRenderContext::getOutput () const
|
||||||
{
|
{
|
||||||
return this->m_output;
|
return this->m_driver.getOutput ();
|
||||||
}
|
}
|
||||||
|
|
||||||
const ITexture* CRenderContext::resolveTexture (const std::string& name)
|
const ITexture* CRenderContext::resolveTexture (const std::string& name)
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#include "WallpaperEngine/Input/CMouseInput.h"
|
#include "WallpaperEngine/Input/CMouseInput.h"
|
||||||
#include "WallpaperEngine/Render/Drivers/CVideoDriver.h"
|
#include "WallpaperEngine/Render/Drivers/CVideoDriver.h"
|
||||||
#include "WallpaperEngine/Render/Drivers/Output/COutput.h"
|
#include "WallpaperEngine/Render/Drivers/Output/COutput.h"
|
||||||
|
#include "WallpaperEngine/Render/Drivers/Output/COutputViewport.h"
|
||||||
|
|
||||||
namespace WallpaperEngine
|
namespace WallpaperEngine
|
||||||
{
|
{
|
||||||
@ -26,6 +27,7 @@ namespace WallpaperEngine
|
|||||||
namespace Output
|
namespace Output
|
||||||
{
|
{
|
||||||
class COutput;
|
class COutput;
|
||||||
|
class COutputViewport;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -35,15 +37,15 @@ namespace WallpaperEngine
|
|||||||
class CRenderContext
|
class CRenderContext
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CRenderContext (const Drivers::Output::COutput* output, Drivers::CVideoDriver& driver, Input::CInputContext& input, CWallpaperApplication& app);
|
CRenderContext (Drivers::CVideoDriver& driver, Input::CInputContext& input, CWallpaperApplication& app);
|
||||||
|
|
||||||
void render ();
|
void render (Drivers::Output::COutputViewport* viewport);
|
||||||
void setDefaultWallpaper (CWallpaper* wallpaper);
|
void setDefaultWallpaper (CWallpaper* wallpaper);
|
||||||
void setWallpaper (const std::string& display, CWallpaper* wallpaper);
|
void setWallpaper (const std::string& display, CWallpaper* wallpaper);
|
||||||
[[nodiscard]] Input::CInputContext& getInputContext () const;
|
[[nodiscard]] Input::CInputContext& getInputContext () const;
|
||||||
[[nodiscard]] const CWallpaperApplication& getApp () const;
|
[[nodiscard]] const CWallpaperApplication& getApp () const;
|
||||||
[[nodiscard]] const Drivers::CVideoDriver& getDriver () const;
|
[[nodiscard]] const Drivers::CVideoDriver& getDriver () const;
|
||||||
[[nodiscard]] const Drivers::Output::COutput* getOutput () const;
|
[[nodiscard]] const Drivers::Output::COutput& getOutput () const;
|
||||||
const ITexture* resolveTexture (const std::string& name);
|
const ITexture* resolveTexture (const std::string& name);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -59,8 +61,6 @@ namespace WallpaperEngine
|
|||||||
CWallpaperApplication& m_app;
|
CWallpaperApplication& m_app;
|
||||||
/** Texture cache for the render */
|
/** Texture cache for the render */
|
||||||
CTextureCache* m_textureCache;
|
CTextureCache* m_textureCache;
|
||||||
/** Output driver that describes how the wallpapers are rendered */
|
|
||||||
const Drivers::Output::COutput* m_output;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -248,7 +248,7 @@ void CScene::renderFrame (glm::ivec4 viewport)
|
|||||||
void CScene::updateMouse (glm::ivec4 viewport)
|
void CScene::updateMouse (glm::ivec4 viewport)
|
||||||
{
|
{
|
||||||
// update virtual mouse position first
|
// update virtual mouse position first
|
||||||
glm::dvec2 position = this->getContext ().getInputContext ().getMouseInput ().position;
|
glm::dvec2 position = this->getContext ().getInputContext ().getMouseInput ().position();
|
||||||
// TODO: PROPERLY TRANSLATE THESE TO WHAT'S VISIBLE ON SCREEN (FOR BACKGROUNDS THAT DO NOT EXACTLY FIT ON SCREEN)
|
// TODO: PROPERLY TRANSLATE THESE TO WHAT'S VISIBLE ON SCREEN (FOR BACKGROUNDS THAT DO NOT EXACTLY FIT ON SCREEN)
|
||||||
|
|
||||||
// rollover the position to the last
|
// rollover the position to the last
|
||||||
|
@ -8,7 +8,7 @@ using namespace WallpaperEngine::Render;
|
|||||||
|
|
||||||
void* get_proc_address (void* ctx, const char* name)
|
void* get_proc_address (void* ctx, const char* name)
|
||||||
{
|
{
|
||||||
return reinterpret_cast <void*> (glfwGetProcAddress (name));
|
return static_cast<CVideo*> (ctx)->getContext ().getDriver ().getProcAddress (name);
|
||||||
}
|
}
|
||||||
|
|
||||||
CVideo::CVideo (Core::CVideo* video, CRenderContext& context, CAudioContext& audioContext) :
|
CVideo::CVideo (Core::CVideo* video, CRenderContext& context, CAudioContext& audioContext) :
|
||||||
@ -40,7 +40,7 @@ CVideo::CVideo (Core::CVideo* video, CRenderContext& context, CAudioContext& aud
|
|||||||
mpv_set_option (this->m_mpv, "volume", MPV_FORMAT_DOUBLE, &volume);
|
mpv_set_option (this->m_mpv, "volume", MPV_FORMAT_DOUBLE, &volume);
|
||||||
|
|
||||||
// initialize gl context for mpv
|
// initialize gl context for mpv
|
||||||
mpv_opengl_init_params gl_init_params {get_proc_address, nullptr};
|
mpv_opengl_init_params gl_init_params {get_proc_address, this};
|
||||||
mpv_render_param params[] {
|
mpv_render_param params[] {
|
||||||
{MPV_RENDER_PARAM_API_TYPE, const_cast <char*> (MPV_RENDER_API_TYPE_OPENGL)},
|
{MPV_RENDER_PARAM_API_TYPE, const_cast <char*> (MPV_RENDER_API_TYPE_OPENGL)},
|
||||||
{MPV_RENDER_PARAM_OPENGL_INIT_PARAMS, &gl_init_params},
|
{MPV_RENDER_PARAM_OPENGL_INIT_PARAMS, &gl_init_params},
|
||||||
|
@ -211,10 +211,9 @@ void CWallpaper::setDestinationFramebuffer (GLuint framebuffer)
|
|||||||
this->m_destFramebuffer = framebuffer;
|
this->m_destFramebuffer = framebuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CWallpaper::render (glm::ivec4 viewport, bool vflip, bool renderFrame, bool newFrame)
|
void CWallpaper::render (glm::ivec4 viewport, bool vflip)
|
||||||
{
|
{
|
||||||
if (renderFrame)
|
this->renderFrame (viewport);
|
||||||
this->renderFrame (viewport);
|
|
||||||
|
|
||||||
uint32_t projectionWidth = this->getWidth ();
|
uint32_t projectionWidth = this->getWidth ();
|
||||||
uint32_t projectionHeight = this->getHeight ();
|
uint32_t projectionHeight = this->getHeight ();
|
||||||
@ -293,9 +292,6 @@ void CWallpaper::render (glm::ivec4 viewport, bool vflip, bool renderFrame, bool
|
|||||||
|
|
||||||
glBindVertexArray (this->m_vaoBuffer);
|
glBindVertexArray (this->m_vaoBuffer);
|
||||||
|
|
||||||
if (newFrame)
|
|
||||||
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
||||||
|
|
||||||
glDisable (GL_BLEND);
|
glDisable (GL_BLEND);
|
||||||
glDisable (GL_DEPTH_TEST);
|
glDisable (GL_DEPTH_TEST);
|
||||||
// do not use any shader
|
// do not use any shader
|
||||||
|
@ -37,7 +37,7 @@ namespace WallpaperEngine::Render
|
|||||||
/**
|
/**
|
||||||
* Performs a render pass of the wallpaper
|
* Performs a render pass of the wallpaper
|
||||||
*/
|
*/
|
||||||
void render (glm::ivec4 viewport, bool vflip, bool renderFrame = true, bool newFrame = true);
|
void render (glm::ivec4 viewport, bool vflip);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return The container to resolve files for this wallpaper
|
* @return The container to resolve files for this wallpaper
|
||||||
|
@ -1,3 +1,17 @@
|
|||||||
#include "CVideoDriver.h"
|
#include "CVideoDriver.h"
|
||||||
|
|
||||||
using namespace WallpaperEngine::Render::Drivers;
|
using namespace WallpaperEngine::Render::Drivers;
|
||||||
|
|
||||||
|
CVideoDriver::CVideoDriver (CWallpaperApplication& app) :
|
||||||
|
m_app (app)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
CVideoDriver::~CVideoDriver ()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
CWallpaperApplication& CVideoDriver::getApp () const
|
||||||
|
{
|
||||||
|
return this->m_app;
|
||||||
|
}
|
@ -2,20 +2,39 @@
|
|||||||
|
|
||||||
#include <glm/vec4.hpp>
|
#include <glm/vec4.hpp>
|
||||||
#include <glm/vec2.hpp>
|
#include <glm/vec2.hpp>
|
||||||
|
#include <string>
|
||||||
|
#include "WallpaperEngine/Render/Drivers/Output/COutput.h"
|
||||||
|
|
||||||
|
namespace WallpaperEngine::Application
|
||||||
|
{
|
||||||
|
class CWallpaperApplication;
|
||||||
|
}
|
||||||
|
|
||||||
namespace WallpaperEngine::Render::Drivers
|
namespace WallpaperEngine::Render::Drivers
|
||||||
{
|
{
|
||||||
|
namespace Detectors
|
||||||
|
{
|
||||||
|
class CFullScreenDetector;
|
||||||
|
}
|
||||||
|
|
||||||
class CVideoDriver
|
class CVideoDriver
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
CVideoDriver (CWallpaperApplication& app);
|
||||||
|
virtual ~CVideoDriver ();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return The window handle used by this video driver
|
* @return The fullscreen detector this video driver uses
|
||||||
*/
|
*/
|
||||||
virtual void* getWindowHandle () const = 0;
|
[[nodiscard]] virtual Detectors::CFullScreenDetector& getFullscreenDetector () = 0;
|
||||||
|
/**
|
||||||
|
* @return The current output in use
|
||||||
|
*/
|
||||||
|
[[nodiscard]] virtual Output::COutput& getOutput () = 0;
|
||||||
/**
|
/**
|
||||||
* @return The time that has passed since the driver started
|
* @return The time that has passed since the driver started
|
||||||
*/
|
*/
|
||||||
virtual float getRenderTime () const = 0;
|
[[nodiscard]] virtual float getRenderTime () const = 0;
|
||||||
/**
|
/**
|
||||||
* @return If a close was requested by the OS
|
* @return If a close was requested by the OS
|
||||||
*/
|
*/
|
||||||
@ -39,14 +58,27 @@ namespace WallpaperEngine::Render::Drivers
|
|||||||
/**
|
/**
|
||||||
* @return The size of the framebuffer available for the driver
|
* @return The size of the framebuffer available for the driver
|
||||||
*/
|
*/
|
||||||
virtual glm::ivec2 getFramebufferSize () const = 0;
|
[[nodiscard]] virtual glm::ivec2 getFramebufferSize () const = 0;
|
||||||
/**
|
|
||||||
* Performs buffer swapping
|
|
||||||
*/
|
|
||||||
virtual void swapBuffers () = 0;
|
|
||||||
/**
|
/**
|
||||||
* @return The number of rendered frames since the start of the driver
|
* @return The number of rendered frames since the start of the driver
|
||||||
*/
|
*/
|
||||||
virtual uint32_t getFrameCounter () const = 0;
|
[[nodiscard]] virtual uint32_t getFrameCounter () const = 0;
|
||||||
|
/**
|
||||||
|
* @param name
|
||||||
|
* @return GetProcAddress for this video driver
|
||||||
|
*/
|
||||||
|
[[nodiscard]] virtual void* getProcAddress (const char* name) const = 0;
|
||||||
|
/**
|
||||||
|
* Process events on the driver and renders a frame
|
||||||
|
*/
|
||||||
|
virtual void dispatchEventQueue() = 0;
|
||||||
|
/**
|
||||||
|
* @return The app that owns this driver
|
||||||
|
*/
|
||||||
|
[[nodiscard]] CWallpaperApplication& getApp () const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
/** App that owns this driver */
|
||||||
|
CWallpaperApplication& m_app;
|
||||||
};
|
};
|
||||||
}
|
}
|
401
src/WallpaperEngine/Render/Drivers/CWaylandOpenGLDriver.cpp
Normal file
401
src/WallpaperEngine/Render/Drivers/CWaylandOpenGLDriver.cpp
Normal file
@ -0,0 +1,401 @@
|
|||||||
|
#include "CWaylandOpenGLDriver.h"
|
||||||
|
#include "WallpaperEngine/Application/CWallpaperApplication.h"
|
||||||
|
|
||||||
|
#include <FreeImage.h>
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
#define class _class
|
||||||
|
#define namespace _namespace
|
||||||
|
#define static
|
||||||
|
extern "C" {
|
||||||
|
#include "xdg-shell-protocol.h"
|
||||||
|
#include "wlr-layer-shell-unstable-v1-protocol.h"
|
||||||
|
}
|
||||||
|
#undef class
|
||||||
|
#undef namespace
|
||||||
|
#undef static
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
using namespace WallpaperEngine::Render::Drivers;
|
||||||
|
|
||||||
|
static void handlePointerEnter (
|
||||||
|
void* data, struct wl_pointer* wl_pointer, uint32_t serial, struct wl_surface* surface,
|
||||||
|
wl_fixed_t surface_x, wl_fixed_t surface_y)
|
||||||
|
{
|
||||||
|
const auto driver = static_cast <CWaylandOpenGLDriver*> (data);
|
||||||
|
const auto viewport = driver->surfaceToViewport (surface);
|
||||||
|
driver->viewportInFocus = viewport;
|
||||||
|
wl_surface_set_buffer_scale(viewport->cursorSurface, viewport->scale);
|
||||||
|
wl_surface_attach(viewport->cursorSurface, wl_cursor_image_get_buffer(viewport->pointer->images[0]), 0, 0);
|
||||||
|
wl_pointer_set_cursor(wl_pointer, serial, viewport->cursorSurface, viewport->pointer->images[0]->hotspot_x, viewport->pointer->images[0]->hotspot_y);
|
||||||
|
wl_surface_commit(viewport->cursorSurface);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void handlePointerLeave(void* data, struct wl_pointer* wl_pointer, uint32_t serial, struct wl_surface* surface)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void handlePointerAxis(void* data, wl_pointer* wl_pointer, uint32_t time, uint32_t axis, wl_fixed_t value)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void handlePointerMotion(
|
||||||
|
void* data, struct wl_pointer* wl_pointer, uint32_t time, wl_fixed_t surface_x, wl_fixed_t surface_y)
|
||||||
|
{
|
||||||
|
const auto driver = static_cast <CWaylandOpenGLDriver*> (data);
|
||||||
|
|
||||||
|
auto x = wl_fixed_to_double(surface_x);
|
||||||
|
auto y = wl_fixed_to_double(surface_y);
|
||||||
|
|
||||||
|
if (!driver->viewportInFocus)
|
||||||
|
return;
|
||||||
|
|
||||||
|
driver->viewportInFocus->mousePos = {x * driver->viewportInFocus->scale, y * driver->viewportInFocus->scale};
|
||||||
|
}
|
||||||
|
|
||||||
|
static void handlePointerButton(
|
||||||
|
void* data, struct wl_pointer* wl_pointer, uint32_t serial, uint32_t time, uint32_t button, uint32_t button_state)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct wl_pointer_listener pointerListener =
|
||||||
|
{
|
||||||
|
.enter = handlePointerEnter,
|
||||||
|
.leave = handlePointerLeave,
|
||||||
|
.motion = handlePointerMotion,
|
||||||
|
.button = handlePointerButton,
|
||||||
|
.axis = handlePointerAxis
|
||||||
|
};
|
||||||
|
|
||||||
|
static void handleCapabilities(void* data, wl_seat* wl_seat, uint32_t capabilities)
|
||||||
|
{
|
||||||
|
if (capabilities & WL_SEAT_CAPABILITY_POINTER)
|
||||||
|
wl_pointer_add_listener(wl_seat_get_pointer(wl_seat), &pointerListener, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct wl_seat_listener seatListener =
|
||||||
|
{
|
||||||
|
.capabilities = handleCapabilities
|
||||||
|
};
|
||||||
|
|
||||||
|
static void handleGlobal(void *data, struct wl_registry *registry, uint32_t name, const char *interface, uint32_t version)
|
||||||
|
{
|
||||||
|
const auto driver = static_cast <CWaylandOpenGLDriver*> (data);
|
||||||
|
|
||||||
|
if (strcmp(interface, wl_compositor_interface.name) == 0) {
|
||||||
|
driver->getWaylandContext()->compositor = (wl_compositor*)wl_registry_bind(registry, name, &wl_compositor_interface, 4);
|
||||||
|
} else if (strcmp(interface, wl_shm_interface.name) == 0) {
|
||||||
|
driver->getWaylandContext()->shm = (wl_shm*)wl_registry_bind(registry, name, &wl_shm_interface, 1);
|
||||||
|
} else if (strcmp(interface, wl_output_interface.name) == 0) {
|
||||||
|
driver->m_screens.emplace_back (new WallpaperEngine::Render::Drivers::Output::CWaylandOutputViewport (driver, name, registry));
|
||||||
|
} else if (strcmp(interface, zwlr_layer_shell_v1_interface.name) == 0) {
|
||||||
|
driver->getWaylandContext()->layerShell = (zwlr_layer_shell_v1*)wl_registry_bind(registry, name, &zwlr_layer_shell_v1_interface, 1);
|
||||||
|
} else if (strcmp(interface, wl_seat_interface.name) == 0) {
|
||||||
|
driver->getWaylandContext()->seat = (wl_seat*)wl_registry_bind(registry, name, &wl_seat_interface, 1);
|
||||||
|
wl_seat_add_listener(driver->getWaylandContext()->seat, &seatListener, driver);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void handleGlobalRemoved(void *data, struct wl_registry *registry, uint32_t id)
|
||||||
|
{
|
||||||
|
// todo: outputs
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct wl_registry_listener registryListener =
|
||||||
|
{
|
||||||
|
.global = handleGlobal,
|
||||||
|
.global_remove = handleGlobalRemoved,
|
||||||
|
};
|
||||||
|
|
||||||
|
void CWaylandOpenGLDriver::initEGL()
|
||||||
|
{
|
||||||
|
const char* CLIENT_EXTENSIONS = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
|
||||||
|
if (!CLIENT_EXTENSIONS)
|
||||||
|
sLog.exception("Failed to query EGL Extensions");
|
||||||
|
|
||||||
|
const std::string CLIENTEXTENSIONS = std::string(CLIENT_EXTENSIONS);
|
||||||
|
|
||||||
|
if (CLIENTEXTENSIONS.find("EGL_EXT_platform_base") == std::string::npos)
|
||||||
|
sLog.exception("EGL_EXT_platform_base not supported by EGL!");
|
||||||
|
|
||||||
|
if (CLIENTEXTENSIONS.find("EGL_EXT_platform_wayland") == std::string::npos)
|
||||||
|
sLog.exception("EGL_EXT_platform_wayland not supported by EGL!");
|
||||||
|
|
||||||
|
PFNEGLGETPLATFORMDISPLAYEXTPROC eglGetPlatformDisplayEXT = (PFNEGLGETPLATFORMDISPLAYEXTPROC)eglGetProcAddress("eglGetPlatformDisplayEXT");
|
||||||
|
m_eglContext.eglCreatePlatformWindowSurfaceEXT = (PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC)eglGetProcAddress("eglCreatePlatformWindowSurfaceEXT");
|
||||||
|
|
||||||
|
if (!eglGetPlatformDisplayEXT || !m_eglContext.eglCreatePlatformWindowSurfaceEXT)
|
||||||
|
sLog.exception("EGL did not return EXT proc pointers!");
|
||||||
|
|
||||||
|
auto deinitEGL = [&] () -> void {
|
||||||
|
eglMakeCurrent(EGL_NO_DISPLAY, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||||
|
if (m_eglContext.display)
|
||||||
|
eglTerminate(m_eglContext.display);
|
||||||
|
eglReleaseThread();
|
||||||
|
};
|
||||||
|
|
||||||
|
m_eglContext.display = eglGetPlatformDisplayEXT(EGL_PLATFORM_WAYLAND_EXT, m_waylandContext.display, nullptr);
|
||||||
|
|
||||||
|
if (m_eglContext.display == EGL_NO_DISPLAY)
|
||||||
|
{
|
||||||
|
deinitEGL ();
|
||||||
|
sLog.exception ("eglGetPlatformDisplayEXT failed!");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!eglInitialize(m_eglContext.display, nullptr, nullptr))
|
||||||
|
{
|
||||||
|
deinitEGL ();
|
||||||
|
sLog.exception ("eglInitialize failed!");
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string CLIENTEXTENSIONSPOSTINIT = std::string(eglQueryString(m_eglContext.display, EGL_EXTENSIONS));
|
||||||
|
|
||||||
|
if (CLIENTEXTENSIONSPOSTINIT.find("EGL_KHR_create_context") == std::string::npos)
|
||||||
|
{
|
||||||
|
deinitEGL ();
|
||||||
|
sLog.exception ("EGL_KHR_create_context not supported!");
|
||||||
|
}
|
||||||
|
|
||||||
|
EGLint matchedConfigs = 0;
|
||||||
|
const EGLint CONFIG_ATTRIBUTES[] = {
|
||||||
|
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
|
||||||
|
EGL_RED_SIZE, 1,
|
||||||
|
EGL_GREEN_SIZE, 1,
|
||||||
|
EGL_BLUE_SIZE, 1,
|
||||||
|
EGL_SAMPLES, 4,
|
||||||
|
EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
|
||||||
|
EGL_NONE,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!eglChooseConfig(m_eglContext.display, CONFIG_ATTRIBUTES, &m_eglContext.config, 1, &matchedConfigs))
|
||||||
|
{
|
||||||
|
deinitEGL ();
|
||||||
|
sLog.exception ("eglChooseConfig failed!");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (matchedConfigs == 0)
|
||||||
|
{
|
||||||
|
deinitEGL ();
|
||||||
|
sLog.exception ("eglChooseConfig failed! (matched 0 configs)");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!eglBindAPI(EGL_OPENGL_API))
|
||||||
|
{
|
||||||
|
deinitEGL ();
|
||||||
|
sLog.exception ("eglBindAPI failed!");
|
||||||
|
}
|
||||||
|
|
||||||
|
const EGLint CONTEXT_ATTRIBUTES[] = {
|
||||||
|
EGL_CONTEXT_MAJOR_VERSION_KHR, 3,
|
||||||
|
EGL_CONTEXT_MINOR_VERSION_KHR, 3,
|
||||||
|
EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR, EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR,
|
||||||
|
EGL_NONE,
|
||||||
|
};
|
||||||
|
|
||||||
|
m_eglContext.context = eglCreateContext(m_eglContext.display, m_eglContext.config, EGL_NO_CONTEXT, CONTEXT_ATTRIBUTES);
|
||||||
|
|
||||||
|
if (m_eglContext.context == EGL_NO_CONTEXT)
|
||||||
|
{
|
||||||
|
deinitEGL ();
|
||||||
|
sLog.error("eglCreateContext error " + std::to_string(eglGetError()));
|
||||||
|
sLog.exception("eglCreateContext failed!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CWaylandOpenGLDriver::onLayerClose(Output::CWaylandOutputViewport* viewport)
|
||||||
|
{
|
||||||
|
sLog.error ("Compositor closed our LS, freeing data...");
|
||||||
|
|
||||||
|
if (viewport->eglSurface)
|
||||||
|
eglDestroySurface (m_eglContext.display, viewport->eglSurface);
|
||||||
|
|
||||||
|
if (viewport->eglWindow)
|
||||||
|
wl_egl_window_destroy(viewport->eglWindow);
|
||||||
|
|
||||||
|
if (viewport->layerSurface)
|
||||||
|
zwlr_layer_surface_v1_destroy(viewport->layerSurface);
|
||||||
|
|
||||||
|
if (viewport->surface)
|
||||||
|
wl_surface_destroy(viewport->surface);
|
||||||
|
|
||||||
|
// remove the output from the list
|
||||||
|
std::remove (this->m_screens.begin (), this->m_screens.end (), viewport);
|
||||||
|
|
||||||
|
// reset the viewports
|
||||||
|
this->getOutput ().reset ();
|
||||||
|
|
||||||
|
// finally free memory used by the viewport
|
||||||
|
delete viewport;
|
||||||
|
}
|
||||||
|
|
||||||
|
CWaylandOpenGLDriver::CWaylandOpenGLDriver(CApplicationContext& context, CWallpaperApplication& app) :
|
||||||
|
m_frameCounter(0),
|
||||||
|
m_fullscreenDetector (context, *this),
|
||||||
|
m_output (context, *this),
|
||||||
|
m_requestedExit (false),
|
||||||
|
m_context (context),
|
||||||
|
CVideoDriver (app)
|
||||||
|
{
|
||||||
|
m_waylandContext.display = wl_display_connect (nullptr);
|
||||||
|
|
||||||
|
if (!m_waylandContext.display)
|
||||||
|
sLog.exception ("Failed to query wayland display");
|
||||||
|
|
||||||
|
m_waylandContext.registry = wl_display_get_registry(m_waylandContext.display);
|
||||||
|
wl_registry_add_listener(m_waylandContext.registry, ®istryListener, this);
|
||||||
|
|
||||||
|
wl_display_dispatch(m_waylandContext.display);
|
||||||
|
wl_display_roundtrip(m_waylandContext.display);
|
||||||
|
|
||||||
|
if (!m_waylandContext.compositor || !m_waylandContext.shm || !m_waylandContext.layerShell || this->m_screens.empty())
|
||||||
|
sLog.exception ("Failed to bind to required interfaces");
|
||||||
|
|
||||||
|
initEGL();
|
||||||
|
|
||||||
|
bool any = false;
|
||||||
|
|
||||||
|
for (auto& o : this->m_screens)
|
||||||
|
{
|
||||||
|
const auto cur = context.settings.general.screenBackgrounds.find (o->name);
|
||||||
|
|
||||||
|
if (cur == context.settings.general.screenBackgrounds.end ())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
o->setupLS ();
|
||||||
|
any = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!any)
|
||||||
|
sLog.exception("No outputs could be initialized, please check the parameters and try again");
|
||||||
|
|
||||||
|
GLenum result = glewInit ();
|
||||||
|
|
||||||
|
if (result != GLEW_OK)
|
||||||
|
sLog.error("Failed to initialize GLEW: ", glewGetErrorString (result));
|
||||||
|
|
||||||
|
FreeImage_Initialise (TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
CWaylandOpenGLDriver::~CWaylandOpenGLDriver ()
|
||||||
|
{
|
||||||
|
// stop EGL
|
||||||
|
eglMakeCurrent (EGL_NO_DISPLAY, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||||
|
|
||||||
|
if (m_eglContext.context != EGL_NO_CONTEXT)
|
||||||
|
eglDestroyContext (m_eglContext.display, m_eglContext.context);
|
||||||
|
|
||||||
|
eglTerminate (m_eglContext.display);
|
||||||
|
eglReleaseThread ();
|
||||||
|
|
||||||
|
// disconnect from wayland display
|
||||||
|
if (this->m_waylandContext.display)
|
||||||
|
wl_display_disconnect (this->m_waylandContext.display);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CWaylandOpenGLDriver::dispatchEventQueue()
|
||||||
|
{
|
||||||
|
static bool initialized = false;
|
||||||
|
|
||||||
|
if (!initialized)
|
||||||
|
{
|
||||||
|
initialized = true;
|
||||||
|
|
||||||
|
for (const auto& viewport : this->getOutput ().getViewports ())
|
||||||
|
this->getApp ().update (viewport.second);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: FRAMETIME CONTROL SHOULD GO BACK TO THE CWALLPAPAERAPPLICATION ONCE ACTUAL PARTICLES ARE IMPLEMENTED
|
||||||
|
// TODO: AS THOSE, MORE THAN LIKELY, WILL REQUIRE OF A DIFFERENT PROCESSING RATE
|
||||||
|
|
||||||
|
// TODO: WRITE A NON-BLOCKING VERSION OF THIS ONCE PARTICLE SIMULATION STARTS WORKING
|
||||||
|
// TODO: OTHERWISE wl_display_dispatch WILL BLOCK IF NO SURFACES ARE BEING DRAWN
|
||||||
|
static float startTime, endTime, minimumTime = 1.0f / this->m_context.settings.render.maximumFPS;
|
||||||
|
// get the start time of the frame
|
||||||
|
startTime = this->getRenderTime ();
|
||||||
|
|
||||||
|
if (wl_display_dispatch(m_waylandContext.display) == -1)
|
||||||
|
m_requestedExit = true;
|
||||||
|
|
||||||
|
m_frameCounter ++;
|
||||||
|
|
||||||
|
endTime = this->getRenderTime ();
|
||||||
|
|
||||||
|
// ensure the frame time is correct to not overrun FPS
|
||||||
|
if ((endTime - startTime) < minimumTime)
|
||||||
|
usleep ((minimumTime - (endTime - startTime)) * CLOCKS_PER_SEC);
|
||||||
|
}
|
||||||
|
|
||||||
|
Detectors::CFullScreenDetector& CWaylandOpenGLDriver::getFullscreenDetector ()
|
||||||
|
{
|
||||||
|
return this->m_fullscreenDetector;
|
||||||
|
}
|
||||||
|
|
||||||
|
Output::COutput& CWaylandOpenGLDriver::getOutput ()
|
||||||
|
{
|
||||||
|
return this->m_output;
|
||||||
|
}
|
||||||
|
|
||||||
|
float CWaylandOpenGLDriver::getRenderTime () const
|
||||||
|
{
|
||||||
|
return (float)std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::high_resolution_clock::now() - renderStart).count() / 1000000.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CWaylandOpenGLDriver::closeRequested ()
|
||||||
|
{
|
||||||
|
return this->m_requestedExit;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CWaylandOpenGLDriver::resizeWindow (glm::ivec2 size)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void CWaylandOpenGLDriver::resizeWindow (glm::ivec4 sizeandpos)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void CWaylandOpenGLDriver::showWindow ()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void CWaylandOpenGLDriver::hideWindow ()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::ivec2 CWaylandOpenGLDriver::getFramebufferSize () const
|
||||||
|
{
|
||||||
|
return glm::ivec2{0, 0};
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t CWaylandOpenGLDriver::getFrameCounter () const
|
||||||
|
{
|
||||||
|
return m_frameCounter;
|
||||||
|
}
|
||||||
|
|
||||||
|
CWaylandOpenGLDriver::SEGLContext* CWaylandOpenGLDriver::getEGLContext ()
|
||||||
|
{
|
||||||
|
return &this->m_eglContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* CWaylandOpenGLDriver::getProcAddress (const char* name) const
|
||||||
|
{
|
||||||
|
return reinterpret_cast <void*> (eglGetProcAddress (name));
|
||||||
|
}
|
||||||
|
|
||||||
|
CWaylandOpenGLDriver::SWaylandContext* CWaylandOpenGLDriver::getWaylandContext ()
|
||||||
|
{
|
||||||
|
return &this->m_waylandContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
Output::CWaylandOutputViewport* CWaylandOpenGLDriver::surfaceToViewport(wl_surface* surface)
|
||||||
|
{
|
||||||
|
for (auto& o : m_screens)
|
||||||
|
{
|
||||||
|
if (o->surface == surface)
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
114
src/WallpaperEngine/Render/Drivers/CWaylandOpenGLDriver.h
Normal file
114
src/WallpaperEngine/Render/Drivers/CWaylandOpenGLDriver.h
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
#ifdef ENABLE_WAYLAND
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <wayland-client.h>
|
||||||
|
#include <wayland-cursor.h>
|
||||||
|
#include <wayland-egl.h>
|
||||||
|
#include <EGL/egl.h>
|
||||||
|
#include <EGL/eglext.h>
|
||||||
|
#include <GL/glew.h>
|
||||||
|
|
||||||
|
#include "WallpaperEngine/Render/Drivers/CVideoDriver.h"
|
||||||
|
#include "WallpaperEngine/Application/CApplicationContext.h"
|
||||||
|
#include "WallpaperEngine/Render/Drivers/Detectors/CWaylandFullScreenDetector.h"
|
||||||
|
#include "WallpaperEngine/Render/Drivers/Output/CWaylandOutputViewport.h"
|
||||||
|
#include "WallpaperEngine/Render/Drivers/Output/CWaylandOutput.h"
|
||||||
|
|
||||||
|
namespace WallpaperEngine::Application
|
||||||
|
{
|
||||||
|
class CApplicationContext;
|
||||||
|
class CWallpaperApplication;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace WallpaperEngine::Input::Drivers
|
||||||
|
{
|
||||||
|
class CWaylandMouseInput;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct zwlr_layer_shell_v1;
|
||||||
|
struct zwlr_layer_surface_v1;
|
||||||
|
|
||||||
|
namespace WallpaperEngine::Render::Drivers
|
||||||
|
{
|
||||||
|
using namespace WallpaperEngine::Application;
|
||||||
|
using namespace WallpaperEngine::Input::Drivers;
|
||||||
|
class CWaylandOpenGLDriver;
|
||||||
|
|
||||||
|
namespace Output
|
||||||
|
{
|
||||||
|
class CWaylandOutputViewport;
|
||||||
|
class CWaylandOutput;
|
||||||
|
}
|
||||||
|
|
||||||
|
class CWaylandOpenGLDriver : public CVideoDriver
|
||||||
|
{
|
||||||
|
friend class Output::CWaylandOutput;
|
||||||
|
friend class CWaylandMouseInput;
|
||||||
|
public:
|
||||||
|
struct SEGLContext
|
||||||
|
{
|
||||||
|
EGLDisplay display = nullptr;
|
||||||
|
EGLConfig config = nullptr;
|
||||||
|
EGLContext context = nullptr;
|
||||||
|
PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC eglCreatePlatformWindowSurfaceEXT = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SWaylandContext
|
||||||
|
{
|
||||||
|
wl_display* display = nullptr;
|
||||||
|
wl_registry* registry = nullptr;
|
||||||
|
wl_compositor* compositor = nullptr;
|
||||||
|
wl_shm* shm = nullptr;
|
||||||
|
zwlr_layer_shell_v1* layerShell = nullptr;
|
||||||
|
wl_seat* seat = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
explicit CWaylandOpenGLDriver (CApplicationContext& context, CWallpaperApplication& app);
|
||||||
|
~CWaylandOpenGLDriver();
|
||||||
|
|
||||||
|
[[nodiscard]] Detectors::CFullScreenDetector& getFullscreenDetector () override;
|
||||||
|
[[nodiscard]] Output::COutput& getOutput () override;
|
||||||
|
float getRenderTime () const override;
|
||||||
|
bool closeRequested () override;
|
||||||
|
void resizeWindow (glm::ivec2 size) override;
|
||||||
|
void resizeWindow (glm::ivec4 sizeandpos) override;
|
||||||
|
void showWindow () override;
|
||||||
|
void hideWindow () override;
|
||||||
|
glm::ivec2 getFramebufferSize () const override;
|
||||||
|
uint32_t getFrameCounter () const override;
|
||||||
|
void dispatchEventQueue() override;
|
||||||
|
[[nodiscard]] void* getProcAddress (const char* name) const override;
|
||||||
|
|
||||||
|
void onLayerClose(Output::CWaylandOutputViewport*);
|
||||||
|
Output::CWaylandOutputViewport* surfaceToViewport(wl_surface*);
|
||||||
|
|
||||||
|
Output::CWaylandOutputViewport* viewportInFocus = nullptr;
|
||||||
|
|
||||||
|
[[nodiscard]] SEGLContext* getEGLContext ();
|
||||||
|
[[nodiscard]] SWaylandContext* getWaylandContext ();
|
||||||
|
|
||||||
|
|
||||||
|
/** List of available screens */
|
||||||
|
std::vector <Output::CWaylandOutputViewport*> m_screens;
|
||||||
|
|
||||||
|
private:
|
||||||
|
/** Fullscreen detection used by this driver */
|
||||||
|
Detectors::CWaylandFullScreenDetector m_fullscreenDetector;
|
||||||
|
/** The output used by the driver */
|
||||||
|
Output::CWaylandOutput m_output;
|
||||||
|
/** The EGL context in use */
|
||||||
|
SEGLContext m_eglContext;
|
||||||
|
/** The Wayland context in use */
|
||||||
|
SWaylandContext m_waylandContext;
|
||||||
|
mutable bool m_requestedExit;
|
||||||
|
|
||||||
|
void initEGL();
|
||||||
|
void finishEGL();
|
||||||
|
|
||||||
|
uint32_t m_frameCounter;
|
||||||
|
CApplicationContext& m_context;
|
||||||
|
|
||||||
|
std::chrono::high_resolution_clock::time_point renderStart = std::chrono::high_resolution_clock::now();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
#endif /* ENABLE_WAYLAND */
|
@ -1,10 +1,13 @@
|
|||||||
#include "CX11OpenGLDriver.h"
|
#include "CX11OpenGLDriver.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
#include "WallpaperEngine/Render/Drivers/Output/CGLFWWindowOutput.h"
|
||||||
#include <FreeImage.h>
|
#include <FreeImage.h>
|
||||||
|
|
||||||
#define GLFW_EXPOSE_NATIVE_X11
|
#define GLFW_EXPOSE_NATIVE_X11
|
||||||
#include <GLFW/glfw3native.h>
|
#include <GLFW/glfw3native.h>
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
using namespace WallpaperEngine::Render::Drivers;
|
using namespace WallpaperEngine::Render::Drivers;
|
||||||
|
|
||||||
void CustomGLFWErrorHandler (int errorCode, const char* reason)
|
void CustomGLFWErrorHandler (int errorCode, const char* reason)
|
||||||
@ -12,8 +15,11 @@ void CustomGLFWErrorHandler (int errorCode, const char* reason)
|
|||||||
sLog.error ("GLFW error ", errorCode, ": ", reason);
|
sLog.error ("GLFW error ", errorCode, ": ", reason);
|
||||||
}
|
}
|
||||||
|
|
||||||
CX11OpenGLDriver::CX11OpenGLDriver (const char* windowTitle, CApplicationContext& context) :
|
CX11OpenGLDriver::CX11OpenGLDriver (const char* windowTitle, CApplicationContext& context, CWallpaperApplication& app) :
|
||||||
m_frameCounter (0)
|
m_frameCounter (0),
|
||||||
|
m_fullscreenDetector (context, *this),
|
||||||
|
m_context (context),
|
||||||
|
CVideoDriver (app)
|
||||||
{
|
{
|
||||||
glfwSetErrorCallback (CustomGLFWErrorHandler);
|
glfwSetErrorCallback (CustomGLFWErrorHandler);
|
||||||
|
|
||||||
@ -60,6 +66,17 @@ CX11OpenGLDriver::CX11OpenGLDriver (const char* windowTitle, CApplicationContext
|
|||||||
|
|
||||||
// initialize free image
|
// initialize free image
|
||||||
FreeImage_Initialise (TRUE);
|
FreeImage_Initialise (TRUE);
|
||||||
|
|
||||||
|
// setup output
|
||||||
|
if (context.settings.render.mode == CApplicationContext::EXPLICIT_WINDOW ||
|
||||||
|
context.settings.render.mode == CApplicationContext::NORMAL_WINDOW)
|
||||||
|
{
|
||||||
|
m_output = new WallpaperEngine::Render::Drivers::Output::CGLFWWindowOutput (context, *this);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_output = new WallpaperEngine::Render::Drivers::Output::CX11Output (context, *this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CX11OpenGLDriver::~CX11OpenGLDriver ()
|
CX11OpenGLDriver::~CX11OpenGLDriver ()
|
||||||
@ -68,9 +85,14 @@ CX11OpenGLDriver::~CX11OpenGLDriver ()
|
|||||||
FreeImage_DeInitialise();
|
FreeImage_DeInitialise();
|
||||||
}
|
}
|
||||||
|
|
||||||
void* CX11OpenGLDriver::getWindowHandle () const
|
Detectors::CFullScreenDetector& CX11OpenGLDriver::getFullscreenDetector ()
|
||||||
{
|
{
|
||||||
return reinterpret_cast <void*> (glfwGetX11Window (this->m_window));
|
return this->m_fullscreenDetector;
|
||||||
|
}
|
||||||
|
|
||||||
|
Output::COutput& CX11OpenGLDriver::getOutput ()
|
||||||
|
{
|
||||||
|
return *this->m_output;
|
||||||
}
|
}
|
||||||
|
|
||||||
float CX11OpenGLDriver::getRenderTime () const
|
float CX11OpenGLDriver::getRenderTime () const
|
||||||
@ -113,19 +135,50 @@ glm::ivec2 CX11OpenGLDriver::getFramebufferSize () const
|
|||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CX11OpenGLDriver::swapBuffers ()
|
uint32_t CX11OpenGLDriver::getFrameCounter () const
|
||||||
{
|
{
|
||||||
|
return this->m_frameCounter;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CX11OpenGLDriver::dispatchEventQueue()
|
||||||
|
{
|
||||||
|
static float startTime, endTime, minimumTime = 1.0f / this->m_context.settings.render.maximumFPS;
|
||||||
|
// get the start time of the frame
|
||||||
|
startTime = this->getRenderTime ();
|
||||||
|
// clear the screen
|
||||||
|
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
|
for (const auto& viewport : this->m_output->getViewports ())
|
||||||
|
this->getApp ().update (viewport.second);
|
||||||
|
|
||||||
|
// read the full texture into the image
|
||||||
|
if (this->m_output->haveImageBuffer ())
|
||||||
|
glReadPixels (
|
||||||
|
0, 0, this->m_output->getFullWidth (), this->m_output->getFullHeight (), GL_BGRA, GL_UNSIGNED_BYTE,
|
||||||
|
this->m_output->getImageBuffer ()
|
||||||
|
);
|
||||||
|
|
||||||
|
// TODO: FRAMETIME CONTROL SHOULD GO BACK TO THE CWALLPAPAERAPPLICATION ONCE ACTUAL PARTICLES ARE IMPLEMENTED
|
||||||
|
// TODO: AS THOSE, MORE THAN LIKELY, WILL REQUIRE OF A DIFFERENT PROCESSING RATE
|
||||||
|
// update the output with the given image
|
||||||
|
this->m_output->updateRender ();
|
||||||
// do buffer swapping first
|
// do buffer swapping first
|
||||||
glfwSwapBuffers (this->m_window);
|
glfwSwapBuffers (this->m_window);
|
||||||
// poll for events
|
// poll for events
|
||||||
glfwPollEvents ();
|
glfwPollEvents ();
|
||||||
// increase frame counter
|
// increase frame counter
|
||||||
this->m_frameCounter ++;
|
this->m_frameCounter ++;
|
||||||
|
// get the end time of the frame
|
||||||
|
endTime = this->getRenderTime ();
|
||||||
|
|
||||||
|
// ensure the frame time is correct to not overrun FPS
|
||||||
|
if ((endTime - startTime) < minimumTime)
|
||||||
|
usleep ((minimumTime - (endTime - startTime)) * CLOCKS_PER_SEC);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t CX11OpenGLDriver::getFrameCounter () const
|
void* CX11OpenGLDriver::getProcAddress (const char* name) const
|
||||||
{
|
{
|
||||||
return this->m_frameCounter;
|
return reinterpret_cast <void*> (glfwGetProcAddress (name));
|
||||||
}
|
}
|
||||||
|
|
||||||
GLFWwindow* CX11OpenGLDriver::getWindow ()
|
GLFWwindow* CX11OpenGLDriver::getWindow ()
|
||||||
|
@ -4,10 +4,15 @@
|
|||||||
#include <GLFW/glfw3.h>
|
#include <GLFW/glfw3.h>
|
||||||
#include "WallpaperEngine/Render/Drivers/CVideoDriver.h"
|
#include "WallpaperEngine/Render/Drivers/CVideoDriver.h"
|
||||||
#include "WallpaperEngine/Application/CApplicationContext.h"
|
#include "WallpaperEngine/Application/CApplicationContext.h"
|
||||||
|
#include "WallpaperEngine/Render/Drivers/Detectors/CFullScreenDetector.h"
|
||||||
|
#include "WallpaperEngine/Render/Drivers/Detectors/CX11FullScreenDetector.h"
|
||||||
|
#include "WallpaperEngine/Render/Drivers/Output/CX11Output.h"
|
||||||
|
#include "WallpaperEngine/Application/CWallpaperApplication.h"
|
||||||
|
|
||||||
namespace WallpaperEngine::Application
|
namespace WallpaperEngine::Application
|
||||||
{
|
{
|
||||||
class CApplicationContext;
|
class CApplicationContext;
|
||||||
|
class CWallpaperApplication;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace WallpaperEngine::Render::Drivers
|
namespace WallpaperEngine::Render::Drivers
|
||||||
@ -17,23 +22,28 @@ namespace WallpaperEngine::Render::Drivers
|
|||||||
class CX11OpenGLDriver : public CVideoDriver
|
class CX11OpenGLDriver : public CVideoDriver
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit CX11OpenGLDriver (const char* windowTitle, CApplicationContext& context);
|
explicit CX11OpenGLDriver (const char* windowTitle, CApplicationContext& context, CWallpaperApplication& app);
|
||||||
~CX11OpenGLDriver();
|
~CX11OpenGLDriver();
|
||||||
|
|
||||||
void* getWindowHandle () const;
|
[[nodiscard]] Detectors::CFullScreenDetector& getFullscreenDetector () override;
|
||||||
float getRenderTime () const override;
|
[[nodiscard]] Output::COutput& getOutput () override;
|
||||||
|
[[nodiscard]] float getRenderTime () const override;
|
||||||
bool closeRequested () override;
|
bool closeRequested () override;
|
||||||
void resizeWindow (glm::ivec2 size) override;
|
void resizeWindow (glm::ivec2 size) override;
|
||||||
void resizeWindow (glm::ivec4 sizeandpos) override;
|
void resizeWindow (glm::ivec4 sizeandpos) override;
|
||||||
void showWindow () override;
|
void showWindow () override;
|
||||||
void hideWindow () override;
|
void hideWindow () override;
|
||||||
glm::ivec2 getFramebufferSize () const override;
|
[[nodiscard]] glm::ivec2 getFramebufferSize () const override;
|
||||||
void swapBuffers () override;
|
[[nodiscard]] uint32_t getFrameCounter () const override;
|
||||||
uint32_t getFrameCounter () const override;
|
void dispatchEventQueue() override;
|
||||||
|
[[nodiscard]] void* getProcAddress (const char* name) const override;
|
||||||
|
|
||||||
GLFWwindow* getWindow ();
|
GLFWwindow* getWindow ();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Detectors::CX11FullScreenDetector m_fullscreenDetector;
|
||||||
|
CApplicationContext& m_context;
|
||||||
|
Output::COutput* m_output;
|
||||||
GLFWwindow* m_window;
|
GLFWwindow* m_window;
|
||||||
uint32_t m_frameCounter;
|
uint32_t m_frameCounter;
|
||||||
};
|
};
|
||||||
|
@ -0,0 +1,20 @@
|
|||||||
|
#include "CWaylandFullScreenDetector.h"
|
||||||
|
|
||||||
|
using namespace WallpaperEngine::Render::Drivers::Detectors;
|
||||||
|
|
||||||
|
CWaylandFullScreenDetector::CWaylandFullScreenDetector (Application::CApplicationContext& appContext, CWaylandOpenGLDriver& driver) :
|
||||||
|
CFullScreenDetector (appContext)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
CWaylandFullScreenDetector::~CWaylandFullScreenDetector () {
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CWaylandFullScreenDetector::anythingFullscreen () const {
|
||||||
|
return false; // todo
|
||||||
|
}
|
||||||
|
|
||||||
|
void CWaylandFullScreenDetector::reset () {
|
||||||
|
;
|
||||||
|
}
|
@ -0,0 +1,28 @@
|
|||||||
|
#ifdef ENABLE_WAYLAND
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <glm/vec4.hpp>
|
||||||
|
|
||||||
|
#include "CFullScreenDetector.h"
|
||||||
|
#include "WallpaperEngine/Render/Drivers/CVideoDriver.h"
|
||||||
|
|
||||||
|
namespace WallpaperEngine::Render::Drivers
|
||||||
|
{
|
||||||
|
class CWaylandOpenGLDriver;
|
||||||
|
|
||||||
|
namespace Detectors
|
||||||
|
{
|
||||||
|
class CWaylandFullScreenDetector : public CFullScreenDetector
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CWaylandFullScreenDetector (Application::CApplicationContext& appContext, CWaylandOpenGLDriver& driver);
|
||||||
|
~CWaylandFullScreenDetector ();
|
||||||
|
|
||||||
|
[[nodiscard]] bool anythingFullscreen () const override;
|
||||||
|
void reset () override;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* ENABLE_WAYLAND */
|
@ -4,6 +4,7 @@
|
|||||||
#include <X11/Xlib.h>
|
#include <X11/Xlib.h>
|
||||||
#include <X11/extensions/Xrandr.h>
|
#include <X11/extensions/Xrandr.h>
|
||||||
|
|
||||||
|
#include "WallpaperEngine/Render/Drivers/CX11OpenGLDriver.h"
|
||||||
|
|
||||||
namespace WallpaperEngine::Render::Drivers::Detectors
|
namespace WallpaperEngine::Render::Drivers::Detectors
|
||||||
{
|
{
|
||||||
@ -31,7 +32,7 @@ namespace WallpaperEngine::Render::Drivers::Detectors
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
CX11FullScreenDetector::CX11FullScreenDetector (Application::CApplicationContext& appContext, CVideoDriver& driver) :
|
CX11FullScreenDetector::CX11FullScreenDetector (Application::CApplicationContext& appContext, CX11OpenGLDriver& driver) :
|
||||||
CFullScreenDetector (appContext),
|
CFullScreenDetector (appContext),
|
||||||
m_driver (driver)
|
m_driver (driver)
|
||||||
{
|
{
|
||||||
@ -67,7 +68,7 @@ namespace WallpaperEngine::Render::Drivers::Detectors
|
|||||||
if (!XQueryTree (this->m_display, this->m_root, &_, &_, &children, &nchildren))
|
if (!XQueryTree (this->m_display, this->m_root, &_, &_, &children, &nchildren))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
auto ourWindow = reinterpret_cast <Window> (this->m_driver.getWindowHandle ());
|
auto ourWindow = reinterpret_cast <Window> (this->m_driver.getWindow ());
|
||||||
Window parentWindow;
|
Window parentWindow;
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -5,34 +5,37 @@
|
|||||||
#include <glm/vec4.hpp>
|
#include <glm/vec4.hpp>
|
||||||
|
|
||||||
#include "CFullScreenDetector.h"
|
#include "CFullScreenDetector.h"
|
||||||
#include "WallpaperEngine/Render/Drivers/CVideoDriver.h"
|
|
||||||
|
|
||||||
#include <X11/Xlib.h>
|
#include <X11/Xlib.h>
|
||||||
|
|
||||||
namespace WallpaperEngine::Render::Drivers::Detectors
|
namespace WallpaperEngine::Render::Drivers
|
||||||
{
|
{
|
||||||
class CX11FullScreenDetector : public CFullScreenDetector
|
class CX11OpenGLDriver;
|
||||||
|
|
||||||
|
namespace Detectors
|
||||||
{
|
{
|
||||||
public:
|
class CX11FullScreenDetector : public CFullScreenDetector
|
||||||
CX11FullScreenDetector (Application::CApplicationContext& appContext, CVideoDriver& driver);
|
|
||||||
~CX11FullScreenDetector ();
|
|
||||||
|
|
||||||
[[nodiscard]] bool anythingFullscreen () const override;
|
|
||||||
void reset () override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void initialize ();
|
|
||||||
void stop ();
|
|
||||||
|
|
||||||
struct ScreenInfo
|
|
||||||
{
|
{
|
||||||
glm::ivec4 viewport;
|
public:
|
||||||
std::string name;
|
CX11FullScreenDetector (Application::CApplicationContext& appContext, CX11OpenGLDriver& driver);
|
||||||
};
|
~CX11FullScreenDetector ();
|
||||||
|
|
||||||
Display* m_display;
|
[[nodiscard]] bool anythingFullscreen () const override;
|
||||||
Window m_root;
|
void reset () override;
|
||||||
std::vector <ScreenInfo> m_screens;
|
|
||||||
CVideoDriver& m_driver;
|
private:
|
||||||
};
|
void initialize ();
|
||||||
|
void stop ();
|
||||||
|
|
||||||
|
struct ScreenInfo
|
||||||
|
{
|
||||||
|
glm::ivec4 viewport;
|
||||||
|
std::string name;
|
||||||
|
};
|
||||||
|
|
||||||
|
Display* m_display;
|
||||||
|
Window m_root;
|
||||||
|
std::vector <ScreenInfo> m_screens;
|
||||||
|
CX11OpenGLDriver& m_driver;
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,6 +1,7 @@
|
|||||||
#include <GLFW/glfw3.h>
|
#include <GLFW/glfw3.h>
|
||||||
#include "CGLFWWindowOutput.h"
|
#include "CGLFWWindowOutput.h"
|
||||||
#include "WallpaperEngine/Logging/CLog.h"
|
#include "WallpaperEngine/Logging/CLog.h"
|
||||||
|
#include "CX11OutputViewport.h"
|
||||||
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
@ -8,9 +9,8 @@
|
|||||||
|
|
||||||
using namespace WallpaperEngine::Render::Drivers::Output;
|
using namespace WallpaperEngine::Render::Drivers::Output;
|
||||||
|
|
||||||
CGLFWWindowOutput::CGLFWWindowOutput (CApplicationContext& context, CVideoDriver& driver, Detectors::CFullScreenDetector& detector) :
|
CGLFWWindowOutput::CGLFWWindowOutput (CApplicationContext& context, CVideoDriver& driver) :
|
||||||
COutput (context, detector),
|
COutput (context, driver)
|
||||||
m_driver (driver)
|
|
||||||
{
|
{
|
||||||
if (
|
if (
|
||||||
this->m_context.settings.render.mode != Application::CApplicationContext::NORMAL_WINDOW &&
|
this->m_context.settings.render.mode != Application::CApplicationContext::NORMAL_WINDOW &&
|
||||||
@ -34,7 +34,7 @@ CGLFWWindowOutput::CGLFWWindowOutput (CApplicationContext& context, CVideoDriver
|
|||||||
}
|
}
|
||||||
|
|
||||||
// register the default viewport
|
// register the default viewport
|
||||||
this->m_viewports ["default"] = {{0, 0, this->m_fullWidth, this->m_fullHeight}, "default"};
|
this->m_viewports ["default"] = new CX11OutputViewport {{0, 0, this->m_fullWidth, this->m_fullHeight}, "default"};
|
||||||
}
|
}
|
||||||
|
|
||||||
void CGLFWWindowOutput::repositionWindow ()
|
void CGLFWWindowOutput::repositionWindow ()
|
||||||
@ -78,9 +78,9 @@ void CGLFWWindowOutput::updateRender () const
|
|||||||
this->m_fullHeight = this->m_driver.getFramebufferSize ().y;
|
this->m_fullHeight = this->m_driver.getFramebufferSize ().y;
|
||||||
|
|
||||||
// update the default viewport
|
// update the default viewport
|
||||||
this->m_viewports ["default"] = {{0, 0, this->m_fullWidth, this->m_fullHeight}, "default"};
|
this->m_viewports ["default"]->viewport = {0, 0, this->m_fullWidth, this->m_fullHeight};
|
||||||
|
|
||||||
// check for fullscreen windows and wait until there's none fullscreen
|
// check for fullscreen windows and wait until there's none fullscreen
|
||||||
while (this->m_detector.anythingFullscreen () && this->m_context.state.general.keepRunning)
|
while (this->m_driver.getFullscreenDetector ().anythingFullscreen () && this->m_context.state.general.keepRunning)
|
||||||
usleep (FULLSCREEN_CHECK_WAIT_TIME);
|
usleep (FULLSCREEN_CHECK_WAIT_TIME);
|
||||||
}
|
}
|
@ -8,7 +8,7 @@ namespace WallpaperEngine::Render::Drivers::Output
|
|||||||
class CGLFWWindowOutput : public COutput
|
class CGLFWWindowOutput : public COutput
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CGLFWWindowOutput (CApplicationContext& context, CVideoDriver& driver, Detectors::CFullScreenDetector& detector);
|
CGLFWWindowOutput (CApplicationContext& context, CVideoDriver& driver);
|
||||||
|
|
||||||
void reset () override;
|
void reset () override;
|
||||||
bool renderVFlip () const override;
|
bool renderVFlip () const override;
|
||||||
@ -19,7 +19,5 @@ namespace WallpaperEngine::Render::Drivers::Output
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
void repositionWindow ();
|
void repositionWindow ();
|
||||||
|
|
||||||
CVideoDriver& m_driver;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
@ -2,13 +2,13 @@
|
|||||||
|
|
||||||
using namespace WallpaperEngine::Render::Drivers::Output;
|
using namespace WallpaperEngine::Render::Drivers::Output;
|
||||||
|
|
||||||
COutput::COutput (CApplicationContext& context, Detectors::CFullScreenDetector& detector) :
|
COutput::COutput (CApplicationContext& context, CVideoDriver& driver) :
|
||||||
m_context (context),
|
m_context (context),
|
||||||
m_detector (detector)
|
m_driver (driver)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::map <std::string, COutput::ScreenInfo>& COutput::getViewports () const
|
const std::map <std::string, COutputViewport*>& COutput::getViewports () const
|
||||||
{
|
{
|
||||||
return this->m_viewports;
|
return this->m_viewports;
|
||||||
}
|
}
|
||||||
|
@ -14,41 +14,42 @@ namespace WallpaperEngine::Application
|
|||||||
class CApplicationContext;
|
class CApplicationContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace WallpaperEngine::Render::Drivers::Detectors
|
namespace WallpaperEngine::Render::Drivers
|
||||||
{
|
{
|
||||||
class CFullScreenDetector;
|
class CVideoDriver;
|
||||||
}
|
|
||||||
|
|
||||||
namespace WallpaperEngine::Render::Drivers::Output
|
namespace Detectors
|
||||||
{
|
|
||||||
class COutput
|
|
||||||
{
|
{
|
||||||
public:
|
class CFullScreenDetector;
|
||||||
COutput (CApplicationContext& context, Detectors::CFullScreenDetector& detector);
|
}
|
||||||
|
|
||||||
virtual void reset () = 0;
|
namespace Output
|
||||||
|
{
|
||||||
|
class COutputViewport;
|
||||||
|
|
||||||
int getFullWidth () const;
|
class COutput
|
||||||
int getFullHeight () const;
|
|
||||||
|
|
||||||
struct ScreenInfo
|
|
||||||
{
|
{
|
||||||
glm::ivec4 viewport;
|
public:
|
||||||
std::string name;
|
COutput (CApplicationContext& context, CVideoDriver& driver);
|
||||||
|
|
||||||
|
virtual void reset () = 0;
|
||||||
|
|
||||||
|
int getFullWidth () const;
|
||||||
|
int getFullHeight () const;
|
||||||
|
|
||||||
|
virtual bool renderVFlip () const = 0;
|
||||||
|
virtual bool renderMultiple () const = 0;
|
||||||
|
virtual bool haveImageBuffer () const = 0;
|
||||||
|
const std::map <std::string, COutputViewport*>& getViewports () const;
|
||||||
|
virtual void* getImageBuffer () const = 0;
|
||||||
|
virtual void updateRender () const = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
mutable int m_fullWidth;
|
||||||
|
mutable int m_fullHeight;
|
||||||
|
mutable std::map <std::string, COutputViewport*> m_viewports;
|
||||||
|
CApplicationContext& m_context;
|
||||||
|
CVideoDriver& m_driver;
|
||||||
};
|
};
|
||||||
|
}
|
||||||
virtual bool renderVFlip () const = 0;
|
|
||||||
virtual bool renderMultiple () const = 0;
|
|
||||||
virtual bool haveImageBuffer () const = 0;
|
|
||||||
const std::map <std::string, ScreenInfo>& getViewports () const;
|
|
||||||
virtual void* getImageBuffer () const = 0;
|
|
||||||
virtual void updateRender () const = 0;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
mutable int m_fullWidth;
|
|
||||||
mutable int m_fullHeight;
|
|
||||||
mutable std::map <std::string, ScreenInfo> m_viewports;
|
|
||||||
CApplicationContext& m_context;
|
|
||||||
Detectors::CFullScreenDetector& m_detector;
|
|
||||||
};
|
|
||||||
}
|
}
|
@ -0,0 +1,16 @@
|
|||||||
|
#include "COutputViewport.h"
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
using namespace WallpaperEngine::Render::Drivers::Output;
|
||||||
|
|
||||||
|
COutputViewport::COutputViewport (glm::ivec4 viewport, std::string name, bool single) :
|
||||||
|
viewport (viewport),
|
||||||
|
name (std::move(name)),
|
||||||
|
single (single)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
COutputViewport::~COutputViewport ()
|
||||||
|
{
|
||||||
|
}
|
30
src/WallpaperEngine/Render/Drivers/Output/COutputViewport.h
Normal file
30
src/WallpaperEngine/Render/Drivers/Output/COutputViewport.h
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <glm/vec4.hpp>
|
||||||
|
|
||||||
|
namespace WallpaperEngine::Render::Drivers::Output
|
||||||
|
{
|
||||||
|
class COutputViewport
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
COutputViewport (glm::ivec4 viewport, std::string name, bool single = false);
|
||||||
|
virtual ~COutputViewport ();
|
||||||
|
|
||||||
|
glm::ivec4 viewport;
|
||||||
|
std::string name;
|
||||||
|
|
||||||
|
/** Whether this viewport is single in the framebuffer or shares space with more viewports */
|
||||||
|
bool single;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Activates output's context for drawing
|
||||||
|
*/
|
||||||
|
virtual void makeCurrent () = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Swaps buffers to present data on the viewport
|
||||||
|
*/
|
||||||
|
virtual void swapOutput () = 0;
|
||||||
|
};
|
||||||
|
}
|
66
src/WallpaperEngine/Render/Drivers/Output/CWaylandOutput.cpp
Normal file
66
src/WallpaperEngine/Render/Drivers/Output/CWaylandOutput.cpp
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
#include "common.h"
|
||||||
|
#include "CWaylandOutput.h"
|
||||||
|
#include "../CWaylandOpenGLDriver.h"
|
||||||
|
#include "WallpaperEngine/Application/CWallpaperApplication.h"
|
||||||
|
|
||||||
|
using namespace WallpaperEngine::Render::Drivers::Output;
|
||||||
|
|
||||||
|
CWaylandOutput::CWaylandOutput (CApplicationContext& context, CWaylandOpenGLDriver& driver) :
|
||||||
|
COutput (context, driver)
|
||||||
|
{
|
||||||
|
updateViewports();
|
||||||
|
}
|
||||||
|
|
||||||
|
CWaylandOutput::~CWaylandOutput ()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void CWaylandOutput::updateViewports()
|
||||||
|
{
|
||||||
|
m_viewports.clear();
|
||||||
|
const auto PDRIVER = (CWaylandOpenGLDriver*)&m_driver;
|
||||||
|
glm::ivec2 fullw = {0,0};
|
||||||
|
for (auto& o : PDRIVER->m_screens)
|
||||||
|
{
|
||||||
|
if (!o->layerSurface)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
m_viewports[o->name] = o;
|
||||||
|
|
||||||
|
fullw = fullw + glm::ivec2{o->size.x * o->scale, 0};
|
||||||
|
if (o->size.y > fullw.y)
|
||||||
|
fullw.y = o->size.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_fullWidth = fullw.x;
|
||||||
|
m_fullHeight = fullw.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CWaylandOutput::reset ()
|
||||||
|
{
|
||||||
|
updateViewports();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CWaylandOutput::renderVFlip () const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CWaylandOutput::renderMultiple () const
|
||||||
|
{
|
||||||
|
return false; // todo
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CWaylandOutput::haveImageBuffer () const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* CWaylandOutput::getImageBuffer () const
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CWaylandOutput::updateRender () const
|
||||||
|
{
|
||||||
|
}
|
36
src/WallpaperEngine/Render/Drivers/Output/CWaylandOutput.h
Normal file
36
src/WallpaperEngine/Render/Drivers/Output/CWaylandOutput.h
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
#ifdef ENABLE_WAYLAND
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <string>
|
||||||
|
#include <glm/vec4.hpp>
|
||||||
|
|
||||||
|
#include "WallpaperEngine/Render/Drivers/CVideoDriver.h"
|
||||||
|
#include "COutput.h"
|
||||||
|
|
||||||
|
namespace WallpaperEngine::Render::Drivers
|
||||||
|
{
|
||||||
|
class CWaylandOpenGLDriver;
|
||||||
|
|
||||||
|
namespace Output
|
||||||
|
{
|
||||||
|
class CWaylandOutput : public COutput
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CWaylandOutput (CApplicationContext& context, CWaylandOpenGLDriver& driver);
|
||||||
|
~CWaylandOutput ();
|
||||||
|
|
||||||
|
void reset () override;
|
||||||
|
|
||||||
|
bool renderVFlip () const override;
|
||||||
|
bool renderMultiple () const override;
|
||||||
|
bool haveImageBuffer () const override;
|
||||||
|
void* getImageBuffer () const override;
|
||||||
|
void updateRender () const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void updateViewports();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* ENABLE_WAYLAND */
|
@ -0,0 +1,224 @@
|
|||||||
|
#include "WallpaperEngine/Application/CWallpaperApplication.h"
|
||||||
|
#include "CWaylandOutputViewport.h"
|
||||||
|
#include "WallpaperEngine/Logging/CLog.h"
|
||||||
|
|
||||||
|
#define class _class
|
||||||
|
#define namespace _namespace
|
||||||
|
#define static
|
||||||
|
extern "C" {
|
||||||
|
#include "xdg-shell-protocol.h"
|
||||||
|
#include "wlr-layer-shell-unstable-v1-protocol.h"
|
||||||
|
}
|
||||||
|
#undef class
|
||||||
|
#undef namespace
|
||||||
|
#undef static
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
using namespace WallpaperEngine::Render::Drivers;
|
||||||
|
using namespace WallpaperEngine::Render::Drivers::Output;
|
||||||
|
|
||||||
|
static void handleLSConfigure(void *data, zwlr_layer_surface_v1 *surface, uint32_t serial, uint32_t w, uint32_t h)
|
||||||
|
{
|
||||||
|
const auto viewport = static_cast <CWaylandOutputViewport*> (data);
|
||||||
|
viewport->size = {w, h};
|
||||||
|
viewport->viewport = {0, 0, viewport->size.x * viewport->scale, viewport->size.y * viewport->scale};
|
||||||
|
viewport->resize ();
|
||||||
|
|
||||||
|
zwlr_layer_surface_v1_ack_configure(surface, serial);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void handleLSClosed(void *data, zwlr_layer_surface_v1 *surface)
|
||||||
|
{
|
||||||
|
const auto viewport = static_cast <CWaylandOutputViewport*> (data);
|
||||||
|
|
||||||
|
viewport->getDriver ()->onLayerClose(viewport);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void geometry(
|
||||||
|
void* data, wl_output* output, int32_t x, int32_t y, int32_t width_mm, int32_t height_mm, int32_t subpixel,
|
||||||
|
const char* make, const char* model, int32_t transform
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// ignored
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mode(void* data, wl_output* output, uint32_t flags, int32_t width, int32_t height, int32_t refresh)
|
||||||
|
{
|
||||||
|
const auto viewport = static_cast <CWaylandOutputViewport*> (data);
|
||||||
|
|
||||||
|
// update viewport size too
|
||||||
|
viewport->size = {width, height};
|
||||||
|
viewport->viewport = {0, 0, viewport->size.x * viewport->scale, viewport->size.y * viewport->scale};
|
||||||
|
|
||||||
|
if (viewport->layerSurface)
|
||||||
|
viewport->resize ();
|
||||||
|
|
||||||
|
if (viewport->initialized)
|
||||||
|
viewport->getDriver ()->getOutput ().reset ();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void done(void* data, wl_output* wl_output)
|
||||||
|
{
|
||||||
|
static_cast <CWaylandOutputViewport*> (data)->initialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void scale(void* data, wl_output* wl_output, int32_t scale)
|
||||||
|
{
|
||||||
|
const auto viewport = static_cast <CWaylandOutputViewport*> (data);
|
||||||
|
|
||||||
|
viewport->scale = scale;
|
||||||
|
|
||||||
|
if (viewport->layerSurface)
|
||||||
|
viewport->resize ();
|
||||||
|
|
||||||
|
if (viewport->initialized)
|
||||||
|
viewport->getDriver ()->getOutput ().reset ();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void name(void* data, wl_output* wl_output, const char* name)
|
||||||
|
{
|
||||||
|
const auto viewport = static_cast <CWaylandOutputViewport*> (data);
|
||||||
|
|
||||||
|
if (name)
|
||||||
|
viewport->name = name;
|
||||||
|
|
||||||
|
// ensure the output is updated with the new name too
|
||||||
|
viewport->getDriver ()->getOutput ().reset ();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void description(void* data, wl_output* wl_output, const char* description)
|
||||||
|
{
|
||||||
|
// ignored
|
||||||
|
}
|
||||||
|
|
||||||
|
static void surfaceFrameCallback(void *data, struct wl_callback *cb, uint32_t time)
|
||||||
|
{
|
||||||
|
const auto viewport = static_cast <CWaylandOutputViewport*> (data);
|
||||||
|
|
||||||
|
wl_callback_destroy(cb);
|
||||||
|
|
||||||
|
viewport->frameCallback = nullptr;
|
||||||
|
viewport->rendering = true;
|
||||||
|
viewport->getDriver ()->getApp ().update (viewport);
|
||||||
|
viewport->rendering = false;
|
||||||
|
|
||||||
|
float renderTime = viewport->getDriver ()->getRenderTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct wl_callback_listener frameListener =
|
||||||
|
{
|
||||||
|
.done = surfaceFrameCallback
|
||||||
|
};
|
||||||
|
|
||||||
|
const wl_output_listener outputListener =
|
||||||
|
{
|
||||||
|
.geometry = geometry,
|
||||||
|
.mode = mode,
|
||||||
|
.done = done,
|
||||||
|
.scale = scale,
|
||||||
|
.name = name,
|
||||||
|
.description = description
|
||||||
|
};
|
||||||
|
|
||||||
|
const struct zwlr_layer_surface_v1_listener layerSurfaceListener = {
|
||||||
|
.configure = handleLSConfigure,
|
||||||
|
.closed = handleLSClosed,
|
||||||
|
};
|
||||||
|
|
||||||
|
CWaylandOutputViewport::CWaylandOutputViewport (CWaylandOpenGLDriver* driver, uint32_t waylandName, struct wl_registry *registry) :
|
||||||
|
m_driver (driver),
|
||||||
|
waylandName (waylandName),
|
||||||
|
COutputViewport ({0,0,0,0}, "", true)
|
||||||
|
{
|
||||||
|
// setup output listener
|
||||||
|
this->output = (wl_output*) wl_registry_bind(registry, waylandName, &wl_output_interface, 4);
|
||||||
|
this->name = "";
|
||||||
|
this->size = {0, 0};
|
||||||
|
wl_output_add_listener(output, &outputListener, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CWaylandOutputViewport::setupLS ()
|
||||||
|
{
|
||||||
|
surface = wl_compositor_create_surface(m_driver->getWaylandContext()->compositor);
|
||||||
|
layerSurface = zwlr_layer_shell_v1_get_layer_surface(m_driver->getWaylandContext()->layerShell, surface, output, ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND, "linux-wallpaperengine");
|
||||||
|
|
||||||
|
if (!layerSurface)
|
||||||
|
sLog.exception("Failed to get a layer surface");
|
||||||
|
|
||||||
|
wl_region* region = wl_compositor_create_region(m_driver->getWaylandContext()->compositor);
|
||||||
|
wl_region_add(region, 0, 0, INT32_MAX, INT32_MAX);
|
||||||
|
|
||||||
|
zwlr_layer_surface_v1_set_size(layerSurface, 0, 0);
|
||||||
|
zwlr_layer_surface_v1_set_anchor(layerSurface, ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT | ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP | ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM);
|
||||||
|
zwlr_layer_surface_v1_set_keyboard_interactivity(layerSurface, false);
|
||||||
|
zwlr_layer_surface_v1_add_listener(layerSurface, &layerSurfaceListener, this);
|
||||||
|
zwlr_layer_surface_v1_set_exclusive_zone(layerSurface, -1);
|
||||||
|
wl_surface_set_input_region(surface, region);
|
||||||
|
wl_surface_commit(surface);
|
||||||
|
wl_display_roundtrip(m_driver->getWaylandContext()->display);
|
||||||
|
|
||||||
|
eglWindow = wl_egl_window_create(surface, size.x * scale, size.y * scale);
|
||||||
|
eglSurface = m_driver->getEGLContext ()->eglCreatePlatformWindowSurfaceEXT(m_driver->getEGLContext ()->display, m_driver->getEGLContext ()->config, eglWindow, nullptr);
|
||||||
|
wl_surface_commit(surface);
|
||||||
|
wl_display_roundtrip(m_driver->getWaylandContext()->display);
|
||||||
|
wl_display_flush(m_driver->getWaylandContext()->display);
|
||||||
|
|
||||||
|
static const auto XCURSORSIZE = getenv("XCURSOR_SIZE") ? std::stoi(getenv("XCURSOR_SIZE")) : 24;
|
||||||
|
const auto PRCURSORTHEME = wl_cursor_theme_load(getenv("XCURSOR_THEME"), XCURSORSIZE * scale, m_driver->getWaylandContext()->shm);
|
||||||
|
|
||||||
|
if (!PRCURSORTHEME)
|
||||||
|
sLog.exception("Failed to get a cursor theme");
|
||||||
|
|
||||||
|
pointer = wl_cursor_theme_get_cursor(PRCURSORTHEME, "left_ptr");
|
||||||
|
cursorSurface = wl_compositor_create_surface(m_driver->getWaylandContext()->compositor);
|
||||||
|
|
||||||
|
if (!cursorSurface)
|
||||||
|
sLog.exception("Failed to get a cursor surface");
|
||||||
|
|
||||||
|
if (eglMakeCurrent(m_driver->getEGLContext ()->display, eglSurface, eglSurface, m_driver->getEGLContext ()->context) == EGL_FALSE)
|
||||||
|
sLog.exception("Failed to make egl current");
|
||||||
|
|
||||||
|
this->m_driver->getOutput ().reset ();
|
||||||
|
}
|
||||||
|
|
||||||
|
CWaylandOpenGLDriver* CWaylandOutputViewport::getDriver ()
|
||||||
|
{
|
||||||
|
return this->m_driver;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CWaylandOutputViewport::makeCurrent ()
|
||||||
|
{
|
||||||
|
EGLBoolean result = eglMakeCurrent (
|
||||||
|
m_driver->getEGLContext ()->display,
|
||||||
|
eglSurface,
|
||||||
|
eglSurface,
|
||||||
|
m_driver->getEGLContext ()->context
|
||||||
|
);
|
||||||
|
|
||||||
|
if (result == EGL_FALSE)
|
||||||
|
sLog.error ("Couldn't make egl current");
|
||||||
|
}
|
||||||
|
|
||||||
|
void CWaylandOutputViewport::swapOutput ()
|
||||||
|
{
|
||||||
|
this->callbackInitialized = true;
|
||||||
|
|
||||||
|
this->makeCurrent ();
|
||||||
|
frameCallback = wl_surface_frame (surface);
|
||||||
|
wl_callback_add_listener (frameCallback, &frameListener, this);
|
||||||
|
eglSwapBuffers (m_driver->getEGLContext ()->display, this->eglSurface);
|
||||||
|
wl_surface_set_buffer_scale(surface, scale);
|
||||||
|
wl_surface_damage_buffer(surface, 0, 0, INT32_MAX, INT32_MAX);
|
||||||
|
wl_surface_commit(surface);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CWaylandOutputViewport::resize ()
|
||||||
|
{
|
||||||
|
if (!this->eglWindow)
|
||||||
|
return;
|
||||||
|
|
||||||
|
wl_egl_window_resize(this->eglWindow, this->size.x * this->scale, this->size.y * this->scale, 0, 0);
|
||||||
|
|
||||||
|
this->getDriver ()->getOutput().reset();
|
||||||
|
}
|
@ -0,0 +1,75 @@
|
|||||||
|
#ifdef ENABLE_WAYLAND
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <wayland-client.h>
|
||||||
|
#include <wayland-cursor.h>
|
||||||
|
#include <wayland-egl.h>
|
||||||
|
#include <EGL/egl.h>
|
||||||
|
#include <EGL/eglext.h>
|
||||||
|
#include <GL/glew.h>
|
||||||
|
|
||||||
|
#include <glm/vec2.hpp>
|
||||||
|
#include "COutputViewport.h"
|
||||||
|
#include "../CWaylandOpenGLDriver.h"
|
||||||
|
|
||||||
|
struct zwlr_layer_shell_v1;
|
||||||
|
struct zwlr_layer_surface_v1;
|
||||||
|
|
||||||
|
namespace WallpaperEngine::Render::Drivers
|
||||||
|
{
|
||||||
|
class CWaylandOpenGLDriver;
|
||||||
|
|
||||||
|
namespace Output
|
||||||
|
{
|
||||||
|
class COutputViewport;
|
||||||
|
|
||||||
|
class CWaylandOutputViewport : public COutputViewport
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CWaylandOutputViewport (CWaylandOpenGLDriver* driver, uint32_t waylandName, struct wl_registry *registry);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The wayland driver
|
||||||
|
*/
|
||||||
|
CWaylandOpenGLDriver* getDriver ();
|
||||||
|
|
||||||
|
wl_output* output;
|
||||||
|
glm::ivec2 size;
|
||||||
|
uint32_t waylandName;
|
||||||
|
int scale = 1;
|
||||||
|
bool initialized = false;
|
||||||
|
bool rendering = false;
|
||||||
|
|
||||||
|
wl_egl_window* eglWindow = nullptr;
|
||||||
|
EGLSurface eglSurface = nullptr;
|
||||||
|
wl_surface* surface = nullptr;
|
||||||
|
zwlr_layer_surface_v1* layerSurface = nullptr;
|
||||||
|
wl_callback* frameCallback = nullptr;
|
||||||
|
glm::dvec2 mousePos = {0, 0};
|
||||||
|
wl_cursor* pointer = nullptr;
|
||||||
|
wl_surface* cursorSurface = nullptr;
|
||||||
|
bool callbackInitialized = false;
|
||||||
|
|
||||||
|
void setupLS ();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Activates output's context for drawing
|
||||||
|
*/
|
||||||
|
void makeCurrent () override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Swaps buffers to present data on the viewport
|
||||||
|
*/
|
||||||
|
void swapOutput () override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the viewport size
|
||||||
|
*/
|
||||||
|
void resize ();
|
||||||
|
|
||||||
|
private:
|
||||||
|
CWaylandOpenGLDriver* m_driver;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* ENABLE_WAYLAND */
|
@ -1,5 +1,6 @@
|
|||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "CX11Output.h"
|
#include "CX11Output.h"
|
||||||
|
#include "CX11OutputViewport.h"
|
||||||
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <X11/Xlib.h>
|
#include <X11/Xlib.h>
|
||||||
@ -34,9 +35,8 @@ int CustomXIOErrorHandler (Display* dsp)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
CX11Output::CX11Output (CApplicationContext& context, CVideoDriver& driver, Detectors::CFullScreenDetector& detector) :
|
CX11Output::CX11Output (CApplicationContext& context, CVideoDriver& driver) :
|
||||||
COutput (context, detector),
|
COutput (context, driver)
|
||||||
m_driver (driver)
|
|
||||||
{
|
{
|
||||||
// do not use previous handler, it might stop the app under weird circumstances
|
// do not use previous handler, it might stop the app under weird circumstances
|
||||||
XSetErrorHandler (CustomXErrorHandler);
|
XSetErrorHandler (CustomXErrorHandler);
|
||||||
@ -57,11 +57,17 @@ void CX11Output::reset ()
|
|||||||
// re-load screen info
|
// re-load screen info
|
||||||
this->loadScreenInfo ();
|
this->loadScreenInfo ();
|
||||||
// do the same for the detector
|
// do the same for the detector
|
||||||
this->m_detector.reset ();
|
this->m_driver.getFullscreenDetector ().reset ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CX11Output::free ()
|
void CX11Output::free ()
|
||||||
{
|
{
|
||||||
|
// go through all the viewports and free them
|
||||||
|
for(const auto& cur : this->m_viewports)
|
||||||
|
delete cur.second;
|
||||||
|
|
||||||
|
this->m_viewports.clear ();
|
||||||
|
|
||||||
// free all the resources we've got
|
// free all the resources we've got
|
||||||
XDestroyImage (this->m_image);
|
XDestroyImage (this->m_image);
|
||||||
XFreeGC (this->m_display, this->m_gc);
|
XFreeGC (this->m_display, this->m_gc);
|
||||||
@ -132,6 +138,7 @@ void CX11Output::loadScreenInfo ()
|
|||||||
|
|
||||||
// add the screen to the list of screens
|
// add the screen to the list of screens
|
||||||
this->m_screens.push_back (
|
this->m_screens.push_back (
|
||||||
|
new CX11OutputViewport
|
||||||
{
|
{
|
||||||
{crtc->x, crtc->y, crtc->width, crtc->height},
|
{crtc->x, crtc->y, crtc->width, crtc->height},
|
||||||
info->name
|
info->name
|
||||||
@ -144,6 +151,7 @@ void CX11Output::loadScreenInfo ()
|
|||||||
sLog.out ("Found requested screen: ", info->name, " -> ", crtc->x, "x", crtc->y, ":", crtc->width, "x", crtc->height);
|
sLog.out ("Found requested screen: ", info->name, " -> ", crtc->x, "x", crtc->y, ":", crtc->width, "x", crtc->height);
|
||||||
|
|
||||||
this->m_viewports[info->name] =
|
this->m_viewports[info->name] =
|
||||||
|
new CX11OutputViewport
|
||||||
{
|
{
|
||||||
{crtc->x, crtc->y, crtc->width, crtc->height},
|
{crtc->x, crtc->y, crtc->width, crtc->height},
|
||||||
info->name
|
info->name
|
||||||
@ -187,6 +195,6 @@ void CX11Output::updateRender () const
|
|||||||
XFlush(this->m_display);
|
XFlush(this->m_display);
|
||||||
|
|
||||||
// check for fullscreen windows and wait until there's none fullscreen
|
// check for fullscreen windows and wait until there's none fullscreen
|
||||||
while (this->m_detector.anythingFullscreen () && this->m_context.state.general.keepRunning)
|
while (this->m_driver.getFullscreenDetector ().anythingFullscreen () && this->m_context.state.general.keepRunning)
|
||||||
usleep (FULLSCREEN_CHECK_WAIT_TIME);
|
usleep (FULLSCREEN_CHECK_WAIT_TIME);
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@ namespace WallpaperEngine::Render::Drivers::Output
|
|||||||
class CX11Output : public COutput
|
class CX11Output : public COutput
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CX11Output (CApplicationContext& context, CVideoDriver& driver, Detectors::CFullScreenDetector& detector);
|
CX11Output (CApplicationContext& context, CVideoDriver& driver);
|
||||||
~CX11Output ();
|
~CX11Output ();
|
||||||
|
|
||||||
void reset () override;
|
void reset () override;
|
||||||
@ -35,7 +35,6 @@ namespace WallpaperEngine::Render::Drivers::Output
|
|||||||
GC m_gc;
|
GC m_gc;
|
||||||
char* m_imageData;
|
char* m_imageData;
|
||||||
XImage* m_image;
|
XImage* m_image;
|
||||||
CVideoDriver& m_driver;
|
std::vector <COutputViewport*> m_screens;
|
||||||
std::vector <ScreenInfo> m_screens;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
#include "CX11OutputViewport.h"
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
using namespace WallpaperEngine::Render::Drivers::Output;
|
||||||
|
|
||||||
|
CX11OutputViewport::CX11OutputViewport (glm::ivec4 viewport, std::string name) :
|
||||||
|
COutputViewport (viewport, std::move(name))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void CX11OutputViewport::makeCurrent ()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void CX11OutputViewport::swapOutput ()
|
||||||
|
{
|
||||||
|
}
|
@ -0,0 +1,15 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "COutputViewport.h"
|
||||||
|
|
||||||
|
namespace WallpaperEngine::Render::Drivers::Output
|
||||||
|
{
|
||||||
|
class CX11OutputViewport : public COutputViewport
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CX11OutputViewport (glm::ivec4 viewport, std::string name);
|
||||||
|
|
||||||
|
void makeCurrent () override;
|
||||||
|
void swapOutput () override;
|
||||||
|
};
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user