mirror of
https://github.com/Almamu/linux-wallpaperengine.git
synced 2025-07-14 05:12:25 +08:00
Added support for running multiple X11 backgrounds off the same instance
Window mode now has extra settings for setting the position and size Fixed audio not muting when --silent was used Signed-off-by: Alexis Maiquez <almamu@almamu.com>
This commit is contained in:
parent
e2d80a074c
commit
b69ce8ba57
@ -105,6 +105,12 @@ add_executable(
|
||||
src/WallpaperEngine/Render/Shaders/Compiler.h
|
||||
src/WallpaperEngine/Render/Shaders/Compiler.cpp
|
||||
|
||||
src/WallpaperEngine/Render/Drivers/Output/COutput.cpp
|
||||
src/WallpaperEngine/Render/Drivers/Output/COutput.h
|
||||
src/WallpaperEngine/Render/Drivers/Output/CX11Output.cpp
|
||||
src/WallpaperEngine/Render/Drivers/Output/CX11Output.h
|
||||
src/WallpaperEngine/Render/Drivers/Output/CWindowOutput.cpp
|
||||
src/WallpaperEngine/Render/Drivers/Output/CWindowOutput.h
|
||||
src/WallpaperEngine/Render/Drivers/COpenGLDriver.h
|
||||
src/WallpaperEngine/Render/Drivers/COpenGLDriver.cpp
|
||||
src/WallpaperEngine/Render/Drivers/CVideoDriver.h
|
||||
|
@ -14,6 +14,8 @@ using namespace WallpaperEngine::Application;
|
||||
|
||||
struct option long_options [] = {
|
||||
{"screen-root", required_argument, nullptr, 'r'},
|
||||
{"bg", required_argument, nullptr, 'b'},
|
||||
{"window", optional_argument, nullptr, 'w'},
|
||||
{"pkg", required_argument, nullptr, 'p'},
|
||||
{"dir", required_argument, nullptr, 'd'},
|
||||
{"silent", no_argument, nullptr, 's'},
|
||||
@ -52,10 +54,21 @@ CApplicationContext::CApplicationContext (int argc, char* argv[]) :
|
||||
{
|
||||
int c;
|
||||
|
||||
while ((c = getopt_long (argc, argv, "r:p:d:shf:a:", long_options, nullptr)) != -1)
|
||||
std::string lastScreen;
|
||||
|
||||
while ((c = getopt_long (argc, argv, "b:r:p:d:shf:a:w::", long_options, nullptr)) != -1)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case 'b':
|
||||
if (lastScreen.empty ())
|
||||
sLog.exception ("--bg has to go after a --screen-root argument");
|
||||
|
||||
// no need to check for previous screen being in the list, as it's the only way for this variable
|
||||
// to have any value
|
||||
this->screenSettings.insert_or_assign (lastScreen, this->validatePath (optarg));
|
||||
break;
|
||||
|
||||
case 'o':
|
||||
{
|
||||
std::string value = optarg;
|
||||
@ -77,13 +90,41 @@ CApplicationContext::CApplicationContext (int argc, char* argv[]) :
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
screens.emplace_back (optarg);
|
||||
if (this->screenSettings.find (optarg) != this->screenSettings.end ())
|
||||
sLog.exception ("Cannot specify the same screen more than once: ", optarg);
|
||||
if (this->windowMode == EXPLICIT_WINDOW)
|
||||
sLog.exception ("Cannot run in both background and window mode");
|
||||
|
||||
this->windowMode = X11_BACKGROUND;
|
||||
lastScreen = optarg;
|
||||
this->screenSettings.insert_or_assign (lastScreen, "");
|
||||
break;
|
||||
|
||||
case 'w':
|
||||
if (this->windowMode == X11_BACKGROUND)
|
||||
sLog.exception ("Cannot run in both background and window mode");
|
||||
|
||||
if (optarg != nullptr)
|
||||
{
|
||||
this->windowMode = EXPLICIT_WINDOW;
|
||||
// read window geometry
|
||||
char* pos = optarg;
|
||||
|
||||
if (pos != nullptr)
|
||||
this->windowGeometry.x = atoi (pos);
|
||||
if ((pos = strchr (pos, '.')) != nullptr)
|
||||
this->windowGeometry.y = atoi (pos + 1);
|
||||
if ((pos = strchr (pos + 1, '.')) != nullptr)
|
||||
this->windowGeometry.z = atoi (pos + 1);
|
||||
if ((pos = strchr (pos + 1, '.')) != nullptr)
|
||||
this->windowGeometry.w = atoi (pos + 1);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
case 'd':
|
||||
sLog.error ("--dir/--pkg is deprecated and not used anymore");
|
||||
this->background = stringPathFixes (optarg);
|
||||
this->background = this->validatePath (stringPathFixes (optarg));
|
||||
break;
|
||||
|
||||
case 's':
|
||||
@ -110,6 +151,10 @@ CApplicationContext::CApplicationContext (int argc, char* argv[]) :
|
||||
this->takeScreenshot = true;
|
||||
this->screenshot = stringPathFixes (optarg);
|
||||
break;
|
||||
|
||||
default:
|
||||
sLog.out ("Default on path parsing: ", optarg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -117,7 +162,7 @@ CApplicationContext::CApplicationContext (int argc, char* argv[]) :
|
||||
{
|
||||
if (optind < argc && strlen (argv [optind]) > 0)
|
||||
{
|
||||
this->background = argv [optind];
|
||||
this->background = this->validatePath (argv [optind]);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -126,17 +171,16 @@ CApplicationContext::CApplicationContext (int argc, char* argv[]) :
|
||||
}
|
||||
|
||||
// perform some extra validation on the inputs
|
||||
this->validatePath ();
|
||||
this->validateAssets ();
|
||||
this->validateScreenshot ();
|
||||
}
|
||||
|
||||
void CApplicationContext::validatePath ()
|
||||
std::string CApplicationContext::validatePath (const std::string& path)
|
||||
{
|
||||
if (this->background.find ('/') != std::string::npos)
|
||||
return;
|
||||
if (path.find ('/') == std::string::npos)
|
||||
return Steam::FileSystem::workshopDirectory (WORKSHOP_APP_ID, path);
|
||||
|
||||
this->background = Steam::FileSystem::workshopDirectory (WORKSHOP_APP_ID, this->background);
|
||||
return path;
|
||||
}
|
||||
|
||||
void CApplicationContext::validateAssets ()
|
||||
@ -191,6 +235,7 @@ void CApplicationContext::printHelp (const char* route)
|
||||
sLog.out ("\t--silent\t\t\t\t\tMutes all the sound the wallpaper might produce");
|
||||
sLog.out ("\t--volume <amount>\t\t\tSets the volume for all the sounds in the background");
|
||||
sLog.out ("\t--screen-root <screen name>\tDisplay as screen's background");
|
||||
sLog.out ("\t--window <geometry>\tRuns in window mode, geometry has to be XxYxWxH");
|
||||
sLog.out ("\t--fps <maximum-fps>\t\t\tLimits the FPS to the given number, useful to keep battery consumption low");
|
||||
sLog.out ("\t--assets-dir <path>\t\t\tFolder where the assets are stored");
|
||||
sLog.out ("\t--screenshot\t\t\t\tTakes a screenshot of the background");
|
||||
|
@ -6,6 +6,8 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <glm/vec4.hpp>
|
||||
|
||||
namespace WallpaperEngine::Application
|
||||
{
|
||||
class CApplicationContext
|
||||
@ -13,7 +15,15 @@ namespace WallpaperEngine::Application
|
||||
public:
|
||||
CApplicationContext (int argc, char* argv[]);
|
||||
|
||||
std::vector <std::string> screens;
|
||||
enum WINDOW_MODE
|
||||
{
|
||||
NORMAL_WINDOW = 0,
|
||||
X11_BACKGROUND = 1,
|
||||
EXPLICIT_WINDOW = 2,
|
||||
};
|
||||
|
||||
glm::ivec4 windowGeometry;
|
||||
std::map <std::string, std::string> screenSettings;
|
||||
std::map <std::string, std::string> properties;
|
||||
std::string background;
|
||||
std::filesystem::path assets;
|
||||
@ -24,9 +34,10 @@ namespace WallpaperEngine::Application
|
||||
bool audioEnabled;
|
||||
bool onlyListProperties;
|
||||
FREE_IMAGE_FORMAT screenshotFormat;
|
||||
WINDOW_MODE windowMode;
|
||||
|
||||
private:
|
||||
void validatePath ();
|
||||
std::string validatePath (const std::string& path);
|
||||
void validateAssets ();
|
||||
void validateScreenshot ();
|
||||
static void printHelp (const char* route);
|
||||
|
@ -5,9 +5,13 @@
|
||||
#include "WallpaperEngine/Core/CVideo.h"
|
||||
#include "WallpaperEngine/Logging/CLog.h"
|
||||
#include "WallpaperEngine/Render/CRenderContext.h"
|
||||
#include "WallpaperEngine/Render/Drivers/Output/CX11Output.h"
|
||||
#include "WallpaperEngine/Render/Drivers/Output/CWindowOutput.h"
|
||||
#include "Steam/FileSystem/FileSystem.h"
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
float g_Time;
|
||||
float g_TimeLast;
|
||||
bool g_KeepRunning = true;
|
||||
@ -18,30 +22,32 @@ using namespace WallpaperEngine::Application;
|
||||
using namespace WallpaperEngine::Core;
|
||||
|
||||
CWallpaperApplication::CWallpaperApplication (CApplicationContext& context) :
|
||||
m_context (context)
|
||||
m_context (context),
|
||||
m_defaultProject (nullptr)
|
||||
{
|
||||
// copy state to global variables for now
|
||||
g_AudioVolume = context.audioVolume;
|
||||
g_AudioEnabled = context.audioEnabled;
|
||||
this->setupContainer ();
|
||||
this->loadProject ();
|
||||
this->loadProjects ();
|
||||
this->setupProperties ();
|
||||
}
|
||||
|
||||
void CWallpaperApplication::setupContainer ()
|
||||
void CWallpaperApplication::setupContainer (CCombinedContainer& container, const std::string& bg) const
|
||||
{
|
||||
this->m_vfs.add (new CDirectory (this->m_context.background));
|
||||
this->m_vfs.addPkg (std::filesystem::path (this->m_context.background) / "scene.pkg");
|
||||
this->m_vfs.addPkg (std::filesystem::path (this->m_context.background) / "gifscene.pkg");
|
||||
this->m_vfs.add (new CDirectory (this->m_context.assets));
|
||||
std::filesystem::path basepath = bg;
|
||||
|
||||
container.add (new CDirectory (basepath));
|
||||
container.addPkg (basepath / "scene.pkg");
|
||||
container.addPkg (basepath / "gifscene.pkg");
|
||||
container.add (new CDirectory (this->m_context.assets));
|
||||
#if !NDEBUG
|
||||
this->m_vfs.add (new CDirectory ("../share/"));
|
||||
container.add (new CDirectory ("../share/"));
|
||||
#else
|
||||
this->m_vfs.add (new CDirectory (DATADIR));
|
||||
#endif /* DEBUG */
|
||||
|
||||
// TODO: move this somewhere else?
|
||||
CVirtualContainer* container = new CVirtualContainer ();
|
||||
CVirtualContainer* virtualContainer = new CVirtualContainer ();
|
||||
|
||||
//
|
||||
// Had to get a little creative with the effects to achieve the same bloom effect without any custom code
|
||||
@ -50,7 +56,7 @@ void CWallpaperApplication::setupContainer ()
|
||||
//
|
||||
|
||||
// add the effect file for screen bloom
|
||||
container->add (
|
||||
virtualContainer->add (
|
||||
"effects/wpenginelinux/bloomeffect.json",
|
||||
"{"
|
||||
"\t\"name\":\"camerabloom_wpengine_linux\","
|
||||
@ -111,7 +117,7 @@ void CWallpaperApplication::setupContainer ()
|
||||
);
|
||||
|
||||
// add some model for the image element even if it's going to waste rendering cycles
|
||||
container->add (
|
||||
virtualContainer->add (
|
||||
"models/wpenginelinux.json",
|
||||
"{"
|
||||
"\t\"material\":\"materials/wpenginelinux.json\""
|
||||
@ -119,7 +125,7 @@ void CWallpaperApplication::setupContainer ()
|
||||
);
|
||||
|
||||
// models require materials, so add that too
|
||||
container->add (
|
||||
virtualContainer->add (
|
||||
"materials/wpenginelinux.json",
|
||||
"{"
|
||||
"\t\"passes\":"
|
||||
@ -136,47 +142,74 @@ void CWallpaperApplication::setupContainer ()
|
||||
"}"
|
||||
);
|
||||
|
||||
this->m_vfs.add (container);
|
||||
container.add (virtualContainer);
|
||||
}
|
||||
|
||||
void CWallpaperApplication::loadProject ()
|
||||
void CWallpaperApplication::loadProjects ()
|
||||
{
|
||||
this->m_project = CProject::fromFile ("project.json", this->m_vfs);
|
||||
// go to the right folder so the videos will play
|
||||
// TODO: stop doing chdir and use full path
|
||||
if (this->m_project->getWallpaper ()->is <WallpaperEngine::Core::CVideo> ())
|
||||
chdir (this->m_context.background.c_str ());
|
||||
for (const auto& it : this->m_context.screenSettings)
|
||||
{
|
||||
// ignore the screen settings if there was no background specified
|
||||
// the default will be used
|
||||
if (it.second.empty())
|
||||
continue;
|
||||
|
||||
this->m_projects.insert_or_assign (
|
||||
it.first,
|
||||
this->loadProject (it.second)
|
||||
);
|
||||
}
|
||||
|
||||
// load the default project if required
|
||||
if (!this->m_context.background.empty ())
|
||||
this->m_defaultProject = this->loadProject (this->m_context.background);
|
||||
}
|
||||
|
||||
CProject* CWallpaperApplication::loadProject (const std::string& bg)
|
||||
{
|
||||
CCombinedContainer* container = new CCombinedContainer ();
|
||||
|
||||
this->setupContainer (*container, bg);
|
||||
|
||||
// TODO: Change this to pointer instead of reference
|
||||
return CProject::fromFile ("project.json", container);
|
||||
}
|
||||
|
||||
void CWallpaperApplication::setupPropertiesForProject (CProject* project)
|
||||
{
|
||||
// show properties if required
|
||||
for (auto cur : project->getProperties ())
|
||||
{
|
||||
// update the value of the property
|
||||
auto override = this->m_context.properties.find (cur->getName ());
|
||||
|
||||
if (override != this->m_context.properties.end ())
|
||||
{
|
||||
sLog.out ("Applying override value for ", cur->getName ());
|
||||
|
||||
cur->update (override->second);
|
||||
}
|
||||
|
||||
if (this->m_context.onlyListProperties)
|
||||
sLog.out (cur->dump ());
|
||||
}
|
||||
}
|
||||
|
||||
void CWallpaperApplication::setupProperties ()
|
||||
{
|
||||
// show properties if required
|
||||
for (auto cur : this->m_project->getProperties ())
|
||||
{
|
||||
// update the value of the property
|
||||
auto override = this->m_context.properties.find (cur->getName ());
|
||||
for (const auto& it : this->m_projects)
|
||||
this->setupPropertiesForProject (it.second);
|
||||
|
||||
if (override != this->m_context.properties.end ())
|
||||
{
|
||||
sLog.out ("Applying override value for ", cur->getName ());
|
||||
|
||||
cur->update (override->second);
|
||||
}
|
||||
|
||||
if (this->m_context.onlyListProperties)
|
||||
sLog.out (cur->dump ());
|
||||
}
|
||||
if (this->m_defaultProject != nullptr)
|
||||
this->setupPropertiesForProject (this->m_defaultProject);
|
||||
}
|
||||
|
||||
void CWallpaperApplication::takeScreenshot (WallpaperEngine::Render::CWallpaper* wp, const std::filesystem::path& filename, FREE_IMAGE_FORMAT format)
|
||||
void CWallpaperApplication::takeScreenshot (const Render::CRenderContext& context, const std::filesystem::path& filename, FREE_IMAGE_FORMAT format)
|
||||
{
|
||||
GLint width, height;
|
||||
// this should be getting called at the end of the frame, so the right thing should be bound already
|
||||
|
||||
// bind texture and get the size
|
||||
glBindFramebuffer (GL_FRAMEBUFFER, wp->getWallpaperFramebuffer ());
|
||||
glBindTexture (GL_TEXTURE_2D, wp->getWallpaperTexture ());
|
||||
glGetTexLevelParameteriv (GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width);
|
||||
glGetTexLevelParameteriv (GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &height);
|
||||
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];
|
||||
@ -222,15 +255,42 @@ void CWallpaperApplication::show ()
|
||||
// initialize audio context
|
||||
WallpaperEngine::Audio::CAudioContext audioContext (audioDriver);
|
||||
// initialize OpenGL driver
|
||||
WallpaperEngine::Render::Drivers::COpenGLDriver videoDriver (this->m_project->getTitle ().c_str ());
|
||||
WallpaperEngine::Render::Drivers::COpenGLDriver videoDriver ("wallpaperengine");
|
||||
// initialize the input subsystem
|
||||
WallpaperEngine::Input::CInputContext inputContext (videoDriver);
|
||||
// output requested
|
||||
WallpaperEngine::Render::Drivers::Output::COutput* output;
|
||||
|
||||
// initialize the requested output
|
||||
switch (this->m_context.windowMode)
|
||||
{
|
||||
case CApplicationContext::EXPLICIT_WINDOW:
|
||||
case CApplicationContext::NORMAL_WINDOW:
|
||||
output = new WallpaperEngine::Render::Drivers::Output::CWindowOutput (this->m_context, videoDriver);
|
||||
break;
|
||||
|
||||
case CApplicationContext::X11_BACKGROUND:
|
||||
output = new WallpaperEngine::Render::Drivers::Output::CX11Output (this->m_context, videoDriver);
|
||||
break;
|
||||
}
|
||||
|
||||
// initialize render context
|
||||
WallpaperEngine::Render::CRenderContext context (this->m_context.screens, videoDriver, inputContext, this->m_vfs, *this);
|
||||
// ensure the context knows what wallpaper to render
|
||||
context.setWallpaper (
|
||||
WallpaperEngine::Render::CWallpaper::fromWallpaper (this->m_project->getWallpaper (), context, audioContext)
|
||||
);
|
||||
WallpaperEngine::Render::CRenderContext context (output, videoDriver, inputContext, *this);
|
||||
|
||||
// set all the specific wallpapers required
|
||||
for (const auto& it : this->m_projects)
|
||||
{
|
||||
context.setWallpaper (
|
||||
it.first,
|
||||
WallpaperEngine::Render::CWallpaper::fromWallpaper (it.second->getWallpaper (), context, audioContext)
|
||||
);
|
||||
}
|
||||
|
||||
// set the default rendering wallpaper if available
|
||||
if (this->m_defaultProject != nullptr)
|
||||
context.setDefaultWallpaper (
|
||||
WallpaperEngine::Render::CWallpaper::fromWallpaper (this->m_defaultProject->getWallpaper (), context, audioContext)
|
||||
);
|
||||
|
||||
float startTime, endTime, minimumTime = 1.0f / this->m_context.maximumFPS;
|
||||
|
||||
@ -255,7 +315,7 @@ void CWallpaperApplication::show ()
|
||||
|
||||
if (this->m_context.takeScreenshot && videoDriver.getFrameCounter () == 5)
|
||||
{
|
||||
this->takeScreenshot (context.getWallpaper (), this->m_context.screenshot, this->m_context.screenshotFormat);
|
||||
this->takeScreenshot (context, this->m_context.screenshot, this->m_context.screenshotFormat);
|
||||
// disable screenshot just in case the counter overflows
|
||||
this->m_context.takeScreenshot = false;
|
||||
}
|
||||
@ -272,4 +332,14 @@ void CWallpaperApplication::show ()
|
||||
void CWallpaperApplication::signal (int signal)
|
||||
{
|
||||
g_KeepRunning = false;
|
||||
}
|
||||
|
||||
const std::map <std::string, CProject*>& CWallpaperApplication::getProjects () const
|
||||
{
|
||||
return this->m_projects;
|
||||
}
|
||||
|
||||
CProject* CWallpaperApplication::getDefaultProject () const
|
||||
{
|
||||
return this->m_defaultProject;
|
||||
}
|
@ -5,10 +5,12 @@
|
||||
#include "WallpaperEngine/Assets/CCombinedContainer.h"
|
||||
#include "WallpaperEngine/Core/CProject.h"
|
||||
#include "WallpaperEngine/Render/CWallpaper.h"
|
||||
#include "WallpaperEngine/Render/CRenderContext.h"
|
||||
|
||||
namespace WallpaperEngine::Render
|
||||
{
|
||||
class CWallpaper;
|
||||
class CRenderContext;
|
||||
}
|
||||
|
||||
namespace WallpaperEngine::Application
|
||||
@ -22,15 +24,19 @@ namespace WallpaperEngine::Application
|
||||
|
||||
void show ();
|
||||
void signal (int signal);
|
||||
const std::map <std::string, Core::CProject*>& getProjects () const;
|
||||
Core::CProject* getDefaultProject () const;
|
||||
|
||||
private:
|
||||
void setupContainer ();
|
||||
void loadProject ();
|
||||
private:
|
||||
void setupContainer (CCombinedContainer& container, const std::string& bg) const;
|
||||
void loadProjects ();
|
||||
Core::CProject* loadProject (const std::string& bg);
|
||||
void setupProperties ();
|
||||
void takeScreenshot (WallpaperEngine::Render::CWallpaper* wp, const std::filesystem::path& filename, FREE_IMAGE_FORMAT format);
|
||||
void setupPropertiesForProject (Core::CProject* project);
|
||||
void takeScreenshot (const Render::CRenderContext& context, const std::filesystem::path& filename, FREE_IMAGE_FORMAT format);
|
||||
|
||||
Core::CProject* m_project;
|
||||
Core::CProject* m_defaultProject;
|
||||
CApplicationContext& m_context;
|
||||
CCombinedContainer m_vfs;
|
||||
std::map <std::string, Core::CProject*> m_projects;
|
||||
};
|
||||
}
|
||||
|
@ -37,6 +37,27 @@ void CCombinedContainer::addPkg (const std::filesystem::path& path)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::filesystem::path CCombinedContainer::resolveRealFile (std::string filename) const
|
||||
{
|
||||
for (auto cur : this->m_containers)
|
||||
{
|
||||
try
|
||||
{
|
||||
// try to read the file on the current container, if the file doesn't exists
|
||||
// an exception will be thrown
|
||||
return cur->resolveRealFile (filename);
|
||||
}
|
||||
catch (CAssetLoadException& ex)
|
||||
{
|
||||
// not found in this container, next try
|
||||
}
|
||||
}
|
||||
|
||||
// no container was able to load the file, abort!
|
||||
throw CAssetLoadException (filename, "Cannot resolve file in any of the containers");
|
||||
}
|
||||
|
||||
const void* CCombinedContainer::readFile (std::string filename, uint32_t* length) const
|
||||
{
|
||||
for (auto cur : this->m_containers)
|
||||
|
@ -21,6 +21,7 @@ namespace WallpaperEngine::Assets
|
||||
void add (CContainer* container);
|
||||
void addPkg (const std::filesystem::path& path);
|
||||
|
||||
std::filesystem::path resolveRealFile (std::string filename) const override;
|
||||
const void* readFile (std::string filename, uint32_t* length = nullptr) const override;
|
||||
|
||||
private:
|
||||
|
@ -9,6 +9,11 @@
|
||||
|
||||
using namespace WallpaperEngine::Assets;
|
||||
|
||||
std::filesystem::path CContainer::resolveRealFile (std::string filename) const
|
||||
{
|
||||
throw CAssetLoadException (filename, "Cannot resolve physical file in this container");
|
||||
}
|
||||
|
||||
const ITexture* CContainer::readTexture (std::string filename) const
|
||||
{
|
||||
// get the texture's filename (usually .tex)
|
||||
|
@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <filesystem>
|
||||
#include <string>
|
||||
#include "WallpaperEngine/Assets/ITexture.h"
|
||||
|
||||
@ -8,6 +9,14 @@ namespace WallpaperEngine::Assets
|
||||
class CContainer
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Resolves the full path to the specified file in the filesystem
|
||||
*
|
||||
* @param filename
|
||||
* @return
|
||||
*/
|
||||
virtual std::filesystem::path resolveRealFile (std::string filename) const;
|
||||
|
||||
/**
|
||||
* Reads the given file from the container and returns it's data
|
||||
* Additionally sets a length parameter to return back the file's length
|
||||
|
@ -24,6 +24,11 @@ CDirectory::CDirectory (std::filesystem::path basepath) :
|
||||
CDirectory::~CDirectory ()
|
||||
= default;
|
||||
|
||||
std::filesystem::path CDirectory::resolveRealFile (std::string filename) const
|
||||
{
|
||||
return std::filesystem::path (this->m_basepath) / filename;
|
||||
}
|
||||
|
||||
const void* CDirectory::readFile (std::string filename, uint32_t* length) const
|
||||
{
|
||||
std::filesystem::path final = std::filesystem::path (this->m_basepath) / filename;
|
||||
|
@ -16,6 +16,7 @@ namespace WallpaperEngine::Assets
|
||||
explicit CDirectory (std::filesystem::path basepath);
|
||||
~CDirectory ();
|
||||
|
||||
std::filesystem::path resolveRealFile (std::string filename) const override;
|
||||
const void* readFile (std::string filename, uint32_t* length) const override;
|
||||
private:
|
||||
std::filesystem::path m_basepath;
|
||||
|
@ -7,7 +7,6 @@ using namespace WallpaperEngine::Audio::Drivers;
|
||||
CAudioContext::CAudioContext (CAudioDriver& driver) :
|
||||
m_driver (driver)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CAudioContext::addStream (CAudioStream* stream)
|
||||
|
@ -35,7 +35,7 @@ CObject::CObject (
|
||||
{
|
||||
}
|
||||
|
||||
CObject* CObject::fromJSON (json data, CScene* scene, const CContainer& container)
|
||||
CObject* CObject::fromJSON (json data, CScene* scene, CContainer* container)
|
||||
{
|
||||
std::string json = data.dump ();
|
||||
|
||||
|
@ -33,7 +33,7 @@ namespace WallpaperEngine::Core
|
||||
{
|
||||
friend class CScene;
|
||||
public:
|
||||
static CObject* fromJSON (json data, CScene* scene, const CContainer& container);
|
||||
static CObject* fromJSON (json data, CScene* scene, CContainer* container);
|
||||
|
||||
template<class T> const T* as () const { assert (is <T> ()); return (const T*) this; }
|
||||
template<class T> T* as () { assert (is <T> ()); return (T*) this; }
|
||||
|
@ -9,14 +9,14 @@
|
||||
using namespace WallpaperEngine::Core;
|
||||
using namespace WallpaperEngine::Assets;
|
||||
|
||||
CProject::CProject (std::string title, std::string type, CContainer& container) :
|
||||
CProject::CProject (std::string title, std::string type, CContainer* container) :
|
||||
m_title (std::move (title)),
|
||||
m_type (std::move (type)),
|
||||
m_container (container)
|
||||
{
|
||||
}
|
||||
|
||||
CProject* CProject::fromFile (const std::string& filename, CContainer& container)
|
||||
CProject* CProject::fromFile (const std::string& filename, CContainer* container)
|
||||
{
|
||||
json content = json::parse (WallpaperEngine::FileSystem::loadFullFile (filename, container));
|
||||
|
||||
@ -85,7 +85,7 @@ const std::vector<Projects::CProperty*>& CProject::getProperties () const
|
||||
return this->m_properties;
|
||||
}
|
||||
|
||||
CContainer& CProject::getContainer ()
|
||||
CContainer* CProject::getContainer ()
|
||||
{
|
||||
return this->m_container;
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ namespace WallpaperEngine::Core
|
||||
class CProject
|
||||
{
|
||||
public:
|
||||
static CProject* fromFile (const std::string& filename, CContainer& container);
|
||||
static CProject* fromFile (const std::string& filename, CContainer* container);
|
||||
|
||||
CWallpaper* getWallpaper () const;
|
||||
|
||||
@ -24,10 +24,10 @@ namespace WallpaperEngine::Core
|
||||
const std::string& getType () const;
|
||||
const std::vector<Projects::CProperty*>& getProperties () const;
|
||||
|
||||
CContainer& getContainer ();
|
||||
CContainer* getContainer ();
|
||||
|
||||
protected:
|
||||
CProject (std::string title, std::string type, CContainer& container);
|
||||
CProject (std::string title, std::string type, CContainer* container);
|
||||
|
||||
void setWallpaper (CWallpaper* wallpaper);
|
||||
void insertProperty (Projects::CProperty* property);
|
||||
@ -37,6 +37,6 @@ namespace WallpaperEngine::Core
|
||||
std::string m_title;
|
||||
std::string m_type;
|
||||
CWallpaper* m_wallpaper;
|
||||
CContainer& m_container;
|
||||
CContainer* m_container;
|
||||
};
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ using namespace WallpaperEngine::Core;
|
||||
|
||||
CScene::CScene (
|
||||
CProject& project,
|
||||
CContainer& container,
|
||||
CContainer* container,
|
||||
Scenes::CCamera* camera,
|
||||
glm::vec3 ambientColor,
|
||||
CUserSettingBoolean* bloom,
|
||||
@ -52,7 +52,7 @@ CScene::CScene (
|
||||
{
|
||||
}
|
||||
|
||||
CScene* CScene::fromFile (const std::string& filename, CProject& project, CContainer& container)
|
||||
CScene* CScene::fromFile (const std::string& filename, CProject& project, CContainer* container)
|
||||
{
|
||||
std::string stringContent = WallpaperEngine::FileSystem::loadFullFile (filename, container);
|
||||
json content = json::parse (WallpaperEngine::FileSystem::loadFullFile (filename, container));
|
||||
@ -128,7 +128,7 @@ void CScene::insertObject (CObject* object)
|
||||
}
|
||||
}
|
||||
|
||||
CContainer& CScene::getContainer ()
|
||||
CContainer* CScene::getContainer ()
|
||||
{
|
||||
return this->m_container;
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ namespace WallpaperEngine::Core
|
||||
class CScene : public CWallpaper
|
||||
{
|
||||
public:
|
||||
static CScene* fromFile (const std::string& filename, CProject& project, CContainer& container);
|
||||
static CScene* fromFile (const std::string& filename, CProject& project, CContainer* container);
|
||||
|
||||
const std::map<uint32_t, CObject*>& getObjects () const;
|
||||
const std::vector<CObject*>& getObjectsByRenderOrder () const;
|
||||
@ -46,7 +46,7 @@ namespace WallpaperEngine::Core
|
||||
|
||||
CScene (
|
||||
CProject& project,
|
||||
CContainer& container,
|
||||
CContainer* container,
|
||||
Scenes::CCamera* camera,
|
||||
glm::vec3 ambientColor,
|
||||
CUserSettingBoolean* bloom,
|
||||
@ -71,9 +71,9 @@ namespace WallpaperEngine::Core
|
||||
|
||||
void insertObject (CObject* object);
|
||||
|
||||
CContainer& getContainer ();
|
||||
CContainer* getContainer ();
|
||||
private:
|
||||
CContainer& m_container;
|
||||
CContainer* m_container;
|
||||
Scenes::CCamera* m_camera;
|
||||
|
||||
// data from general section on the json
|
||||
|
@ -36,7 +36,7 @@ CEffect::CEffect (
|
||||
{
|
||||
}
|
||||
|
||||
CEffect* CEffect::fromJSON (json data, CUserSettingBoolean* visible, Core::CObject* object, const CContainer& container)
|
||||
CEffect* CEffect::fromJSON (json data, CUserSettingBoolean* visible, Core::CObject* object, CContainer* container)
|
||||
{
|
||||
auto file_it = jsonFindRequired (data, "file", "Object effect must have a file");
|
||||
auto effectpasses_it = data.find ("passes");
|
||||
@ -202,7 +202,7 @@ void CEffect::dependencyFromJSON (json::const_iterator dependencies_it, CEffect*
|
||||
effect->insertDependency (cur);
|
||||
}
|
||||
|
||||
void CEffect::materialsFromJSON (json::const_iterator passes_it, CEffect* effect, const CContainer& container)
|
||||
void CEffect::materialsFromJSON (json::const_iterator passes_it, CEffect* effect, CContainer* container)
|
||||
{
|
||||
for (const auto& cur : (*passes_it))
|
||||
{
|
||||
|
@ -35,7 +35,7 @@ namespace WallpaperEngine::Core::Objects
|
||||
CUserSettingBoolean* visible
|
||||
);
|
||||
|
||||
static CEffect* fromJSON (json data, CUserSettingBoolean* visible, Core::CObject* object, const CContainer& container);
|
||||
static CEffect* fromJSON (json data, CUserSettingBoolean* visible, Core::CObject* object, CContainer* container);
|
||||
|
||||
const std::vector<std::string>& getDependencies () const;
|
||||
const std::vector<Images::CMaterial*>& getMaterials () const;
|
||||
@ -48,7 +48,7 @@ namespace WallpaperEngine::Core::Objects
|
||||
static void combosFromJSON (json::const_iterator combos_it, Core::Objects::Images::Materials::CPass* pass);
|
||||
static void fbosFromJSON (json::const_iterator fbos_it, CEffect* effect);
|
||||
static void dependencyFromJSON (json::const_iterator dependencies_it, CEffect* effect);
|
||||
static void materialsFromJSON (json::const_iterator passes_it, CEffect* effect, const CContainer& container);
|
||||
static void materialsFromJSON (json::const_iterator passes_it, CEffect* effect, CContainer* container);
|
||||
|
||||
void insertDependency (const std::string& dep);
|
||||
void insertMaterial (Images::CMaterial* material);
|
||||
|
@ -44,7 +44,7 @@ CImage::CImage (
|
||||
WallpaperEngine::Core::CObject* CImage::fromJSON (
|
||||
CScene* scene,
|
||||
json data,
|
||||
const CContainer& container,
|
||||
CContainer* container,
|
||||
CUserSettingBoolean* visible,
|
||||
uint32_t id,
|
||||
std::string name,
|
||||
|
@ -29,7 +29,7 @@ namespace WallpaperEngine::Core::Objects
|
||||
static CObject* fromJSON (
|
||||
CScene* scene,
|
||||
json data,
|
||||
const CContainer& container,
|
||||
CContainer* container,
|
||||
CUserSettingBoolean* visible,
|
||||
uint32_t id,
|
||||
std::string name,
|
||||
|
@ -8,7 +8,7 @@ using namespace WallpaperEngine::Core::Objects;
|
||||
CParticle* CParticle::fromFile (
|
||||
CScene* scene,
|
||||
const std::string& filename,
|
||||
const CContainer& container,
|
||||
CContainer* container,
|
||||
CUserSettingBoolean* visible,
|
||||
uint32_t id,
|
||||
std::string name,
|
||||
@ -34,10 +34,8 @@ CParticle* CParticle::fromFile (
|
||||
);
|
||||
|
||||
if (controlpoint_it != data.end ())
|
||||
{
|
||||
for (const auto& cur : (*controlpoint_it))
|
||||
particle->insertControlPoint (Particles::CControlPoint::fromJSON (cur));
|
||||
}
|
||||
|
||||
for (const auto& cur : (*emitter_it))
|
||||
particle->insertEmitter (Particles::CEmitter::fromJSON (cur));
|
||||
|
@ -19,7 +19,7 @@ namespace WallpaperEngine::Core::Objects
|
||||
static CParticle* fromFile (
|
||||
CScene* scene,
|
||||
const std::string& filename,
|
||||
const CContainer& container,
|
||||
CContainer* container,
|
||||
CUserSettingBoolean* visible,
|
||||
uint32_t id,
|
||||
std::string name,
|
||||
|
@ -16,13 +16,13 @@ CMaterial::CMaterial (std::string name) :
|
||||
{
|
||||
}
|
||||
|
||||
CMaterial* CMaterial::fromFile (const std::string& filename, const CContainer& container)
|
||||
CMaterial* CMaterial::fromFile (const std::string& filename, CContainer* container)
|
||||
{
|
||||
return fromJSON (
|
||||
filename, json::parse (WallpaperEngine::FileSystem::loadFullFile (filename, container))
|
||||
);
|
||||
}
|
||||
CMaterial* CMaterial::fromFile (const std::string& filename, const std::string& target, const CContainer& container)
|
||||
CMaterial* CMaterial::fromFile (const std::string& filename, const std::string& target, CContainer* container)
|
||||
{
|
||||
return fromJSON (
|
||||
filename, json::parse (WallpaperEngine::FileSystem::loadFullFile (filename, container)), target
|
||||
|
@ -14,9 +14,9 @@ namespace WallpaperEngine::Core::Objects::Images
|
||||
class CMaterial
|
||||
{
|
||||
public:
|
||||
static CMaterial* fromFile (const std::string& filename, const CContainer& container);
|
||||
static CMaterial* fromFile (const std::string& filename, CContainer* container);
|
||||
static CMaterial* fromJSON (const std::string& name, json data);
|
||||
static CMaterial* fromFile (const std::string& filename, const std::string& target, const CContainer& container);
|
||||
static CMaterial* fromFile (const std::string& filename, const std::string& target, CContainer* container);
|
||||
static CMaterial* fromJSON (const std::string& name, json data, const std::string& target);
|
||||
|
||||
void insertPass (Materials::CPass* mass);
|
||||
|
@ -5,10 +5,10 @@
|
||||
|
||||
using namespace WallpaperEngine;
|
||||
|
||||
std::string FileSystem::loadFullFile (const std::string& file, const WallpaperEngine::Assets::CContainer& containers)
|
||||
std::string FileSystem::loadFullFile (const std::string& file, WallpaperEngine::Assets::CContainer* containers)
|
||||
{
|
||||
uint32_t length = 0;
|
||||
const void* contents = containers.readFile (file, &length);
|
||||
const void* contents = containers->readFile (file, &length);
|
||||
|
||||
// build a new buffer that can fit in the string
|
||||
char* filedata = new char [length + 1];
|
||||
|
@ -17,5 +17,5 @@ namespace WallpaperEngine::FileSystem
|
||||
* @param file
|
||||
* @return
|
||||
*/
|
||||
std::string loadFullFile (const std::string& file, const WallpaperEngine::Assets::CContainer& containers);
|
||||
std::string loadFullFile (const std::string& file, WallpaperEngine::Assets::CContainer* containers);
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ namespace WallpaperEngine::Render
|
||||
{
|
||||
public:
|
||||
CFBO (std::string name, ITexture::TextureFormat format, ITexture::TextureFlags flags, float scale, uint32_t realWidth, uint32_t realHeight, uint32_t textureWidth, uint32_t textureHeight);
|
||||
// TODO: ADD DESTRUCTOR TO FREE RESOURCES
|
||||
|
||||
const std::string& getName () const;
|
||||
const float& getScale () const;
|
||||
|
@ -20,7 +20,7 @@ CScene* CObject::getScene () const
|
||||
return this->m_scene;
|
||||
}
|
||||
|
||||
const CContainer& CObject::getContainer () const
|
||||
CContainer* CObject::getContainer () const
|
||||
{
|
||||
return this->getScene ()->getContainer ();
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ namespace WallpaperEngine::Render
|
||||
virtual void render () = 0;
|
||||
|
||||
CScene* getScene () const;
|
||||
const CContainer& getContainer () const;
|
||||
CContainer* getContainer () const;
|
||||
int getId () const;
|
||||
|
||||
protected:
|
||||
|
@ -12,190 +12,39 @@
|
||||
#include "CRenderContext.h"
|
||||
#include "CVideo.h"
|
||||
|
||||
#define DEFAULT_WINDOW_WIDTH 1280
|
||||
#define DEFAULT_WINDOW_HEIGHT 720
|
||||
|
||||
using namespace WallpaperEngine::Render;
|
||||
|
||||
XErrorHandler originalErrorHandler;
|
||||
|
||||
void CustomXIOErrorExitHandler (Display* dsp, void* userdata)
|
||||
CRenderContext::CRenderContext (const COutput* output, CVideoDriver& driver, CInputContext& input, CWallpaperApplication& app) :
|
||||
m_defaultWallpaper (nullptr),
|
||||
m_output (output),
|
||||
m_driver (driver),
|
||||
m_app (app),
|
||||
m_input (input),
|
||||
m_textureCache (new CTextureCache (*this))
|
||||
{
|
||||
auto context = static_cast <CRenderContext*> (userdata);
|
||||
|
||||
#if !NDEBUG
|
||||
sLog.debugerror ("Critical XServer error detected. Attempting to recover...");
|
||||
#endif /* DEBUG */
|
||||
|
||||
// refetch all the resources
|
||||
context->initialize ();
|
||||
}
|
||||
|
||||
int CustomXErrorHandler (Display* dpy, XErrorEvent* event)
|
||||
void CRenderContext::render ()
|
||||
{
|
||||
#if !NDEBUG
|
||||
sLog.debugerror ("Detected X error");
|
||||
#endif /* DEBUG */
|
||||
bool firstFrame = true;
|
||||
bool renderFrame = true;
|
||||
|
||||
// call the original handler so we can keep some information reporting
|
||||
originalErrorHandler (dpy, event);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CustomXIOErrorHandler (Display* dsp)
|
||||
{
|
||||
#if !NDEBUG
|
||||
sLog.debugerror ("Detected X error");
|
||||
#endif /* DEBUG */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
CRenderContext::CRenderContext (std::vector <std::string> screens, CVideoDriver& driver, CInputContext& input, CContainer& container, CWallpaperApplication& app) :
|
||||
m_wallpaper (nullptr),
|
||||
m_screens (std::move (screens)),
|
||||
m_driver (driver),
|
||||
m_container (container),
|
||||
m_app (app),
|
||||
m_input (input),
|
||||
m_textureCache (new CTextureCache (*this)),
|
||||
m_display (nullptr),
|
||||
m_pixmap (0),
|
||||
m_gc (nullptr),
|
||||
m_image (nullptr),
|
||||
m_imageData (nullptr),
|
||||
m_fbo (nullptr)
|
||||
{
|
||||
this->initialize ();
|
||||
}
|
||||
|
||||
void CRenderContext::initialize ()
|
||||
{
|
||||
if (this->m_screens.empty ())
|
||||
this->setupWindow ();
|
||||
else
|
||||
this->setupScreens ();
|
||||
}
|
||||
|
||||
void CRenderContext::setupWindow ()
|
||||
{
|
||||
this->m_driver.showWindow ();
|
||||
this->m_driver.resizeWindow ({DEFAULT_WINDOW_WIDTH, DEFAULT_WINDOW_HEIGHT});
|
||||
}
|
||||
|
||||
void CRenderContext::setupScreens ()
|
||||
{
|
||||
this->m_viewports.clear ();
|
||||
|
||||
this->m_display = XOpenDisplay (nullptr);
|
||||
|
||||
// set the error handling to try and recover from X disconnections
|
||||
#ifdef HAVE_XSETIOERROREXITHANDLER
|
||||
XSetIOErrorExitHandler (this->m_display, CustomXIOErrorExitHandler, this);
|
||||
#endif /* HAVE_XSETIOERROREXITHANDLER */
|
||||
originalErrorHandler = XSetErrorHandler (CustomXErrorHandler);
|
||||
XSetIOErrorHandler (CustomXIOErrorHandler);
|
||||
|
||||
int xrandr_result, xrandr_error;
|
||||
|
||||
if (!XRRQueryExtension (this->m_display, &xrandr_result, &xrandr_error))
|
||||
{
|
||||
sLog.error ("XRandr is not present, cannot detect specified screens, running in window mode");
|
||||
return;
|
||||
}
|
||||
|
||||
Window root = DefaultRootWindow (this->m_display);
|
||||
int fullWidth = DisplayWidth (this->m_display, DefaultScreen (this->m_display));
|
||||
int fullHeight = DisplayHeight (this->m_display, DefaultScreen (this->m_display));
|
||||
XRRScreenResources* screenResources = XRRGetScreenResources (this->m_display, DefaultRootWindow (this->m_display));
|
||||
|
||||
// there are some situations where xrandr returns null (like screen not using the extension)
|
||||
if (screenResources == nullptr)
|
||||
return;
|
||||
|
||||
// create the pixmap and gc used for this display, most situations only have one "display"
|
||||
this->m_pixmap = XCreatePixmap (this->m_display, DefaultRootWindow (this->m_display), fullWidth, fullHeight, 24);
|
||||
this->m_gc = XCreateGC (this->m_display, this->m_pixmap, 0, nullptr);
|
||||
// fill the whole pixmap with black for now
|
||||
XFillRectangle (this->m_display, this->m_pixmap, this->m_gc, 0, 0, fullWidth, fullHeight);
|
||||
|
||||
for (int i = 0; i < screenResources->noutput; i ++)
|
||||
{
|
||||
XRROutputInfo* info = XRRGetOutputInfo (this->m_display, screenResources, screenResources->outputs [i]);
|
||||
|
||||
// there are some situations where xrandr returns null (like screen not using the extension)
|
||||
if (info == nullptr || info->connection != RR_Connected)
|
||||
continue;
|
||||
|
||||
for (const auto& cur : this->m_screens)
|
||||
{
|
||||
if (strcmp (info->name, cur.c_str ()) != 0)
|
||||
continue;
|
||||
|
||||
XRRCrtcInfo* crtc = XRRGetCrtcInfo (this->m_display, screenResources, info->crtc);
|
||||
|
||||
sLog.out ("Found requested screen: ", info->name, " -> ", crtc->x, "x", crtc->y, ":", crtc->width, "x", crtc->height);
|
||||
|
||||
this->m_viewports.push_back ({{crtc->x, crtc->y, crtc->width, crtc->height}, cur});
|
||||
|
||||
XRRFreeCrtcInfo (crtc);
|
||||
}
|
||||
|
||||
XRRFreeOutputInfo (info);
|
||||
}
|
||||
|
||||
XRRFreeScreenResources (screenResources);
|
||||
|
||||
// create the fbo that will handle the screen
|
||||
this->m_fbo = new CFBO(
|
||||
"_sc_FullFrameBuffer",
|
||||
ITexture::TextureFormat::ARGB8888,
|
||||
ITexture::TextureFlags::NoFlags,
|
||||
1.0,
|
||||
fullWidth, fullHeight,
|
||||
fullWidth, fullHeight
|
||||
);
|
||||
|
||||
// set the window background so the pixmap is drawn
|
||||
XSetWindowBackgroundPixmap(this->m_display, root, this->m_pixmap);
|
||||
|
||||
this->m_imageData = new char [fullWidth * fullHeight * 4];
|
||||
|
||||
// create the image for X11 to be able to copy it over
|
||||
this->m_image = XCreateImage (this->m_display, CopyFromParent, 24, ZPixmap, 0, this->m_imageData, fullWidth, fullHeight, 32, 0);
|
||||
}
|
||||
|
||||
CRenderContext::~CRenderContext ()
|
||||
{
|
||||
if (!this->m_screens.empty ())
|
||||
{
|
||||
// free any used resource
|
||||
XDestroyImage (this->m_image);
|
||||
XFreeGC (this->m_display, this->m_gc);
|
||||
XFreePixmap (this->m_display, this->m_pixmap);
|
||||
XCloseDisplay (this->m_display);
|
||||
}
|
||||
}
|
||||
|
||||
void CRenderContext::renderScreens ()
|
||||
{
|
||||
bool firstFrame = true;
|
||||
bool renderFrame = true;
|
||||
int fullWidth = DisplayWidth (this->m_display, DefaultScreen (this->m_display));
|
||||
int fullHeight = DisplayHeight (this->m_display, DefaultScreen (this->m_display));
|
||||
Window root = DefaultRootWindow (this->m_display);
|
||||
|
||||
for (const auto& cur : this->m_viewports)
|
||||
for (const auto& cur : this->m_output->getViewports ())
|
||||
{
|
||||
#if !NDEBUG
|
||||
std::string str = "Rendering to screen " + cur.name;
|
||||
std::string str = "Rendering to output " + cur.first;
|
||||
|
||||
glPushDebugGroup (GL_DEBUG_SOURCE_APPLICATION, 0, -1, str.c_str ());
|
||||
#endif /* DEBUG */
|
||||
|
||||
// render the background
|
||||
this->m_wallpaper->render (cur.viewport, false, renderFrame, firstFrame);
|
||||
// search the background in the viewport selection
|
||||
auto ref = this->m_wallpapers.find (cur.first);
|
||||
|
||||
// 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;
|
||||
@ -205,61 +54,27 @@ void CRenderContext::renderScreens ()
|
||||
}
|
||||
|
||||
// read the full texture into the image
|
||||
glReadPixels (0, 0, fullWidth, fullHeight, GL_BGRA, GL_UNSIGNED_BYTE, (void*) this->m_imageData);
|
||||
|
||||
// put the image back into the screen
|
||||
XPutImage (this->m_display, this->m_pixmap, this->m_gc, this->m_image, 0, 0, 0, 0, fullWidth, fullHeight);
|
||||
|
||||
// _XROOTPMAP_ID & ESETROOT_PMAP_ID allow other programs (compositors) to
|
||||
// edit the background. Without these, other programs will clear the screen.
|
||||
// it also forces the compositor to refresh the background (tested with picom)
|
||||
Atom prop_root = XInternAtom(this->m_display, "_XROOTPMAP_ID", False);
|
||||
Atom prop_esetroot = XInternAtom(this->m_display, "ESETROOT_PMAP_ID", False);
|
||||
XChangeProperty(this->m_display, root, prop_root, XA_PIXMAP, 32, PropModeReplace, (unsigned char *) &this->m_pixmap, 1);
|
||||
XChangeProperty(this->m_display, root, prop_esetroot, XA_PIXMAP, 32, PropModeReplace, (unsigned char *) &this->m_pixmap, 1);
|
||||
|
||||
XClearWindow(this->m_display, root);
|
||||
XFlush(this->m_display);
|
||||
}
|
||||
|
||||
void CRenderContext::renderWindow ()
|
||||
{
|
||||
// render the background to the window directly
|
||||
this->m_wallpaper->render ({0, 0, this->m_driver.getFramebufferSize ()}, true);
|
||||
}
|
||||
|
||||
void CRenderContext::render ()
|
||||
{
|
||||
if (this->m_wallpaper == nullptr)
|
||||
return;
|
||||
|
||||
if (this->m_viewports.empty ())
|
||||
this->renderWindow ();
|
||||
else
|
||||
this->renderScreens ();
|
||||
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::setWallpaper (CWallpaper* wallpaper)
|
||||
void CRenderContext::setDefaultWallpaper (CWallpaper* wallpaper)
|
||||
{
|
||||
this->m_wallpaper = wallpaper;
|
||||
this->m_defaultWallpaper = wallpaper;
|
||||
}
|
||||
|
||||
// update the wallpaper's texcoords based on the mode we're running
|
||||
if (!this->m_screens.empty ())
|
||||
{
|
||||
GLfloat texCoords [] = {
|
||||
0.0f, 1.0f,
|
||||
1.0f, 1.0f,
|
||||
0.0f, 0.0f,
|
||||
0.0f, 0.0f,
|
||||
1.0f, 1.0f,
|
||||
1.0f, 0.0f
|
||||
};
|
||||
|
||||
this->m_wallpaper->updateTexCoord (texCoords, sizeof (texCoords));
|
||||
this->m_wallpaper->setDestinationFramebuffer (this->m_fbo->getFramebuffer ());
|
||||
}
|
||||
void CRenderContext::setWallpaper (const std::string& display, CWallpaper* wallpaper)
|
||||
{
|
||||
this->m_wallpapers.insert_or_assign (display, wallpaper);
|
||||
}
|
||||
|
||||
CInputContext& CRenderContext::getInputContext () const
|
||||
@ -267,21 +82,16 @@ CInputContext& CRenderContext::getInputContext () const
|
||||
return this->m_input;
|
||||
}
|
||||
|
||||
CWallpaper* CRenderContext::getWallpaper () const
|
||||
{
|
||||
return this->m_wallpaper;
|
||||
}
|
||||
|
||||
const CContainer& CRenderContext::getContainer () const
|
||||
{
|
||||
return this->m_container;
|
||||
}
|
||||
|
||||
const CWallpaperApplication& CRenderContext::getApp () const
|
||||
{
|
||||
return this->m_app;
|
||||
}
|
||||
|
||||
const COutput* CRenderContext::getOutput () const
|
||||
{
|
||||
return this->m_output;
|
||||
}
|
||||
|
||||
const ITexture* CRenderContext::resolveTexture (const std::string& name)
|
||||
{
|
||||
return this->m_textureCache->resolve (name);
|
||||
|
@ -9,12 +9,19 @@
|
||||
#include "WallpaperEngine/Input/CInputContext.h"
|
||||
#include "WallpaperEngine/Input/CMouseInput.h"
|
||||
#include "WallpaperEngine/Render/Drivers/CVideoDriver.h"
|
||||
#include "WallpaperEngine/Render/Drivers/Output/COutput.h"
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
using namespace WallpaperEngine::Application;
|
||||
using namespace WallpaperEngine::Assets;
|
||||
using namespace WallpaperEngine::Input;
|
||||
using namespace WallpaperEngine::Render::Drivers;
|
||||
using namespace WallpaperEngine::Render::Drivers::Output;
|
||||
|
||||
namespace WallpaperEngine::Render::Drivers::Output
|
||||
{
|
||||
class COutput;
|
||||
}
|
||||
|
||||
namespace WallpaperEngine::Render::Drivers
|
||||
{
|
||||
@ -34,45 +41,23 @@ namespace WallpaperEngine::Render
|
||||
class CRenderContext
|
||||
{
|
||||
public:
|
||||
CRenderContext (std::vector <std::string> screens, CVideoDriver& driver, CInputContext& input, CContainer& container, CWallpaperApplication& app);
|
||||
~CRenderContext ();
|
||||
CRenderContext (const COutput* output, CVideoDriver& driver, CInputContext& input, CWallpaperApplication& app);
|
||||
|
||||
void initialize ();
|
||||
void render ();
|
||||
void setWallpaper (CWallpaper* wallpaper);
|
||||
void setDefaultWallpaper (CWallpaper* wallpaper);
|
||||
void setWallpaper (const std::string& display, CWallpaper* wallpaper);
|
||||
CInputContext& getInputContext () const;
|
||||
void setMouse (CMouseInput* mouse);
|
||||
CWallpaper* getWallpaper () const;
|
||||
const CContainer& getContainer () const;
|
||||
const CWallpaperApplication& getApp () const;
|
||||
const COutput* getOutput () const;
|
||||
const ITexture* resolveTexture (const std::string& name);
|
||||
|
||||
private:
|
||||
void setupScreens ();
|
||||
void setupWindow ();
|
||||
|
||||
void renderScreens ();
|
||||
void renderWindow ();
|
||||
|
||||
struct viewport
|
||||
{
|
||||
glm::ivec4 viewport;
|
||||
std::string name;
|
||||
};
|
||||
|
||||
Display* m_display;
|
||||
Pixmap m_pixmap;
|
||||
GC m_gc;
|
||||
XImage* m_image;
|
||||
CVideoDriver& m_driver;
|
||||
char* m_imageData;
|
||||
CFBO* m_fbo;
|
||||
std::vector <std::string> m_screens;
|
||||
std::vector <viewport> m_viewports;
|
||||
CWallpaper* m_wallpaper;
|
||||
std::map <std::string, CWallpaper*> m_wallpapers;
|
||||
CWallpaper* m_defaultWallpaper;
|
||||
CInputContext& m_input;
|
||||
CContainer& m_container;
|
||||
CWallpaperApplication& m_app;
|
||||
CTextureCache* m_textureCache;
|
||||
const COutput* m_output;
|
||||
};
|
||||
}
|
@ -1,6 +1,9 @@
|
||||
#include "CTextureCache.h"
|
||||
|
||||
#include "WallpaperEngine/Assets/CAssetLoadException.h"
|
||||
|
||||
using namespace WallpaperEngine::Render;
|
||||
using namespace WallpaperEngine::Assets;
|
||||
|
||||
CTextureCache::CTextureCache (CRenderContext& context) :
|
||||
m_context (context)
|
||||
@ -17,11 +20,26 @@ const ITexture* CTextureCache::resolve (const std::string& filename)
|
||||
if (found != this->m_textureCache.end ())
|
||||
return (*found).second;
|
||||
|
||||
const ITexture* texture = this->m_context.getContainer ().readTexture (filename);
|
||||
// search for the texture in all the different containers just in case
|
||||
for (auto it : this->m_context.getApp ().getProjects ())
|
||||
{
|
||||
const ITexture* texture = it.second->getContainer ()->readTexture (filename);
|
||||
|
||||
this->store (filename, texture);
|
||||
this->store (filename, texture);
|
||||
|
||||
return texture;
|
||||
return texture;
|
||||
}
|
||||
|
||||
if (this->m_context.getApp ().getDefaultProject () != nullptr)
|
||||
{
|
||||
const ITexture* texture = this->m_context.getApp ().getDefaultProject ()->getContainer ()->readTexture (filename);
|
||||
|
||||
this->store (filename, texture);
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
||||
throw CAssetLoadException (filename, "Cannot find file");
|
||||
}
|
||||
|
||||
void CTextureCache::store (std::string name, const ITexture* texture)
|
||||
|
@ -54,8 +54,11 @@ CVideo::CVideo (Core::CVideo* video, CRenderContext& context, CAudioContext& aud
|
||||
if (mpv_render_context_create (&this->m_mpvGl, this->m_mpv, params) < 0)
|
||||
sLog.exception ("Failed to initialize MPV's GL context");
|
||||
|
||||
std::filesystem::path videopath = this->getVideo ()->getProject ().getContainer ()->resolveRealFile (this->getVideo ()->getFilename ());
|
||||
|
||||
// build the path to the video file
|
||||
const char* command [] = {
|
||||
"loadfile", this->getVideo ()->getFilename ().c_str (), nullptr
|
||||
"loadfile", videopath.c_str (), nullptr
|
||||
};
|
||||
|
||||
if (mpv_command (this->m_mpv, command) < 0)
|
||||
|
@ -61,9 +61,9 @@ CWallpaper::CWallpaper (Core::CWallpaper* wallpaperData, std::string type, CRend
|
||||
CWallpaper::~CWallpaper ()
|
||||
= default;
|
||||
|
||||
const CContainer& CWallpaper::getContainer () const
|
||||
CContainer* CWallpaper::getContainer () const
|
||||
{
|
||||
return this->m_context.getContainer ();
|
||||
return this->m_wallpaperData->getProject ().getContainer ();
|
||||
}
|
||||
|
||||
WallpaperEngine::Core::CWallpaper* CWallpaper::getWallpaperData () const
|
||||
|
@ -38,7 +38,7 @@ namespace WallpaperEngine::Render
|
||||
/**
|
||||
* @return The container to resolve files for this wallpaper
|
||||
*/
|
||||
const CContainer& getContainer () const;
|
||||
CContainer* getContainer () const;
|
||||
|
||||
/**
|
||||
* @return The current context rendering this wallpaper
|
||||
|
@ -62,6 +62,12 @@ void COpenGLDriver::resizeWindow (glm::ivec2 size)
|
||||
glfwSetWindowSize (this->m_window, size.x, size.y);
|
||||
}
|
||||
|
||||
void COpenGLDriver::resizeWindow (glm::ivec4 sizeandpos)
|
||||
{
|
||||
glfwSetWindowPos (this->m_window, sizeandpos.x, sizeandpos.y);
|
||||
glfwSetWindowSize (this->m_window, sizeandpos.z, sizeandpos.w);
|
||||
}
|
||||
|
||||
void COpenGLDriver::showWindow ()
|
||||
{
|
||||
glfwShowWindow (this->m_window);
|
||||
|
@ -3,9 +3,17 @@
|
||||
#include <GL/glew.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
#include "WallpaperEngine/Render/Drivers/CVideoDriver.h"
|
||||
#include "WallpaperEngine/Application/CApplicationContext.h"
|
||||
|
||||
namespace WallpaperEngine::Application
|
||||
{
|
||||
class CApplicationContext;
|
||||
}
|
||||
|
||||
namespace WallpaperEngine::Render::Drivers
|
||||
{
|
||||
using namespace WallpaperEngine::Application;
|
||||
|
||||
class COpenGLDriver : public CVideoDriver
|
||||
{
|
||||
public:
|
||||
@ -15,6 +23,7 @@ namespace WallpaperEngine::Render::Drivers
|
||||
float getRenderTime () 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 () override;
|
||||
@ -22,6 +31,7 @@ namespace WallpaperEngine::Render::Drivers
|
||||
uint32_t getFrameCounter () override;
|
||||
|
||||
GLFWwindow* getWindow ();
|
||||
|
||||
private:
|
||||
GLFWwindow* m_window;
|
||||
uint32_t m_frameCounter;
|
||||
|
@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <glm/vec4.hpp>
|
||||
#include <glm/vec2.hpp>
|
||||
|
||||
namespace WallpaperEngine::Render::Drivers
|
||||
@ -10,6 +11,7 @@ namespace WallpaperEngine::Render::Drivers
|
||||
virtual float getRenderTime () = 0;
|
||||
virtual bool closeRequested () = 0;
|
||||
virtual void resizeWindow (glm::ivec2 size) = 0;
|
||||
virtual void resizeWindow (glm::ivec4 size) = 0;
|
||||
virtual void showWindow () = 0;
|
||||
virtual void hideWindow () = 0;
|
||||
virtual glm::ivec2 getFramebufferSize () = 0;
|
||||
|
23
src/WallpaperEngine/Render/Drivers/Output/COutput.cpp
Normal file
23
src/WallpaperEngine/Render/Drivers/Output/COutput.cpp
Normal file
@ -0,0 +1,23 @@
|
||||
#include "COutput.h"
|
||||
|
||||
using namespace WallpaperEngine::Render::Drivers::Output;
|
||||
|
||||
COutput::COutput (CApplicationContext& context) :
|
||||
m_context (context)
|
||||
{
|
||||
}
|
||||
|
||||
const std::map <std::string, COutput::ScreenInfo>& COutput::getViewports () const
|
||||
{
|
||||
return this->m_viewports;
|
||||
}
|
||||
|
||||
int COutput::getFullWidth () const
|
||||
{
|
||||
return this->m_fullWidth;
|
||||
}
|
||||
|
||||
int COutput::getFullHeight () const
|
||||
{
|
||||
return this->m_fullHeight;
|
||||
}
|
47
src/WallpaperEngine/Render/Drivers/Output/COutput.h
Normal file
47
src/WallpaperEngine/Render/Drivers/Output/COutput.h
Normal file
@ -0,0 +1,47 @@
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <glm/vec4.hpp>
|
||||
|
||||
#include "WallpaperEngine/Application/CApplicationContext.h"
|
||||
|
||||
using namespace WallpaperEngine::Application;
|
||||
|
||||
namespace WallpaperEngine::Application
|
||||
{
|
||||
class CApplicationContext;
|
||||
}
|
||||
|
||||
namespace WallpaperEngine::Render::Drivers::Output
|
||||
{
|
||||
class COutput
|
||||
{
|
||||
public:
|
||||
COutput (CApplicationContext& context);
|
||||
|
||||
virtual void reset () = 0;
|
||||
|
||||
int getFullWidth () const;
|
||||
int getFullHeight () const;
|
||||
|
||||
struct ScreenInfo
|
||||
{
|
||||
glm::ivec4 viewport;
|
||||
std::string name;
|
||||
};
|
||||
|
||||
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;
|
||||
};
|
||||
}
|
77
src/WallpaperEngine/Render/Drivers/Output/CWindowOutput.cpp
Normal file
77
src/WallpaperEngine/Render/Drivers/Output/CWindowOutput.cpp
Normal file
@ -0,0 +1,77 @@
|
||||
#include "CWindowOutput.h"
|
||||
#include "WallpaperEngine/Logging/CLog.h"
|
||||
|
||||
using namespace WallpaperEngine::Render::Drivers::Output;
|
||||
|
||||
CWindowOutput::CWindowOutput (CApplicationContext& context, CVideoDriver& driver) :
|
||||
COutput (context),
|
||||
m_driver (driver)
|
||||
{
|
||||
if (
|
||||
this->m_context.windowMode != Application::CApplicationContext::NORMAL_WINDOW &&
|
||||
this->m_context.windowMode != Application::CApplicationContext::EXPLICIT_WINDOW)
|
||||
sLog.exception ("Inititalizing window output when not in output mode, how did you get here?!");
|
||||
|
||||
// window should be visible
|
||||
driver.showWindow ();
|
||||
|
||||
if (this->m_context.windowMode == Application::CApplicationContext::EXPLICIT_WINDOW)
|
||||
{
|
||||
this->m_fullWidth = this->m_context.windowGeometry.z;
|
||||
this->m_fullHeight = this->m_context.windowGeometry.w;
|
||||
this->repositionWindow ();
|
||||
}
|
||||
else
|
||||
{
|
||||
// take the size from the driver (default window size)
|
||||
this->m_fullWidth = this->m_driver.getFramebufferSize ().x;
|
||||
this->m_fullHeight = this->m_driver.getFramebufferSize ().y;
|
||||
}
|
||||
|
||||
// register the default viewport
|
||||
this->m_viewports ["default"] = {{0, 0, this->m_fullWidth, this->m_fullHeight}, "default"};
|
||||
}
|
||||
|
||||
void CWindowOutput::repositionWindow ()
|
||||
{
|
||||
// reposition the window
|
||||
this->m_driver.resizeWindow (this->m_context.windowGeometry);
|
||||
}
|
||||
|
||||
void CWindowOutput::reset ()
|
||||
{
|
||||
if (this->m_context.windowMode == Application::CApplicationContext::EXPLICIT_WINDOW)
|
||||
this->repositionWindow ();
|
||||
}
|
||||
|
||||
bool CWindowOutput::renderVFlip () const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CWindowOutput::renderMultiple () const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CWindowOutput::haveImageBuffer () const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void* CWindowOutput::getImageBuffer () const
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
void CWindowOutput::updateRender () const
|
||||
{
|
||||
if (this->m_context.windowMode != Application::CApplicationContext::NORMAL_WINDOW)
|
||||
return;
|
||||
|
||||
// take the size from the driver (default window size)
|
||||
this->m_fullWidth = this->m_driver.getFramebufferSize ().x;
|
||||
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"};
|
||||
}
|
25
src/WallpaperEngine/Render/Drivers/Output/CWindowOutput.h
Normal file
25
src/WallpaperEngine/Render/Drivers/Output/CWindowOutput.h
Normal file
@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
#include "WallpaperEngine/Render/Drivers/CVideoDriver.h"
|
||||
#include "COutput.h"
|
||||
|
||||
namespace WallpaperEngine::Render::Drivers::Output
|
||||
{
|
||||
class CWindowOutput : public COutput
|
||||
{
|
||||
public:
|
||||
CWindowOutput (CApplicationContext& context, CVideoDriver& driver);
|
||||
|
||||
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 repositionWindow ();
|
||||
|
||||
CVideoDriver& m_driver;
|
||||
};
|
||||
}
|
183
src/WallpaperEngine/Render/Drivers/Output/CX11Output.cpp
Normal file
183
src/WallpaperEngine/Render/Drivers/Output/CX11Output.cpp
Normal file
@ -0,0 +1,183 @@
|
||||
#include "common.h"
|
||||
#include "CX11Output.h"
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xatom.h>
|
||||
#include <X11/extensions/Xrandr.h>
|
||||
|
||||
using namespace WallpaperEngine::Render::Drivers::Output;
|
||||
|
||||
XErrorHandler originalErrorHandler;
|
||||
|
||||
void CustomXIOErrorExitHandler (Display* dsp, void* userdata)
|
||||
{
|
||||
auto context = static_cast <CX11Output*> (userdata);
|
||||
|
||||
#if !NDEBUG
|
||||
sLog.debugerror ("Critical XServer error detected. Attempting to recover...");
|
||||
#endif /* DEBUG */
|
||||
|
||||
// refetch all the resources
|
||||
context->reset ();
|
||||
}
|
||||
|
||||
int CustomXErrorHandler (Display* dpy, XErrorEvent* event)
|
||||
{
|
||||
#if !NDEBUG
|
||||
sLog.debugerror ("Detected X error");
|
||||
#endif /* DEBUG */
|
||||
|
||||
// call the original handler so we can keep some information reporting
|
||||
originalErrorHandler (dpy, event);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CustomXIOErrorHandler (Display* dsp)
|
||||
{
|
||||
#if !NDEBUG
|
||||
sLog.debugerror ("Detected X error");
|
||||
#endif /* DEBUG */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
CX11Output::CX11Output (CApplicationContext& context, CVideoDriver& driver) :
|
||||
COutput (context),
|
||||
m_driver (driver)
|
||||
{
|
||||
this->m_display = XOpenDisplay (nullptr);
|
||||
this->loadScreenInfo ();
|
||||
}
|
||||
CX11Output::~CX11Output ()
|
||||
{
|
||||
this->free ();
|
||||
XCloseDisplay (this->m_display);
|
||||
}
|
||||
|
||||
void CX11Output::reset ()
|
||||
{
|
||||
// first free whatever we have right now
|
||||
this->free ();
|
||||
// re-load screen info
|
||||
this->loadScreenInfo ();
|
||||
}
|
||||
|
||||
void CX11Output::free ()
|
||||
{
|
||||
// free all the resources we've got
|
||||
XDestroyImage (this->m_image);
|
||||
XFreeGC (this->m_display, this->m_gc);
|
||||
XFreePixmap (this->m_display, this->m_pixmap);
|
||||
delete this->m_imageData;
|
||||
}
|
||||
|
||||
void* CX11Output::getImageBuffer () const
|
||||
{
|
||||
return this->m_imageData;
|
||||
}
|
||||
|
||||
bool CX11Output::renderVFlip () const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CX11Output::renderMultiple () const
|
||||
{
|
||||
return this->m_viewports.size () > 1;
|
||||
}
|
||||
|
||||
bool CX11Output::haveImageBuffer () const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void CX11Output::loadScreenInfo ()
|
||||
{
|
||||
// reset the viewports
|
||||
this->m_viewports.clear ();
|
||||
|
||||
// set the error handling to try and recover from X disconnections
|
||||
#ifdef HAVE_XSETIOERROREXITHANDLER
|
||||
XSetIOErrorExitHandler (this->m_display, CustomXIOErrorExitHandler, this);
|
||||
#endif /* HAVE_XSETIOERROREXITHANDLER */
|
||||
originalErrorHandler = XSetErrorHandler (CustomXErrorHandler);
|
||||
XSetIOErrorHandler (CustomXIOErrorHandler);
|
||||
|
||||
int xrandr_result, xrandr_error;
|
||||
|
||||
if (!XRRQueryExtension (this->m_display, &xrandr_result, &xrandr_error))
|
||||
{
|
||||
sLog.error ("XRandr is not present, cannot detect specified screens, running in window mode");
|
||||
return;
|
||||
}
|
||||
|
||||
this->m_root = DefaultRootWindow (this->m_display);
|
||||
this->m_fullWidth = DisplayWidth (this->m_display, DefaultScreen (this->m_display));
|
||||
this->m_fullHeight = DisplayHeight (this->m_display, DefaultScreen (this->m_display));
|
||||
XRRScreenResources* screenResources = XRRGetScreenResources (this->m_display, DefaultRootWindow (this->m_display));
|
||||
|
||||
if (screenResources == nullptr)
|
||||
{
|
||||
sLog.error ("Cannot detect screen sizes using xrandr, running in window mode");
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < screenResources->noutput; i ++)
|
||||
{
|
||||
XRROutputInfo* info = XRRGetOutputInfo (this->m_display, screenResources, screenResources->outputs [i]);
|
||||
|
||||
// screen not in use, ignore it
|
||||
if (info == nullptr || info->connection != RR_Connected)
|
||||
continue;
|
||||
|
||||
// only keep info of registered screens
|
||||
if (this->m_context.screenSettings.find (info->name) == this->m_context.screenSettings.end ())
|
||||
continue;
|
||||
|
||||
XRRCrtcInfo* crtc = XRRGetCrtcInfo (this->m_display, screenResources, info->crtc);
|
||||
|
||||
sLog.out ("Found requested screen: ", info->name, " -> ", crtc->x, "x", crtc->y, ":", crtc->width, "x", crtc->height);
|
||||
|
||||
this->m_viewports [info->name] =
|
||||
{
|
||||
{crtc->x, crtc->y, crtc->width, crtc->height},
|
||||
info->name
|
||||
};
|
||||
|
||||
XRRFreeCrtcInfo (crtc);
|
||||
}
|
||||
|
||||
XRRFreeScreenResources (screenResources);
|
||||
|
||||
// create pixmap so we can draw things in there
|
||||
this->m_pixmap = XCreatePixmap (this->m_display, this->m_root, this->m_fullWidth, this->m_fullHeight, 24);
|
||||
this->m_gc = XCreateGC (this->m_display, this->m_pixmap, 0, nullptr);
|
||||
// pre-fill it with black
|
||||
XFillRectangle (this->m_display, this->m_pixmap, this->m_gc, 0, 0, this->m_fullWidth, this->m_fullHeight);
|
||||
// set the window background as our pixmap
|
||||
XSetWindowBackgroundPixmap (this->m_display, this->m_root, this->m_pixmap);
|
||||
// allocate space for the image's data
|
||||
this->m_imageData = new char [this->m_fullWidth * this->m_fullHeight * 4];
|
||||
// create an image so we can copy it over
|
||||
this->m_image = XCreateImage (this->m_display, CopyFromParent, 24, ZPixmap, 0, this->m_imageData, this->m_fullWidth, this->m_fullHeight, 32, 0);
|
||||
// setup driver's render changing the window's size
|
||||
this->m_driver.resizeWindow ({this->m_fullWidth, this->m_fullHeight});
|
||||
}
|
||||
|
||||
void CX11Output::updateRender () const
|
||||
{
|
||||
// put the image back into the screen
|
||||
XPutImage (this->m_display, this->m_pixmap, this->m_gc, this->m_image, 0, 0, 0, 0, this->m_fullWidth, this->m_fullHeight);
|
||||
|
||||
// _XROOTPMAP_ID & ESETROOT_PMAP_ID allow other programs (compositors) to
|
||||
// edit the background. Without these, other programs will clear the screen.
|
||||
// it also forces the compositor to refresh the background (tested with picom)
|
||||
Atom prop_root = XInternAtom(this->m_display, "_XROOTPMAP_ID", False);
|
||||
Atom prop_esetroot = XInternAtom(this->m_display, "ESETROOT_PMAP_ID", False);
|
||||
XChangeProperty(this->m_display, this->m_root, prop_root, XA_PIXMAP, 32, PropModeReplace, (unsigned char *) &this->m_pixmap, 1);
|
||||
XChangeProperty(this->m_display, this->m_root, prop_esetroot, XA_PIXMAP, 32, PropModeReplace, (unsigned char *) &this->m_pixmap, 1);
|
||||
|
||||
XClearWindow(this->m_display, this->m_root);
|
||||
XFlush(this->m_display);
|
||||
}
|
40
src/WallpaperEngine/Render/Drivers/Output/CX11Output.h
Normal file
40
src/WallpaperEngine/Render/Drivers/Output/CX11Output.h
Normal file
@ -0,0 +1,40 @@
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <glm/vec4.hpp>
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
#include "WallpaperEngine/Render/Drivers/CVideoDriver.h"
|
||||
#include "COutput.h"
|
||||
|
||||
namespace WallpaperEngine::Render::Drivers::Output
|
||||
{
|
||||
class CX11Output : public COutput
|
||||
{
|
||||
public:
|
||||
CX11Output (CApplicationContext& context, CVideoDriver& driver);
|
||||
~CX11Output ();
|
||||
|
||||
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 loadScreenInfo ();
|
||||
void free ();
|
||||
|
||||
Display* m_display;
|
||||
Pixmap m_pixmap;
|
||||
Window m_root;
|
||||
GC m_gc;
|
||||
char* m_imageData;
|
||||
XImage* m_image;
|
||||
CVideoDriver& m_driver;
|
||||
};
|
||||
}
|
@ -2,13 +2,16 @@
|
||||
|
||||
#include "CSound.h"
|
||||
|
||||
extern bool g_AudioEnabled;
|
||||
|
||||
using namespace WallpaperEngine::Render::Objects;
|
||||
|
||||
CSound::CSound (CScene* scene, Core::Objects::CSound* sound) :
|
||||
CObject (scene, Type, sound),
|
||||
m_sound (sound)
|
||||
{
|
||||
this->load ();
|
||||
if (g_AudioEnabled)
|
||||
this->load ();
|
||||
}
|
||||
|
||||
void CSound::load ()
|
||||
@ -16,7 +19,7 @@ void CSound::load ()
|
||||
for (const auto& cur : this->m_sound->getSounds ())
|
||||
{
|
||||
uint32_t filesize = 0;
|
||||
const void* filebuffer = this->getContainer ().readFile (cur, &filesize);
|
||||
const void* filebuffer = this->getContainer ()->readFile (cur, &filesize);
|
||||
|
||||
auto stream = new Audio::CAudioStream (this->getScene ()->getAudioContext (), filebuffer, filesize);
|
||||
|
||||
|
@ -29,7 +29,7 @@ using namespace WallpaperEngine::Assets;
|
||||
namespace WallpaperEngine::Render::Shaders
|
||||
{
|
||||
Compiler::Compiler (
|
||||
const CContainer& container,
|
||||
CContainer* container,
|
||||
std::string filename,
|
||||
Type type,
|
||||
std::map <std::string, int>* combos,
|
||||
@ -50,11 +50,11 @@ namespace WallpaperEngine::Render::Shaders
|
||||
m_baseCombos ()
|
||||
{
|
||||
if (type == Type_Vertex)
|
||||
this->m_content = this->m_container.readVertexShader (this->m_file);
|
||||
this->m_content = this->m_container->readVertexShader (this->m_file);
|
||||
else if (type == Type_Pixel)
|
||||
this->m_content = this->m_container.readFragmentShader (this->m_file);
|
||||
this->m_content = this->m_container->readFragmentShader (this->m_file);
|
||||
else if (type == Type_Include)
|
||||
this->m_content = this->m_container.readIncludeShader (this->m_file);
|
||||
this->m_content = this->m_container->readIncludeShader (this->m_file);
|
||||
|
||||
// clone the combos into the baseCombos to keep track of values that must be embedded no matter what
|
||||
for (const auto& cur : *this->m_combos)
|
||||
@ -650,7 +650,7 @@ namespace WallpaperEngine::Render::Shaders
|
||||
file += ".json";
|
||||
|
||||
std::string tmp = file;
|
||||
std::string patchContents = this->m_container.readFileAsString (file);
|
||||
std::string patchContents = this->m_container->readFileAsString (file);
|
||||
|
||||
json data = json::parse (patchContents);
|
||||
auto patches = data.find ("patches");
|
||||
|
@ -51,7 +51,7 @@ namespace WallpaperEngine::Render::Shaders
|
||||
* @param recursive Whether the compiler should add base definitions or not
|
||||
*/
|
||||
Compiler (
|
||||
const CContainer& container,
|
||||
CContainer* container,
|
||||
std::string filename,
|
||||
Type type,
|
||||
std::map<std::string, int>* combos,
|
||||
@ -264,7 +264,7 @@ namespace WallpaperEngine::Render::Shaders
|
||||
/**
|
||||
* The container to load files from
|
||||
*/
|
||||
const CContainer& m_container;
|
||||
CContainer* m_container;
|
||||
/**
|
||||
* List of textures that the shader expects (inferred from sampler2D and it's JSON data)
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user