add colorspace metadata to surfaces and items, and use it in the OpenGL renderer

master
Xaver Hugl 11 months ago
parent c1b4806962
commit 09278caf48

@ -442,6 +442,16 @@ void Item::markSortedChildItemsDirty()
m_sortedChildItems.reset();
}
const ColorDescription &Item::colorDescription() const
{
return m_colorDescription;
}
void Item::setColorDescription(const ColorDescription &description)
{
m_colorDescription = description;
}
} // namespace KWin
#include "moc_item.cpp"

@ -6,6 +6,7 @@
#pragma once
#include "libkwineffects/colorspace.h"
#include "libkwineffects/kwineffects.h"
#include "libkwineffects/kwinglobals.h"
@ -111,6 +112,7 @@ public:
WindowQuadList quads() const;
virtual void preprocess();
const ColorDescription &colorDescription() const;
Q_SIGNALS:
void childAdded(Item *item);
@ -132,6 +134,7 @@ Q_SIGNALS:
protected:
virtual WindowQuadList buildQuads() const;
void discardQuads();
void setColorDescription(const ColorDescription &description);
private:
void addChild(Item *item);
@ -159,6 +162,7 @@ private:
QMap<SceneDelegate *, QRegion> m_repaints;
mutable std::optional<WindowQuadList> m_quads;
mutable std::optional<QList<Item *>> m_sortedChildItems;
ColorDescription m_colorDescription = ColorDescription::sRGB;
};
} // namespace KWin

@ -175,6 +175,7 @@ void ItemRendererOpenGL::createRenderNode(Item *item, RenderContext *context)
.hasAlpha = true,
.coordinateType = UnnormalizedCoordinates,
.scale = scale,
.colorDescription = item->colorDescription(),
});
}
} else if (auto decorationItem = qobject_cast<DecorationItem *>(item)) {
@ -188,6 +189,7 @@ void ItemRendererOpenGL::createRenderNode(Item *item, RenderContext *context)
.hasAlpha = true,
.coordinateType = UnnormalizedCoordinates,
.scale = scale,
.colorDescription = item->colorDescription(),
});
}
} else if (auto surfaceItem = qobject_cast<SurfaceItem *>(item)) {
@ -202,6 +204,7 @@ void ItemRendererOpenGL::createRenderNode(Item *item, RenderContext *context)
.hasAlpha = pixmap->hasAlphaChannel(),
.coordinateType = NormalizedCoordinates,
.scale = scale,
.colorDescription = item->colorDescription(),
});
}
}
@ -215,6 +218,7 @@ void ItemRendererOpenGL::createRenderNode(Item *item, RenderContext *context)
.hasAlpha = imageItem->image().hasAlphaChannel(),
.coordinateType = NormalizedCoordinates,
.scale = scale,
.colorDescription = item->colorDescription(),
});
}
}
@ -281,10 +285,7 @@ void ItemRendererOpenGL::renderItem(const RenderTarget &renderTarget, const Rend
return;
}
ShaderTraits shaderTraits = ShaderTrait::MapTexture;
if (renderTarget.colorDescription() != ColorDescription::sRGB) {
shaderTraits |= ShaderTrait::TransformColorspace;
}
ShaderTraits shaderTraits = ShaderTrait::MapTexture | ShaderTrait::TransformColorspace;
if (data.brightness() != 1.0) {
shaderTraits |= ShaderTrait::Modulate;
@ -330,9 +331,6 @@ void ItemRendererOpenGL::renderItem(const RenderTarget &renderTarget, const Rend
shader->setUniform(GLShader::Saturation, data.saturation());
shader->setUniform(GLShader::Vec3Uniform::PrimaryBrightness, QVector3D(toXYZ(1, 0), toXYZ(1, 1), toXYZ(1, 2)));
}
if (shaderTraits & ShaderTrait::TransformColorspace) {
shader->setColorspaceUniformsFromSRGB(renderTarget.colorDescription());
}
if (renderContext.hardwareClipping) {
glEnable(GL_SCISSOR_TEST);
@ -363,6 +361,7 @@ void ItemRendererOpenGL::renderItem(const RenderTarget &renderTarget, const Rend
modulate(renderNode.opacity, data.brightness()));
opacity = renderNode.opacity;
}
shader->setColorspaceUniforms(renderNode.colorDescription, renderTarget.colorDescription());
renderNode.texture->bind();

@ -27,6 +27,7 @@ public:
bool hasAlpha = false;
TextureCoordinateType coordinateType = UnnormalizedCoordinates;
qreal scale = 1.0;
ColorDescription colorDescription;
};
struct RenderContext

