diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml
index f268342..1cd2dac 100644
--- a/.github/workflows/cmake.yml
+++ b/.github/workflows/cmake.yml
@@ -34,3 +34,27 @@ jobs:
- name: Build
# Build your program with the given configuration
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}}
diff --git a/.gitignore b/.gitignore
index a2705b0..cbaea3c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,8 @@
cmake-build-debug*
-.idea
\ No newline at end of file
+.idea
+build/
+.vscode/
+
+*-protocol.o
+*-protocol.c
+*-protocol.h
\ No newline at end of file
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 221e7f8..20c58c2 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -41,8 +41,55 @@ include_directories(
${FREEIMAGE_INCLUDE_DIR}
${PULSEAUDIO_INCLUDE_DIR}
src
+ ${CMAKE_SOURCE_DIR}
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(
linux-wallpaperengine
main.cpp
@@ -105,6 +152,8 @@ add_executable(
src/WallpaperEngine/Input/CInputContext.h
src/WallpaperEngine/Input/CMouseInput.cpp
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.cpp
@@ -136,6 +185,10 @@ add_executable(
src/WallpaperEngine/Render/Drivers/Output/CX11Output.h
src/WallpaperEngine/Render/Drivers/Output/CGLFWWindowOutput.cpp
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.cpp
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.h
+
+ ${WAYLAND_SOURCES}
)
target_link_libraries(linux-wallpaperengine
@@ -286,6 +341,14 @@ target_link_libraries(linux-wallpaperengine
${PULSEAUDIO_LIBRARY}
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)
set(CMAKE_REQUIRED_LIBRARIES ${X11_LIBRARIES})
diff --git a/protocols/wlr-layer-shell-unstable-v1.xml b/protocols/wlr-layer-shell-unstable-v1.xml
new file mode 100644
index 0000000..f29eb87
--- /dev/null
+++ b/protocols/wlr-layer-shell-unstable-v1.xml
@@ -0,0 +1,285 @@
+
+
+
+ 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.
+
+
+
+
+ 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.
+
+
+
+
+ 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.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 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.
+
+
+
+
+
+
+
+
+
+
+
+ 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.
+
+
+
+
+ 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.
+
+
+
+
+
+
+
+ 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.
+
+
+
+
+
+
+ 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.
+
+
+
+
+
+
+ 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.
+
+
+
+
+
+
+
+
+
+ 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.
+
+
+
+
+
+
+ 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.
+
+
+
+
+
+
+ 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.
+
+
+
+
+
+
+ This request destroys the layer surface.
+
+
+
+
+
+ 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.
+
+
+
+
+
+
+
+
+ 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.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/External/Android/fft.cpp b/src/External/Android/fft.cpp
index 93122ef..6406889 100644
--- a/src/External/Android/fft.cpp
+++ b/src/External/Android/fft.cpp
@@ -26,8 +26,8 @@ namespace External::Android
* 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.
*/
-#include
-#include
+#include
+#include
#ifdef __arm__
#include
#endif
diff --git a/src/WallpaperEngine/Application/CApplicationContext.cpp b/src/WallpaperEngine/Application/CApplicationContext.cpp
index e22b497..857a995 100644
--- a/src/WallpaperEngine/Application/CApplicationContext.cpp
+++ b/src/WallpaperEngine/Application/CApplicationContext.cpp
@@ -12,22 +12,22 @@
using namespace WallpaperEngine::Application;
struct option long_options[] = {
- { "screen-root", required_argument, nullptr, 'r' },
- { "bg", required_argument, nullptr, 'b' },
- { "window", required_argument, nullptr, 'w' },
- { "pkg", required_argument, nullptr, 'p' },
- { "dir", required_argument, nullptr, 'd' },
- { "silent", no_argument, nullptr, 's' },
- { "volume", required_argument, nullptr, 'v' },
- { "help", no_argument, nullptr, 'h' },
- { "fps", required_argument, nullptr, 'f' },
- { "assets-dir", required_argument, nullptr, 'a' },
- { "screenshot", required_argument, nullptr, 'c' },
- { "list-properties", no_argument, nullptr, 'l' },
- { "set-property", required_argument, nullptr, 'o' },
- { "noautomute", no_argument, nullptr, 'm' },
- { "no-fullscreen-pause", no_argument,nullptr, 'n' },
- { nullptr, 0, nullptr, 0 }
+ { "screen-root", required_argument, nullptr, 'r' },
+ { "bg", required_argument, nullptr, 'b' },
+ { "window", required_argument, nullptr, 'w' },
+ { "pkg", required_argument, nullptr, 'p' },
+ { "dir", required_argument, nullptr, 'd' },
+ { "silent", no_argument, nullptr, 's' },
+ { "volume", required_argument, nullptr, 'v' },
+ { "help", no_argument, nullptr, 'h' },
+ { "fps", required_argument, nullptr, 'f' },
+ { "assets-dir", required_argument, nullptr, 'a' },
+ { "screenshot", required_argument, nullptr, 'c' },
+ { "list-properties", no_argument, nullptr, 'l' },
+ { "set-property", required_argument, nullptr, 'o' },
+ { "noautomute", no_argument, nullptr, 'm' },
+ { "no-fullscreen-pause", no_argument, nullptr, 'n' },
+ { nullptr, 0, nullptr, 0 }
};
std::string stringPathFixes (const std::string& s)
@@ -124,13 +124,13 @@ CApplicationContext::CApplicationContext (int argc, char* argv[])
if (this->settings.render.mode == EXPLICIT_WINDOW)
sLog.exception ("Cannot run in both background and window mode");
- this->settings.render.mode = X11_BACKGROUND;
+ this->settings.render.mode = DESKTOP_BACKGROUND;
lastScreen = optarg;
this->settings.general.screenBackgrounds[lastScreen] = "";
break;
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");
if (optarg != nullptr)
diff --git a/src/WallpaperEngine/Application/CApplicationContext.h b/src/WallpaperEngine/Application/CApplicationContext.h
index 700a0db..5d37fbf 100644
--- a/src/WallpaperEngine/Application/CApplicationContext.h
+++ b/src/WallpaperEngine/Application/CApplicationContext.h
@@ -25,8 +25,8 @@ namespace WallpaperEngine::Application
{
/** Default window mode */
NORMAL_WINDOW = 0,
- /** Draw to X11 background */
- X11_BACKGROUND = 1,
+ /** Draw to the window server desktop */
+ DESKTOP_BACKGROUND = 1,
/** Explicit window mode with specified geometry */
EXPLICIT_WINDOW = 2,
};
diff --git a/src/WallpaperEngine/Application/CWallpaperApplication.cpp b/src/WallpaperEngine/Application/CWallpaperApplication.cpp
index 5d52a3a..2096677 100644
--- a/src/WallpaperEngine/Application/CWallpaperApplication.cpp
+++ b/src/WallpaperEngine/Application/CWallpaperApplication.cpp
@@ -3,17 +3,15 @@
#include "Steam/FileSystem/FileSystem.h"
#include "WallpaperEngine/Assets/CDirectory.h"
#include "WallpaperEngine/Assets/CVirtualContainer.h"
-#include "WallpaperEngine/Audio/Drivers/CSDLAudioDriver.h"
#include "WallpaperEngine/Core/CVideo.h"
#include "WallpaperEngine/Logging/CLog.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/Render/Drivers/Detectors/CX11FullScreenDetector.h"
#include "WallpaperEngine/Audio/Drivers/Detectors/CPulseAudioPlayingDetector.h"
+#include "WallpaperEngine/Input/Drivers/CGLFWMouseInput.h"
-#include
+#include "WallpaperEngine/Input/Drivers/CWaylandMouseInput.h"
+#include "WallpaperEngine/Render/Drivers/CWaylandOpenGLDriver.h"
float g_Time;
float g_TimeLast;
@@ -29,6 +27,15 @@ namespace WallpaperEngine::Application
this->setupProperties ();
}
+ CWallpaperApplication::~CWallpaperApplication ()
+ {
+ delete context;
+ delete videoDriver;
+ delete audioContext;
+ delete audioDriver;
+ delete inputContext;
+ }
+
void CWallpaperApplication::setupContainer (CCombinedContainer& container, const std::string& bg) const
{
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
-
- int width = context.getOutput ()->getFullWidth ();
- 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);
+ int width = context.getOutput ().getFullWidth ();
+ int height = context.getOutput ().getFullHeight ();
// build the output file with FreeImage
- FIBITMAP* bitmap = FreeImage_Allocate (width, height, 24);
+ static FIBITMAP* bitmap = FreeImage_Allocate (width, height, 24);
RGBQUAD color;
+ int xoffset = 0;
- // now get access to the pixels
- for (int y = height; y > 0; y--)
+ for (const auto& viewport : context.getOutput ().getViewports ())
{
- for (int x = 0; x < width; x++)
- {
- color.rgbRed = *pixel++;
- color.rgbGreen = *pixel++;
- color.rgbBlue = *pixel++;
+ // activate opengl context so we can read from the framebuffer
+ viewport.second->makeCurrent ();
+ // make room for storing the pixel of this viewport
+ uint8_t* buffer = new uint8_t[viewport.second->viewport.z * viewport.second->viewport.w * sizeof (uint8_t) * 3];
+ uint8_t* pixel = buffer;
- // set the pixel in the destination
- FreeImage_SetPixelColor (bitmap, x, y, &color);
+ // read the viewport data into the pixel buffer
+ 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
FreeImage_Save (format, bitmap, filename.c_str (), 0);
- // free all the used memory
- delete[] buffer;
-
FreeImage_Unload (bitmap);
}
void CWallpaperApplication::show ()
{
- // initialize OpenGL driver
- WallpaperEngine::Render::Drivers::CX11OpenGLDriver videoDriver ("wallpaperengine", this->m_context);
- // initialize the input subsystem
- WallpaperEngine::Input::CInputContext inputContext (videoDriver);
- // output requested
- WallpaperEngine::Render::Drivers::Output::COutput* output;
- // fullscreen detector is common for the different render modes
- WallpaperEngine::Render::Drivers::Detectors::CX11FullScreenDetector fullscreenDetector (this->m_context, videoDriver);
+#ifdef ENABLE_WAYLAND
+ const bool WAYLAND_DISPLAY = getenv ("WAYLAND_DISPLAY");
+
+ // setup the right video driver based on the environment and the startup mode requested
+ if (WAYLAND_DISPLAY && this->m_context.settings.render.mode == CApplicationContext::DESKTOP_BACKGROUND)
+ {
+ auto waylandDriver = new WallpaperEngine::Render::Drivers::CWaylandOpenGLDriver (this->m_context, *this);
+ 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
WallpaperEngine::Audio::Drivers::Recorders::CPulseAudioPlaybackRecorder audioRecorder;
// 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
- WallpaperEngine::Audio::Drivers::CSDLAudioDriver audioDriver (this->m_context, audioDetector, audioRecorder);
+ audioDriver = new WallpaperEngine::Audio::Drivers::CSDLAudioDriver (this->m_context, audioDetector, audioRecorder);
// initialize audio context
- WallpaperEngine::Audio::CAudioContext audioContext (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;
- }
-
+ audioContext = new WallpaperEngine::Audio::CAudioContext (*audioDriver);
// 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
for (const auto& it : this->m_backgrounds)
- context.setWallpaper (
+ context->setWallpaper (
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
if (this->m_defaultBackground != nullptr)
- context.setDefaultWallpaper (WallpaperEngine::Render::CWallpaper::fromWallpaper (
- this->m_defaultBackground->getWallpaper (), context, audioContext
+ context->setDefaultWallpaper (WallpaperEngine::Render::CWallpaper::fromWallpaper (
+ this->m_defaultBackground->getWallpaper (), *context, *audioContext
));
- float startTime, endTime, minimumTime = 1.0f / this->m_context.settings.render.maximumFPS;
- time_t seconds;
- struct tm* timeinfo;
+ static time_t seconds;
+ static struct tm* timeinfo;
- while (!videoDriver.closeRequested () && this->m_context.state.general.keepRunning)
+ while (this->m_context.state.general.keepRunning && !videoDriver->closeRequested ())
{
// update g_Daytime
time (&seconds);
timeinfo = localtime(&seconds);
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
g_TimeLast = g_Time;
// calculate the current time value
- g_Time = videoDriver.getRenderTime ();
- // get the start time of the frame
- startTime = g_Time;
- // render the scene
- context.render ();
- // get the end time of the frame
- endTime = videoDriver.getRenderTime ();
+ g_Time = videoDriver->getRenderTime ();
+ // update audio recorder
+ audioDriver->update ();
+ // update input information
+ inputContext->update ();
+ // process driver events
+ videoDriver->dispatchEventQueue ();
- // ensure the frame time is correct to not overrun FPS
- if ((endTime - startTime) < minimumTime)
- usleep ((minimumTime - (endTime - startTime)) * CLOCKS_PER_SEC);
-
- if (!this->m_context.settings.screenshot.take || videoDriver.getFrameCounter () != 5)
+ if (!this->m_context.settings.screenshot.take || videoDriver->getFrameCounter () < 5)
continue;
- this->takeScreenshot (context, this->m_context.settings.screenshot.path, this->m_context.settings.screenshot.format);
- // disable screenshot just in case the counter overflows
+ this->takeScreenshot (*context, this->m_context.settings.screenshot.path, this->m_context.settings.screenshot.format);
this->m_context.settings.screenshot.take = false;
}
@@ -358,6 +367,12 @@ namespace WallpaperEngine::Application
SDL_Quit ();
}
+ void CWallpaperApplication::update(Render::Drivers::Output::COutputViewport* viewport)
+ {
+ // render the scene
+ context->render (viewport);
+ }
+
void CWallpaperApplication::signal (int signal)
{
this->m_context.state.general.keepRunning = false;
diff --git a/src/WallpaperEngine/Application/CWallpaperApplication.h b/src/WallpaperEngine/Application/CWallpaperApplication.h
index 959f595..70ffacf 100644
--- a/src/WallpaperEngine/Application/CWallpaperApplication.h
+++ b/src/WallpaperEngine/Application/CWallpaperApplication.h
@@ -9,6 +9,24 @@
#include "WallpaperEngine/Render/CWallpaper.h"
#include "WallpaperEngine/Render/CRenderContext.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
{
@@ -21,6 +39,7 @@ namespace WallpaperEngine::Application
{
public:
explicit CWallpaperApplication (CApplicationContext& context);
+ ~CWallpaperApplication ();
/**
* Shows the application until it's closed
@@ -44,6 +63,14 @@ namespace WallpaperEngine::Application
* @return The current application context
*/
[[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:
/**
@@ -89,5 +116,11 @@ namespace WallpaperEngine::Application
CApplicationContext& m_context;
/** Maps screens to backgrounds */
std::map m_backgrounds;
+
+ WallpaperEngine::Render::Drivers::CVideoDriver* videoDriver;
+ WallpaperEngine::Input::CInputContext* inputContext;
+ WallpaperEngine::Audio::Drivers::CSDLAudioDriver* audioDriver;
+ WallpaperEngine::Render::CRenderContext* context;
+ WallpaperEngine::Audio::CAudioContext* audioContext;
};
}
diff --git a/src/WallpaperEngine/Assets/CFileEntry.h b/src/WallpaperEngine/Assets/CFileEntry.h
index bf2ab9e..e73112a 100644
--- a/src/WallpaperEngine/Assets/CFileEntry.h
+++ b/src/WallpaperEngine/Assets/CFileEntry.h
@@ -1,5 +1,7 @@
#pragma once
+#include
+
namespace WallpaperEngine::Assets
{
/**
diff --git a/src/WallpaperEngine/Audio/Drivers/Detectors/CAudioPlayingDetector.cpp b/src/WallpaperEngine/Audio/Drivers/Detectors/CAudioPlayingDetector.cpp
index b02c740..ba0962a 100644
--- a/src/WallpaperEngine/Audio/Drivers/Detectors/CAudioPlayingDetector.cpp
+++ b/src/WallpaperEngine/Audio/Drivers/Detectors/CAudioPlayingDetector.cpp
@@ -4,7 +4,7 @@ namespace WallpaperEngine::Audio::Drivers::Detectors
{
CAudioPlayingDetector::CAudioPlayingDetector (
Application::CApplicationContext& appContext,
- Render::Drivers::Detectors::CFullScreenDetector& fullscreenDetector) :
+ const Render::Drivers::Detectors::CFullScreenDetector& fullscreenDetector) :
m_applicationContext (appContext),
m_fullscreenDetector (fullscreenDetector),
m_isPlaying (false)
@@ -21,7 +21,7 @@ namespace WallpaperEngine::Audio::Drivers::Detectors
return this->m_applicationContext;
}
- Render::Drivers::Detectors::CFullScreenDetector& CAudioPlayingDetector::getFullscreenDetector ()
+ const Render::Drivers::Detectors::CFullScreenDetector& CAudioPlayingDetector::getFullscreenDetector () const
{
return this->m_fullscreenDetector;
}
diff --git a/src/WallpaperEngine/Audio/Drivers/Detectors/CAudioPlayingDetector.h b/src/WallpaperEngine/Audio/Drivers/Detectors/CAudioPlayingDetector.h
index 28bfde2..cec3341 100644
--- a/src/WallpaperEngine/Audio/Drivers/Detectors/CAudioPlayingDetector.h
+++ b/src/WallpaperEngine/Audio/Drivers/Detectors/CAudioPlayingDetector.h
@@ -23,7 +23,7 @@ namespace WallpaperEngine
class CAudioPlayingDetector
{
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
@@ -48,13 +48,13 @@ namespace WallpaperEngine
/**
* @return The fullscreen detector used
*/
- [[nodiscard]] Render::Drivers::Detectors::CFullScreenDetector& getFullscreenDetector ();
+ [[nodiscard]] const Render::Drivers::Detectors::CFullScreenDetector& getFullscreenDetector () const;
private:
bool m_isPlaying;
Application::CApplicationContext& m_applicationContext;
- Render::Drivers::Detectors::CFullScreenDetector& m_fullscreenDetector;
+ const Render::Drivers::Detectors::CFullScreenDetector& m_fullscreenDetector;
};
}
}
diff --git a/src/WallpaperEngine/Audio/Drivers/Detectors/CPulseAudioPlayingDetector.cpp b/src/WallpaperEngine/Audio/Drivers/Detectors/CPulseAudioPlayingDetector.cpp
index 2e16cfe..3019e01 100644
--- a/src/WallpaperEngine/Audio/Drivers/Detectors/CPulseAudioPlayingDetector.cpp
+++ b/src/WallpaperEngine/Audio/Drivers/Detectors/CPulseAudioPlayingDetector.cpp
@@ -18,7 +18,7 @@ namespace WallpaperEngine::Audio::Drivers::Detectors
// get processid
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);
}
@@ -34,7 +34,7 @@ namespace WallpaperEngine::Audio::Drivers::Detectors
CPulseAudioPlayingDetector::CPulseAudioPlayingDetector (
Application::CApplicationContext& appContext,
- Render::Drivers::Detectors::CFullScreenDetector& fullscreenDetector) :
+ const Render::Drivers::Detectors::CFullScreenDetector& fullscreenDetector) :
CAudioPlayingDetector (appContext, fullscreenDetector),
m_mainloop (nullptr),
m_mainloopApi (nullptr),
diff --git a/src/WallpaperEngine/Audio/Drivers/Detectors/CPulseAudioPlayingDetector.h b/src/WallpaperEngine/Audio/Drivers/Detectors/CPulseAudioPlayingDetector.h
index f48a0b7..b4628c2 100644
--- a/src/WallpaperEngine/Audio/Drivers/Detectors/CPulseAudioPlayingDetector.h
+++ b/src/WallpaperEngine/Audio/Drivers/Detectors/CPulseAudioPlayingDetector.h
@@ -10,7 +10,7 @@ namespace WallpaperEngine::Audio::Drivers::Detectors
class CPulseAudioPlayingDetector : public CAudioPlayingDetector
{
public:
- explicit CPulseAudioPlayingDetector (Application::CApplicationContext& appContext, Render::Drivers::Detectors::CFullScreenDetector&);
+ explicit CPulseAudioPlayingDetector (Application::CApplicationContext& appContext, const Render::Drivers::Detectors::CFullScreenDetector&);
~CPulseAudioPlayingDetector ();
void update () override;
diff --git a/src/WallpaperEngine/Input/CInputContext.cpp b/src/WallpaperEngine/Input/CInputContext.cpp
index 8ae463f..7c3970b 100644
--- a/src/WallpaperEngine/Input/CInputContext.cpp
+++ b/src/WallpaperEngine/Input/CInputContext.cpp
@@ -1,20 +1,19 @@
#include "CInputContext.h"
-#include "WallpaperEngine/Render/Drivers/CX11OpenGLDriver.h"
using namespace WallpaperEngine::Input;
using namespace WallpaperEngine::Render::Drivers;
-CInputContext::CInputContext (CX11OpenGLDriver& videoDriver) :
- m_mouse (videoDriver.getWindow ())
+CInputContext::CInputContext (CMouseInput* mouseInput) :
+ m_mouse (mouseInput)
{
}
void CInputContext::update ()
{
- this->m_mouse.update ();
+ this->m_mouse->update ();
}
const CMouseInput& CInputContext::getMouseInput () const
{
- return this->m_mouse;
+ return *this->m_mouse;
}
\ No newline at end of file
diff --git a/src/WallpaperEngine/Input/CInputContext.h b/src/WallpaperEngine/Input/CInputContext.h
index bffc9c3..40e0394 100644
--- a/src/WallpaperEngine/Input/CInputContext.h
+++ b/src/WallpaperEngine/Input/CInputContext.h
@@ -1,11 +1,10 @@
#pragma once
-#include "WallpaperEngine/Render/Drivers/CX11OpenGLDriver.h"
#include "CMouseInput.h"
namespace WallpaperEngine::Render::Drivers
{
- class CX11OpenGLDriver;
+ class CVideoDriver;
}
namespace WallpaperEngine::Input
@@ -13,12 +12,16 @@ namespace WallpaperEngine::Input
class CInputContext
{
public:
- explicit CInputContext (Render::Drivers::CX11OpenGLDriver& videoDriver);
+ explicit CInputContext (CMouseInput* mouseInput);
+
+ /**
+ * Updates input information
+ */
void update ();
[[nodiscard]] const CMouseInput& getMouseInput () const;
private:
- CMouseInput m_mouse;
+ CMouseInput* m_mouse;
};
}
diff --git a/src/WallpaperEngine/Input/CMouseInput.cpp b/src/WallpaperEngine/Input/CMouseInput.cpp
index 458bb4d..e69de29 100644
--- a/src/WallpaperEngine/Input/CMouseInput.cpp
+++ b/src/WallpaperEngine/Input/CMouseInput.cpp
@@ -1,14 +0,0 @@
-#include
-#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);
-}
\ No newline at end of file
diff --git a/src/WallpaperEngine/Input/CMouseInput.h b/src/WallpaperEngine/Input/CMouseInput.h
index 7909081..06021f6 100644
--- a/src/WallpaperEngine/Input/CMouseInput.h
+++ b/src/WallpaperEngine/Input/CMouseInput.h
@@ -1,7 +1,6 @@
#pragma once
#include
-#include "GLFW/glfw3.h"
namespace WallpaperEngine::Input
{
@@ -11,28 +10,15 @@ namespace WallpaperEngine::Input
class CMouseInput
{
public:
- explicit CMouseInput(GLFWwindow* window);
-
/**
* Takes current mouse position and updates it
*/
- void update ();
+ virtual void update () = 0;
/**
* The virtual pointer's position
*/
- glm::dvec2 position;
-
- private:
- /**
- * The GLFW window to get mouse position from
- */
- GLFWwindow* m_window;
-
- /**
- * The current mouse position
- */
- glm::dvec2 m_mousePosition;
+ virtual glm::dvec2 position () const = 0;
};
}
diff --git a/src/WallpaperEngine/Input/Drivers/CGLFWMouseInput.cpp b/src/WallpaperEngine/Input/Drivers/CGLFWMouseInput.cpp
new file mode 100644
index 0000000..ffc8836
--- /dev/null
+++ b/src/WallpaperEngine/Input/Drivers/CGLFWMouseInput.cpp
@@ -0,0 +1,24 @@
+#include
+#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;
+}
\ No newline at end of file
diff --git a/src/WallpaperEngine/Input/Drivers/CGLFWMouseInput.h b/src/WallpaperEngine/Input/Drivers/CGLFWMouseInput.h
new file mode 100644
index 0000000..73bf9d1
--- /dev/null
+++ b/src/WallpaperEngine/Input/Drivers/CGLFWMouseInput.h
@@ -0,0 +1,42 @@
+#pragma once
+
+#include "WallpaperEngine/Input/CMouseInput.h"
+
+#include
+
+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;
+ };
+}
+
diff --git a/src/WallpaperEngine/Input/Drivers/CWaylandMouseInput.cpp b/src/WallpaperEngine/Input/Drivers/CWaylandMouseInput.cpp
new file mode 100644
index 0000000..2261996
--- /dev/null
+++ b/src/WallpaperEngine/Input/Drivers/CWaylandMouseInput.cpp
@@ -0,0 +1,21 @@
+#include
+#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};
+}
\ No newline at end of file
diff --git a/src/WallpaperEngine/Input/Drivers/CWaylandMouseInput.h b/src/WallpaperEngine/Input/Drivers/CWaylandMouseInput.h
new file mode 100644
index 0000000..dd83a61
--- /dev/null
+++ b/src/WallpaperEngine/Input/Drivers/CWaylandMouseInput.h
@@ -0,0 +1,41 @@
+#ifdef ENABLE_WAYLAND
+#pragma once
+
+#include "WallpaperEngine/Input/CMouseInput.h"
+#include "WallpaperEngine/Render/Drivers/CWaylandOpenGLDriver.h"
+
+#include
+#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 */
\ No newline at end of file
diff --git a/src/WallpaperEngine/Render/CRenderContext.cpp b/src/WallpaperEngine/Render/CRenderContext.cpp
index 22803f9..08ad438 100644
--- a/src/WallpaperEngine/Render/CRenderContext.cpp
+++ b/src/WallpaperEngine/Render/CRenderContext.cpp
@@ -10,11 +10,10 @@
namespace WallpaperEngine::Render
{
CRenderContext::CRenderContext (
- const Drivers::Output::COutput* output, Drivers::CVideoDriver& driver, Input::CInputContext& input,
+ Drivers::CVideoDriver& driver, Input::CInputContext& input,
CWallpaperApplication& app
) :
m_defaultWallpaper (nullptr),
- m_output (output),
m_driver (driver),
m_app (app),
m_input (input),
@@ -22,48 +21,30 @@ namespace WallpaperEngine::Render
{
}
- void CRenderContext::render ()
+ void CRenderContext::render (Drivers::Output::COutputViewport* viewport)
{
- bool firstFrame = true;
- bool renderFrame = true;
+ viewport->makeCurrent ();
- for (const auto& cur : this->m_output->getViewports ())
- {
#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 */
- // search the background in the viewport selection
- auto ref = this->m_wallpapers.find (cur.first);
+ // search the background in the viewport selection
+ 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
- glPopDebugGroup ();
+ glPopDebugGroup ();
#endif /* DEBUG */
- }
- // 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 ()
- );
-
- // update the output with the given image
- this->m_output->updateRender ();
- // finally swap buffers
- this->m_driver.swapBuffers ();
+ viewport->swapOutput ();
}
void CRenderContext::setDefaultWallpaper (CWallpaper* wallpaper)
@@ -91,9 +72,9 @@ namespace WallpaperEngine::Render
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)
diff --git a/src/WallpaperEngine/Render/CRenderContext.h b/src/WallpaperEngine/Render/CRenderContext.h
index 87d4b31..2ce79e1 100644
--- a/src/WallpaperEngine/Render/CRenderContext.h
+++ b/src/WallpaperEngine/Render/CRenderContext.h
@@ -9,6 +9,7 @@
#include "WallpaperEngine/Input/CMouseInput.h"
#include "WallpaperEngine/Render/Drivers/CVideoDriver.h"
#include "WallpaperEngine/Render/Drivers/Output/COutput.h"
+#include "WallpaperEngine/Render/Drivers/Output/COutputViewport.h"
namespace WallpaperEngine
{
@@ -26,6 +27,7 @@ namespace WallpaperEngine
namespace Output
{
class COutput;
+ class COutputViewport;
}
}
@@ -35,15 +37,15 @@ namespace WallpaperEngine
class CRenderContext
{
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 setWallpaper (const std::string& display, CWallpaper* wallpaper);
[[nodiscard]] Input::CInputContext& getInputContext () const;
[[nodiscard]] const CWallpaperApplication& getApp () 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);
private:
@@ -59,8 +61,6 @@ namespace WallpaperEngine
CWallpaperApplication& m_app;
/** Texture cache for the render */
CTextureCache* m_textureCache;
- /** Output driver that describes how the wallpapers are rendered */
- const Drivers::Output::COutput* m_output;
};
}
}
\ No newline at end of file
diff --git a/src/WallpaperEngine/Render/CScene.cpp b/src/WallpaperEngine/Render/CScene.cpp
index c345ede..3f8f80c 100644
--- a/src/WallpaperEngine/Render/CScene.cpp
+++ b/src/WallpaperEngine/Render/CScene.cpp
@@ -248,7 +248,7 @@ void CScene::renderFrame (glm::ivec4 viewport)
void CScene::updateMouse (glm::ivec4 viewport)
{
// 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)
// rollover the position to the last
diff --git a/src/WallpaperEngine/Render/CVideo.cpp b/src/WallpaperEngine/Render/CVideo.cpp
index d3fe4a6..8606e19 100644
--- a/src/WallpaperEngine/Render/CVideo.cpp
+++ b/src/WallpaperEngine/Render/CVideo.cpp
@@ -8,7 +8,7 @@ using namespace WallpaperEngine::Render;
void* get_proc_address (void* ctx, const char* name)
{
- return reinterpret_cast (glfwGetProcAddress (name));
+ return static_cast (ctx)->getContext ().getDriver ().getProcAddress (name);
}
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);
// 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_API_TYPE, const_cast (MPV_RENDER_API_TYPE_OPENGL)},
{MPV_RENDER_PARAM_OPENGL_INIT_PARAMS, &gl_init_params},
diff --git a/src/WallpaperEngine/Render/CWallpaper.cpp b/src/WallpaperEngine/Render/CWallpaper.cpp
index 235484f..f925020 100644
--- a/src/WallpaperEngine/Render/CWallpaper.cpp
+++ b/src/WallpaperEngine/Render/CWallpaper.cpp
@@ -211,10 +211,9 @@ void CWallpaper::setDestinationFramebuffer (GLuint 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 projectionHeight = this->getHeight ();
@@ -293,9 +292,6 @@ void CWallpaper::render (glm::ivec4 viewport, bool vflip, bool renderFrame, bool
glBindVertexArray (this->m_vaoBuffer);
- if (newFrame)
- glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-
glDisable (GL_BLEND);
glDisable (GL_DEPTH_TEST);
// do not use any shader
diff --git a/src/WallpaperEngine/Render/CWallpaper.h b/src/WallpaperEngine/Render/CWallpaper.h
index 1ba10c9..ed71611 100644
--- a/src/WallpaperEngine/Render/CWallpaper.h
+++ b/src/WallpaperEngine/Render/CWallpaper.h
@@ -37,7 +37,7 @@ namespace WallpaperEngine::Render
/**
* 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
diff --git a/src/WallpaperEngine/Render/Drivers/CVideoDriver.cpp b/src/WallpaperEngine/Render/Drivers/CVideoDriver.cpp
index 36d8178..cfb3b77 100644
--- a/src/WallpaperEngine/Render/Drivers/CVideoDriver.cpp
+++ b/src/WallpaperEngine/Render/Drivers/CVideoDriver.cpp
@@ -1,3 +1,17 @@
#include "CVideoDriver.h"
using namespace WallpaperEngine::Render::Drivers;
+
+CVideoDriver::CVideoDriver (CWallpaperApplication& app) :
+ m_app (app)
+{
+}
+
+CVideoDriver::~CVideoDriver ()
+{
+}
+
+CWallpaperApplication& CVideoDriver::getApp () const
+{
+ return this->m_app;
+}
\ No newline at end of file
diff --git a/src/WallpaperEngine/Render/Drivers/CVideoDriver.h b/src/WallpaperEngine/Render/Drivers/CVideoDriver.h
index c164b2e..f42eb02 100644
--- a/src/WallpaperEngine/Render/Drivers/CVideoDriver.h
+++ b/src/WallpaperEngine/Render/Drivers/CVideoDriver.h
@@ -2,20 +2,39 @@
#include
#include
+#include
+#include "WallpaperEngine/Render/Drivers/Output/COutput.h"
+
+namespace WallpaperEngine::Application
+{
+ class CWallpaperApplication;
+}
namespace WallpaperEngine::Render::Drivers
{
+ namespace Detectors
+ {
+ class CFullScreenDetector;
+ }
+
class CVideoDriver
{
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
*/
- virtual float getRenderTime () const = 0;
+ [[nodiscard]] virtual float getRenderTime () const = 0;
/**
* @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
*/
- virtual glm::ivec2 getFramebufferSize () const = 0;
- /**
- * Performs buffer swapping
- */
- virtual void swapBuffers () = 0;
+ [[nodiscard]] virtual glm::ivec2 getFramebufferSize () const = 0;
/**
* @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;
};
}
\ No newline at end of file
diff --git a/src/WallpaperEngine/Render/Drivers/CWaylandOpenGLDriver.cpp b/src/WallpaperEngine/Render/Drivers/CWaylandOpenGLDriver.cpp
new file mode 100644
index 0000000..e72aa9f
--- /dev/null
+++ b/src/WallpaperEngine/Render/Drivers/CWaylandOpenGLDriver.cpp
@@ -0,0 +1,401 @@
+#include "CWaylandOpenGLDriver.h"
+#include "WallpaperEngine/Application/CWallpaperApplication.h"
+
+#include
+
+#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
+#include
+
+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 (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 (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 (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::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 (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;
+}
diff --git a/src/WallpaperEngine/Render/Drivers/CWaylandOpenGLDriver.h b/src/WallpaperEngine/Render/Drivers/CWaylandOpenGLDriver.h
new file mode 100644
index 0000000..4c7e3d0
--- /dev/null
+++ b/src/WallpaperEngine/Render/Drivers/CWaylandOpenGLDriver.h
@@ -0,0 +1,114 @@
+#ifdef ENABLE_WAYLAND
+#pragma once
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#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 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 */
\ No newline at end of file
diff --git a/src/WallpaperEngine/Render/Drivers/CX11OpenGLDriver.cpp b/src/WallpaperEngine/Render/Drivers/CX11OpenGLDriver.cpp
index 28038a6..ccb979d 100644
--- a/src/WallpaperEngine/Render/Drivers/CX11OpenGLDriver.cpp
+++ b/src/WallpaperEngine/Render/Drivers/CX11OpenGLDriver.cpp
@@ -1,10 +1,13 @@
#include "CX11OpenGLDriver.h"
#include "common.h"
+#include "WallpaperEngine/Render/Drivers/Output/CGLFWWindowOutput.h"
#include
#define GLFW_EXPOSE_NATIVE_X11
#include
+#include
+
using namespace WallpaperEngine::Render::Drivers;
void CustomGLFWErrorHandler (int errorCode, const char* reason)
@@ -12,8 +15,11 @@ void CustomGLFWErrorHandler (int errorCode, const char* reason)
sLog.error ("GLFW error ", errorCode, ": ", reason);
}
-CX11OpenGLDriver::CX11OpenGLDriver (const char* windowTitle, CApplicationContext& context) :
- m_frameCounter (0)
+CX11OpenGLDriver::CX11OpenGLDriver (const char* windowTitle, CApplicationContext& context, CWallpaperApplication& app) :
+ m_frameCounter (0),
+ m_fullscreenDetector (context, *this),
+ m_context (context),
+ CVideoDriver (app)
{
glfwSetErrorCallback (CustomGLFWErrorHandler);
@@ -60,6 +66,17 @@ CX11OpenGLDriver::CX11OpenGLDriver (const char* windowTitle, CApplicationContext
// initialize free image
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 ()
@@ -68,9 +85,14 @@ CX11OpenGLDriver::~CX11OpenGLDriver ()
FreeImage_DeInitialise();
}
-void* CX11OpenGLDriver::getWindowHandle () const
+Detectors::CFullScreenDetector& CX11OpenGLDriver::getFullscreenDetector ()
{
- return reinterpret_cast (glfwGetX11Window (this->m_window));
+ return this->m_fullscreenDetector;
+}
+
+Output::COutput& CX11OpenGLDriver::getOutput ()
+{
+ return *this->m_output;
}
float CX11OpenGLDriver::getRenderTime () const
@@ -113,19 +135,50 @@ glm::ivec2 CX11OpenGLDriver::getFramebufferSize () const
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
glfwSwapBuffers (this->m_window);
// poll for events
glfwPollEvents ();
// increase frame counter
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 (glfwGetProcAddress (name));
}
GLFWwindow* CX11OpenGLDriver::getWindow ()
diff --git a/src/WallpaperEngine/Render/Drivers/CX11OpenGLDriver.h b/src/WallpaperEngine/Render/Drivers/CX11OpenGLDriver.h
index 99ca118..2249959 100644
--- a/src/WallpaperEngine/Render/Drivers/CX11OpenGLDriver.h
+++ b/src/WallpaperEngine/Render/Drivers/CX11OpenGLDriver.h
@@ -4,10 +4,15 @@
#include
#include "WallpaperEngine/Render/Drivers/CVideoDriver.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
{
class CApplicationContext;
+ class CWallpaperApplication;
}
namespace WallpaperEngine::Render::Drivers
@@ -17,23 +22,28 @@ namespace WallpaperEngine::Render::Drivers
class CX11OpenGLDriver : public CVideoDriver
{
public:
- explicit CX11OpenGLDriver (const char* windowTitle, CApplicationContext& context);
+ explicit CX11OpenGLDriver (const char* windowTitle, CApplicationContext& context, CWallpaperApplication& app);
~CX11OpenGLDriver();
- void* getWindowHandle () const;
- float getRenderTime () const override;
+ [[nodiscard]] Detectors::CFullScreenDetector& getFullscreenDetector () override;
+ [[nodiscard]] Output::COutput& getOutput () override;
+ [[nodiscard]] 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;
- void swapBuffers () override;
- uint32_t getFrameCounter () const override;
+ [[nodiscard]] glm::ivec2 getFramebufferSize () const override;
+ [[nodiscard]] uint32_t getFrameCounter () const override;
+ void dispatchEventQueue() override;
+ [[nodiscard]] void* getProcAddress (const char* name) const override;
GLFWwindow* getWindow ();
private:
+ Detectors::CX11FullScreenDetector m_fullscreenDetector;
+ CApplicationContext& m_context;
+ Output::COutput* m_output;
GLFWwindow* m_window;
uint32_t m_frameCounter;
};
diff --git a/src/WallpaperEngine/Render/Drivers/Detectors/CWaylandFullScreenDetector.cpp b/src/WallpaperEngine/Render/Drivers/Detectors/CWaylandFullScreenDetector.cpp
new file mode 100644
index 0000000..2625e91
--- /dev/null
+++ b/src/WallpaperEngine/Render/Drivers/Detectors/CWaylandFullScreenDetector.cpp
@@ -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 () {
+ ;
+}
\ No newline at end of file
diff --git a/src/WallpaperEngine/Render/Drivers/Detectors/CWaylandFullScreenDetector.h b/src/WallpaperEngine/Render/Drivers/Detectors/CWaylandFullScreenDetector.h
new file mode 100644
index 0000000..00650b0
--- /dev/null
+++ b/src/WallpaperEngine/Render/Drivers/Detectors/CWaylandFullScreenDetector.h
@@ -0,0 +1,28 @@
+#ifdef ENABLE_WAYLAND
+#pragma once
+
+#include
+#include
+#include
+
+#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 */
\ No newline at end of file
diff --git a/src/WallpaperEngine/Render/Drivers/Detectors/CX11FullScreenDetector.cpp b/src/WallpaperEngine/Render/Drivers/Detectors/CX11FullScreenDetector.cpp
index 849e368..2ce526f 100644
--- a/src/WallpaperEngine/Render/Drivers/Detectors/CX11FullScreenDetector.cpp
+++ b/src/WallpaperEngine/Render/Drivers/Detectors/CX11FullScreenDetector.cpp
@@ -4,6 +4,7 @@
#include
#include
+#include "WallpaperEngine/Render/Drivers/CX11OpenGLDriver.h"
namespace WallpaperEngine::Render::Drivers::Detectors
{
@@ -31,7 +32,7 @@ namespace WallpaperEngine::Render::Drivers::Detectors
return 0;
}
- CX11FullScreenDetector::CX11FullScreenDetector (Application::CApplicationContext& appContext, CVideoDriver& driver) :
+ CX11FullScreenDetector::CX11FullScreenDetector (Application::CApplicationContext& appContext, CX11OpenGLDriver& driver) :
CFullScreenDetector (appContext),
m_driver (driver)
{
@@ -67,7 +68,7 @@ namespace WallpaperEngine::Render::Drivers::Detectors
if (!XQueryTree (this->m_display, this->m_root, &_, &_, &children, &nchildren))
return false;
- auto ourWindow = reinterpret_cast (this->m_driver.getWindowHandle ());
+ auto ourWindow = reinterpret_cast (this->m_driver.getWindow ());
Window parentWindow;
{
diff --git a/src/WallpaperEngine/Render/Drivers/Detectors/CX11FullScreenDetector.h b/src/WallpaperEngine/Render/Drivers/Detectors/CX11FullScreenDetector.h
index 272e680..dd5b73a 100644
--- a/src/WallpaperEngine/Render/Drivers/Detectors/CX11FullScreenDetector.h
+++ b/src/WallpaperEngine/Render/Drivers/Detectors/CX11FullScreenDetector.h
@@ -5,34 +5,37 @@
#include
#include "CFullScreenDetector.h"
-#include "WallpaperEngine/Render/Drivers/CVideoDriver.h"
-
#include
-namespace WallpaperEngine::Render::Drivers::Detectors
+namespace WallpaperEngine::Render::Drivers
{
- class CX11FullScreenDetector : public CFullScreenDetector
+ class CX11OpenGLDriver;
+
+ namespace Detectors
{
- public:
- CX11FullScreenDetector (Application::CApplicationContext& appContext, CVideoDriver& driver);
- ~CX11FullScreenDetector ();
-
- [[nodiscard]] bool anythingFullscreen () const override;
- void reset () override;
-
- private:
- void initialize ();
- void stop ();
-
- struct ScreenInfo
+ class CX11FullScreenDetector : public CFullScreenDetector
{
- glm::ivec4 viewport;
- std::string name;
- };
+ public:
+ CX11FullScreenDetector (Application::CApplicationContext& appContext, CX11OpenGLDriver& driver);
+ ~CX11FullScreenDetector ();
- Display* m_display;
- Window m_root;
- std::vector m_screens;
- CVideoDriver& m_driver;
- };
+ [[nodiscard]] bool anythingFullscreen () const override;
+ void reset () override;
+
+ private:
+ void initialize ();
+ void stop ();
+
+ struct ScreenInfo
+ {
+ glm::ivec4 viewport;
+ std::string name;
+ };
+
+ Display* m_display;
+ Window m_root;
+ std::vector m_screens;
+ CX11OpenGLDriver& m_driver;
+ };
+ }
}
\ No newline at end of file
diff --git a/src/WallpaperEngine/Render/Drivers/Output/CGLFWWindowOutput.cpp b/src/WallpaperEngine/Render/Drivers/Output/CGLFWWindowOutput.cpp
index 4b10aa4..7994f4f 100644
--- a/src/WallpaperEngine/Render/Drivers/Output/CGLFWWindowOutput.cpp
+++ b/src/WallpaperEngine/Render/Drivers/Output/CGLFWWindowOutput.cpp
@@ -1,6 +1,7 @@
#include
#include "CGLFWWindowOutput.h"
#include "WallpaperEngine/Logging/CLog.h"
+#include "CX11OutputViewport.h"
#include
@@ -8,9 +9,8 @@
using namespace WallpaperEngine::Render::Drivers::Output;
-CGLFWWindowOutput::CGLFWWindowOutput (CApplicationContext& context, CVideoDriver& driver, Detectors::CFullScreenDetector& detector) :
- COutput (context, detector),
- m_driver (driver)
+CGLFWWindowOutput::CGLFWWindowOutput (CApplicationContext& context, CVideoDriver& driver) :
+ COutput (context, driver)
{
if (
this->m_context.settings.render.mode != Application::CApplicationContext::NORMAL_WINDOW &&
@@ -34,7 +34,7 @@ CGLFWWindowOutput::CGLFWWindowOutput (CApplicationContext& context, CVideoDriver
}
// 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 ()
@@ -78,9 +78,9 @@ void CGLFWWindowOutput::updateRender () const
this->m_fullHeight = this->m_driver.getFramebufferSize ().y;
// 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
- 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);
}
\ No newline at end of file
diff --git a/src/WallpaperEngine/Render/Drivers/Output/CGLFWWindowOutput.h b/src/WallpaperEngine/Render/Drivers/Output/CGLFWWindowOutput.h
index 7486cc6..099903a 100644
--- a/src/WallpaperEngine/Render/Drivers/Output/CGLFWWindowOutput.h
+++ b/src/WallpaperEngine/Render/Drivers/Output/CGLFWWindowOutput.h
@@ -8,7 +8,7 @@ namespace WallpaperEngine::Render::Drivers::Output
class CGLFWWindowOutput : public COutput
{
public:
- CGLFWWindowOutput (CApplicationContext& context, CVideoDriver& driver, Detectors::CFullScreenDetector& detector);
+ CGLFWWindowOutput (CApplicationContext& context, CVideoDriver& driver);
void reset () override;
bool renderVFlip () const override;
@@ -19,7 +19,5 @@ namespace WallpaperEngine::Render::Drivers::Output
private:
void repositionWindow ();
-
- CVideoDriver& m_driver;
};
}
\ No newline at end of file
diff --git a/src/WallpaperEngine/Render/Drivers/Output/COutput.cpp b/src/WallpaperEngine/Render/Drivers/Output/COutput.cpp
index ab3a4e7..6b514dc 100644
--- a/src/WallpaperEngine/Render/Drivers/Output/COutput.cpp
+++ b/src/WallpaperEngine/Render/Drivers/Output/COutput.cpp
@@ -2,13 +2,13 @@
using namespace WallpaperEngine::Render::Drivers::Output;
-COutput::COutput (CApplicationContext& context, Detectors::CFullScreenDetector& detector) :
+COutput::COutput (CApplicationContext& context, CVideoDriver& driver) :
m_context (context),
- m_detector (detector)
+ m_driver (driver)
{
}
-const std::map & COutput::getViewports () const
+const std::map & COutput::getViewports () const
{
return this->m_viewports;
}
diff --git a/src/WallpaperEngine/Render/Drivers/Output/COutput.h b/src/WallpaperEngine/Render/Drivers/Output/COutput.h
index 79330fd..cabf9d2 100644
--- a/src/WallpaperEngine/Render/Drivers/Output/COutput.h
+++ b/src/WallpaperEngine/Render/Drivers/Output/COutput.h
@@ -14,41 +14,42 @@ namespace WallpaperEngine::Application
class CApplicationContext;
}
-namespace WallpaperEngine::Render::Drivers::Detectors
+namespace WallpaperEngine::Render::Drivers
{
- class CFullScreenDetector;
-}
+ class CVideoDriver;
-namespace WallpaperEngine::Render::Drivers::Output
-{
- class COutput
+ namespace Detectors
{
- public:
- COutput (CApplicationContext& context, Detectors::CFullScreenDetector& detector);
+ class CFullScreenDetector;
+ }
- virtual void reset () = 0;
+ namespace Output
+ {
+ class COutputViewport;
- int getFullWidth () const;
- int getFullHeight () const;
-
- struct ScreenInfo
+ class COutput
{
- glm::ivec4 viewport;
- std::string name;
+ public:
+ 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 & getViewports () const;
+ virtual void* getImageBuffer () const = 0;
+ virtual void updateRender () const = 0;
+
+ protected:
+ mutable int m_fullWidth;
+ mutable int m_fullHeight;
+ mutable std::map 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 & getViewports () const;
- virtual void* getImageBuffer () const = 0;
- virtual void updateRender () const = 0;
-
- protected:
- mutable int m_fullWidth;
- mutable int m_fullHeight;
- mutable std::map m_viewports;
- CApplicationContext& m_context;
- Detectors::CFullScreenDetector& m_detector;
- };
+ }
}
\ No newline at end of file
diff --git a/src/WallpaperEngine/Render/Drivers/Output/COutputViewport.cpp b/src/WallpaperEngine/Render/Drivers/Output/COutputViewport.cpp
new file mode 100644
index 0000000..11abc8b
--- /dev/null
+++ b/src/WallpaperEngine/Render/Drivers/Output/COutputViewport.cpp
@@ -0,0 +1,16 @@
+#include "COutputViewport.h"
+
+#include
+
+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 ()
+{
+}
\ No newline at end of file
diff --git a/src/WallpaperEngine/Render/Drivers/Output/COutputViewport.h b/src/WallpaperEngine/Render/Drivers/Output/COutputViewport.h
new file mode 100644
index 0000000..3e5ce4a
--- /dev/null
+++ b/src/WallpaperEngine/Render/Drivers/Output/COutputViewport.h
@@ -0,0 +1,30 @@
+#pragma once
+
+#include
+#include
+
+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;
+ };
+}
diff --git a/src/WallpaperEngine/Render/Drivers/Output/CWaylandOutput.cpp b/src/WallpaperEngine/Render/Drivers/Output/CWaylandOutput.cpp
new file mode 100644
index 0000000..2a60a64
--- /dev/null
+++ b/src/WallpaperEngine/Render/Drivers/Output/CWaylandOutput.cpp
@@ -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
+{
+}
\ No newline at end of file
diff --git a/src/WallpaperEngine/Render/Drivers/Output/CWaylandOutput.h b/src/WallpaperEngine/Render/Drivers/Output/CWaylandOutput.h
new file mode 100644
index 0000000..eca4367
--- /dev/null
+++ b/src/WallpaperEngine/Render/Drivers/Output/CWaylandOutput.h
@@ -0,0 +1,36 @@
+#ifdef ENABLE_WAYLAND
+#pragma once
+
+#include