effects: Fix resource file reading for builtin effects

Currently, the invert effect doesn't work because it can't load its
fragment shader because builtin effects are static libs. We need
Q_INIT_RESOURCE() before reading shader code.

This modularizes builtin effects more, which makes easier to add and
remove builtin effects, as well as allows to have per effect resources.

Technically, changing the inner workings of the ShaderManager is an
API incompatible change, but ShaderManager::generateShaderFromResources()
can be used only by builtin effects so it's okay.

ShaderManager::generateShaderFromResources() had to be changed because
two resource files can't share the same prefix. Appending "_core" was
inspired by QtQuick.
master
Vlad Zahorodnii 3 years ago
parent 11763bb32c
commit 754e0d8f6e

@ -169,8 +169,6 @@ set(kwin4_effect_builtins_sources
../service_utils.cpp
)
qt5_add_resources(kwin4_effect_builtins_sources shaders.qrc)
add_library(kwin4_effect_builtins STATIC ${kwin4_effect_builtins_sources})
kcoreaddons_target_static_plugins(kwin4_effect_builtins "kwin/effects/plugins" LINK_OPTION "PRIVATE")
target_link_libraries(kwin4_effect_builtins PRIVATE

@ -3,6 +3,7 @@
set(invert_SOURCES
invert.cpp
invert.qrc
main.cpp
)

@ -22,6 +22,12 @@
Q_LOGGING_CATEGORY(KWIN_INVERT, "kwin_effect_invert", QtWarningMsg)
static void ensureResources()
{
// Must initialize resources manually because the effect is a static lib.
Q_INIT_RESOURCE(invert);
}
namespace KWin
{
@ -62,9 +68,10 @@ bool InvertEffect::supported()
bool InvertEffect::loadData()
{
ensureResources();
m_inited = true;
m_shader = ShaderManager::instance()->generateShaderFromResources(ShaderTrait::MapTexture, QString(), QStringLiteral("invert.frag"));
m_shader = ShaderManager::instance()->generateShaderFromResources(ShaderTrait::MapTexture, QString(), QStringLiteral(":/effects/invert/shaders/invert.frag"));
if (!m_shader->isValid()) {
qCCritical(KWIN_INVERT) << "The shader failed to load!";
return false;

@ -0,0 +1,6 @@
<!DOCTYPE RCC><RCC version="1.0">
<qresource prefix="/effects/invert/">
<file>shaders/invert.frag</file>
<file>shaders/invert_core.frag</file>
</qresource>
</RCC>

@ -3,6 +3,7 @@
set(lookingglass_SOURCES
lookingglass.cpp
lookingglass.qrc
main.cpp
)

@ -29,6 +29,12 @@
Q_LOGGING_CATEGORY(KWIN_LOOKINGGLASS, "kwin_effect_lookingglass", QtWarningMsg)
static void ensureResources()
{
// Must initialize resources manually because the effect is a static lib.
Q_INIT_RESOURCE(lookingglass);
}
namespace KWin
{
@ -91,6 +97,8 @@ void LookingGlassEffect::reconfigure(ReconfigureFlags)
bool LookingGlassEffect::loadData()
{
ensureResources();
const QSize screenSize = effects->virtualScreenSize();
int texw = screenSize.width();
int texh = screenSize.height();
@ -106,7 +114,7 @@ bool LookingGlassEffect::loadData()
return false;
}
m_shader = ShaderManager::instance()->generateShaderFromResources(ShaderTrait::MapTexture, QString(), QStringLiteral("lookingglass.frag"));
m_shader = ShaderManager::instance()->generateShaderFromResources(ShaderTrait::MapTexture, QString(), QStringLiteral(":/effects/lookingglass/shaders/lookingglass.frag"));
if (m_shader->isValid()) {
ShaderBinder binder(m_shader);
m_shader->setUniform("u_textureSize", QVector2D(screenSize.width(), screenSize.height()));

@ -0,0 +1,7 @@
<!DOCTYPE RCC><RCC version="1.0">
<qresource prefix="/effects/lookingglass/">
<file>shaders/lookingglass.frag</file>
<file>shaders/lookingglass_core.frag</file>
</qresource>
</RCC>

@ -1,13 +0,0 @@
<!DOCTYPE RCC><RCC version="1.0">
<qresource prefix="/effect-shaders-1.10">
<file alias="invert.frag">invert/data/1.10/invert.frag</file>
<file alias="lookingglass.frag">lookingglass/data/1.10/lookingglass.frag</file>
<file alias="blinking-startup-fragment.glsl">startupfeedback/data/1.10/blinking-startup-fragment.glsl</file>
</qresource>
<qresource prefix="/effect-shaders-1.40">
<file alias="invert.frag">invert/data/1.40/invert.frag</file>
<file alias="lookingglass.frag">lookingglass/data/1.40/lookingglass.frag</file>
<file alias="blinking-startup-fragment.glsl">startupfeedback/data/1.40/blinking-startup-fragment.glsl</file>
</qresource>
</RCC>

@ -5,6 +5,7 @@
set(startupfeedback_SOURCES
main.cpp
startupfeedback.cpp
startupfeedback.qrc
)
kwin4_add_effect_module(kwin4_effect_startupfeedback ${startupfeedback_SOURCES})

@ -30,6 +30,12 @@
Q_LOGGING_CATEGORY(KWIN_STARTUPFEEDBACK, "kwin_effect_startupfeedback", QtWarningMsg)
static void ensureResources()
{
// Must initialize resources manually because the effect is a static lib.
Q_INIT_RESOURCE(startupfeedback);
}
namespace KWin
{
@ -145,7 +151,8 @@ void StartupFeedbackEffect::reconfigure(Effect::ReconfigureFlags flags)
else if (busyBlinking) {
m_type = BlinkingFeedback;
if (effects->compositingType() == OpenGLCompositing) {
m_blinkingShader.reset(ShaderManager::instance()->generateShaderFromResources(ShaderTrait::MapTexture, QString(), QStringLiteral("blinking-startup-fragment.glsl")));
ensureResources();
m_blinkingShader.reset(ShaderManager::instance()->generateShaderFromResources(ShaderTrait::MapTexture, QString(), QStringLiteral(":/effects/startupfeedback/shaders/blinking-startup.frag")));
if (m_blinkingShader->isValid()) {
qCDebug(KWIN_STARTUPFEEDBACK) << "Blinking Shader is valid";
} else {

@ -0,0 +1,7 @@
<!DOCTYPE RCC><RCC version="1.0">
<qresource prefix="/effects/startupfeedback/">
<file>shaders/blinking-startup.frag</file>
<file>shaders/blinking-startup_core.frag</file>
</qresource>
</RCC>

@ -618,12 +618,6 @@ void ShaderManager::cleanup()
ShaderManager::ShaderManager()
{
const qint64 coreVersionNumber = GLPlatform::instance()->isGLES() ? kVersionNumber(3, 0) : kVersionNumber(1, 40);
if (GLPlatform::instance()->glslVersion() >= coreVersionNumber) {
m_resourcePath = QStringLiteral(":/effect-shaders-1.40/");
} else {
m_resourcePath = QStringLiteral(":/effect-shaders-1.10/");
}
}
ShaderManager::~ShaderManager()
@ -783,26 +777,49 @@ GLShader *ShaderManager::generateCustomShader(ShaderTraits traits, const QByteAr
return shader;
}
static QString resolveShaderFilePath(const QString &filePath)
{
QString suffix;
QString extension;
const qint64 coreVersionNumber = GLPlatform::instance()->isGLES() ? kVersionNumber(3, 0) : kVersionNumber(1, 40);
if (GLPlatform::instance()->glslVersion() >= coreVersionNumber) {
suffix = QStringLiteral("_core");
}
if (filePath.endsWith(QStringLiteral(".frag"))) {
extension = QStringLiteral(".frag");
} else if (filePath.endsWith(QStringLiteral(".vert"))) {
extension = QStringLiteral(".vert");
} else {
qCWarning(LIBKWINGLUTILS) << filePath << "must end either with .vert or .frag";
return QString();
}
const QString prefix = filePath.chopped(extension.size());
return prefix + suffix + extension;
}
GLShader *ShaderManager::generateShaderFromResources(ShaderTraits traits, const QString &vertexFile, const QString &fragmentFile)
{
auto loadShaderFile = [this] (const QString &fileName) {
QFile file(m_resourcePath + fileName);
auto loadShaderFile = [](const QString &filePath) {
QFile file(filePath);
if (file.open(QIODevice::ReadOnly)) {
return file.readAll();
}
qCCritical(LIBKWINGLUTILS) << "Failed to read shader " << fileName;
qCCritical(LIBKWINGLUTILS) << "Failed to read shader " << filePath;
return QByteArray();
};
QByteArray vertexSource;
QByteArray fragmentSource;
if (!vertexFile.isEmpty()) {
vertexSource = loadShaderFile(vertexFile);
vertexSource = loadShaderFile(resolveShaderFilePath(vertexFile));
if (vertexSource.isEmpty()) {
return new GLShader();
}
}
if (!fragmentFile.isEmpty()) {
fragmentSource = loadShaderFile(fragmentFile);
fragmentSource = loadShaderFile(resolveShaderFilePath(fragmentFile));
if (fragmentSource.isEmpty()) {
return new GLShader();
}

@ -306,7 +306,6 @@ private:
QStack<GLShader*> m_boundShaders;
QHash<ShaderTraits, GLShader *> m_shaderHash;
QString m_resourcePath;
static ShaderManager *s_shaderManager;
};

Loading…
Cancel
Save