@ -40,6 +40,8 @@ SurfaceItemWayland::SurfaceItemWayland(SurfaceInterface *surface, Scene *scene,
this, &SurfaceItemWayland::addDamage);
connect(surface, &SurfaceInterface::childSubSurfaceRemoved,
this, &SurfaceItemWayland::handleChildSubSurfaceRemoved);
connect(surface, &SurfaceInterface::colorDescriptionChanged,
this, &SurfaceItemWayland::handleColorDescriptionChanged);
SubSurfaceInterface *subsurface = surface->subSurface();
if (subsurface) {
@ -162,7 +164,12 @@ std::unique_ptr<SurfacePixmap> SurfaceItemWayland::createPixmap()
ContentType SurfaceItemWayland::contentType() const
{
return m_surface->contentType();
return m_surface ? m_surface->contentType() : ContentType::None;
}
void SurfaceItemWayland::handleColorDescriptionChanged()
{
setColorDescription(m_surface->colorDescription());
}
SurfacePixmapWayland::SurfacePixmapWayland(SurfaceItemWayland *item, QObject *parent)

@ -46,6 +46,7 @@ private Q_SLOTS:
void handleChildSubSurfacesChanged();
void handleSubSurfacePositionChanged();
void handleSubSurfaceMappedChanged();
void handleColorDescriptionChanged();
protected:
std::unique_ptr<SurfacePixmap> createPixmap() override;

@ -639,6 +639,10 @@ void SurfaceState::mergeInto(SurfaceState *target)
target->presentationHint = presentationHint;
target->tearingIsSet = true;
}
if (colorDescriptionIsSet) {
target->colorDescription = colorDescription;
target->colorDescriptionIsSet = true;
}
*this = SurfaceState{};
serial = target->serial;
@ -657,6 +661,7 @@ void SurfaceInterfacePrivate::applyState(SurfaceState *next)
const bool slideChanged = next->slideIsSet;
const bool subsurfaceOrderChanged = next->subsurfaceOrderChanged;
const bool visibilityChanged = bufferChanged && bool(current->buffer) != bool(next->buffer);
const bool colorDescriptionChanged = next->colorDescriptionIsSet;
const QSizeF oldSurfaceSize = surfaceSize;
const QSize oldBufferSize = bufferSize;
@ -749,6 +754,9 @@ void SurfaceInterfacePrivate::applyState(SurfaceState *next)
if (subsurfaceOrderChanged) {
Q_EMIT q->childSubSurfacesChanged();
}
if (colorDescriptionChanged) {
Q_EMIT q->colorDescriptionChanged();
}
if (bufferChanged) {
if (current->buffer && (!current->damage.isEmpty() || !current->bufferDamage.isEmpty())) {
@ -1138,6 +1146,11 @@ PresentationHint SurfaceInterface::presentationHint() const
return d->current->presentationHint;
}
const ColorDescription &SurfaceInterface::colorDescription() const
{
return d->current->colorDescription;
}
void SurfaceInterface::setPreferredBufferScale(qreal scale)
{
if (scale == d->preferredBufferScale) {

@ -7,6 +7,7 @@
#pragma once
#include "core/output.h"
#include "libkwineffects/colorspace.h"
#include <QMatrix4x4>
#include <QObject>
@ -371,6 +372,8 @@ public:
Transaction *lastTransaction() const;
void setLastTransaction(Transaction *transaction);
const ColorDescription &colorDescription() const;
Q_SIGNALS:
/**
* This signal is emitted when the underlying wl_surface resource is about to be freed.
@ -456,6 +459,8 @@ Q_SIGNALS:
*/
void inhibitsIdleChanged();
void colorDescriptionChanged();
/**
* Emitted when the Surface has been committed.
*

@ -52,6 +52,7 @@ struct SurfaceState
bool bufferTransformIsSet = false;
bool contentTypeIsSet = false;
bool tearingIsSet = false;
bool colorDescriptionIsSet = false;
qint32 bufferScale = 1;
OutputTransform bufferTransform = OutputTransform::Normal;
wl_list frameCallbacks;
@ -63,6 +64,7 @@ struct SurfaceState
QPointer<SlideInterface> slide;
ContentType contentType = ContentType::None;
PresentationHint presentationHint = PresentationHint::VSync;
ColorDescription colorDescription = ColorDescription::sRGB;
struct
{

Loading…
Cancel
Save