add colorspace metadata to surfaces and items, and use it in the OpenGL renderer
This commit is contained in:
parent
c1b4806962
commit
09278caf48
9 changed files with 50 additions and 8 deletions
|
@ -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…
Reference in a new issue