diff --git a/src/scene/item.cpp b/src/scene/item.cpp index 67955851b6..839e245204 100644 --- a/src/scene/item.cpp +++ b/src/scene/item.cpp @@ -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" diff --git a/src/scene/item.h b/src/scene/item.h index dc85d24684..1e6f515487 100644 --- a/src/scene/item.h +++ b/src/scene/item.h @@ -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 m_repaints; mutable std::optional m_quads; mutable std::optional> m_sortedChildItems; + ColorDescription m_colorDescription = ColorDescription::sRGB; }; } // namespace KWin diff --git a/src/scene/itemrenderer_opengl.cpp b/src/scene/itemrenderer_opengl.cpp index 23c0c493ff..388431ace1 100644 --- a/src/scene/itemrenderer_opengl.cpp +++ b/src/scene/itemrenderer_opengl.cpp @@ -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(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(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(); diff --git a/src/scene/itemrenderer_opengl.h b/src/scene/itemrenderer_opengl.h index 87a4ffd440..87d7ab71e5 100644 --- a/src/scene/itemrenderer_opengl.h +++ b/src/scene/itemrenderer_opengl.h @@ -27,6 +27,7 @@ public: bool hasAlpha = false; TextureCoordinateType coordinateType = UnnormalizedCoordinates; qreal scale = 1.0; + ColorDescription colorDescription; }; struct RenderContext diff --git a/src/scene/surfaceitem_wayland.cpp b/src/scene/surfaceitem_wayland.cpp index f2fbf971cc..2d60505adb 100644 --- a/src/scene/surfaceitem_wayland.cpp +++ b/src/scene/surfaceitem_wayland.cpp @@ -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 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) diff --git a/src/scene/surfaceitem_wayland.h b/src/scene/surfaceitem_wayland.h index dfc1544866..a0c4914308 100644 --- a/src/scene/surfaceitem_wayland.h +++ b/src/scene/surfaceitem_wayland.h @@ -46,6 +46,7 @@ private Q_SLOTS: void handleChildSubSurfacesChanged(); void handleSubSurfacePositionChanged(); void handleSubSurfaceMappedChanged(); + void handleColorDescriptionChanged(); protected: std::unique_ptr createPixmap() override; diff --git a/src/wayland/surface.cpp b/src/wayland/surface.cpp index c02f6b6d7c..8853a98330 100644 --- a/src/wayland/surface.cpp +++ b/src/wayland/surface.cpp @@ -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) { diff --git a/src/wayland/surface.h b/src/wayland/surface.h index d1b785cf89..5d14344f81 100644 --- a/src/wayland/surface.h +++ b/src/wayland/surface.h @@ -7,6 +7,7 @@ #pragma once #include "core/output.h" +#include "libkwineffects/colorspace.h" #include #include @@ -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. * diff --git a/src/wayland/surface_p.h b/src/wayland/surface_p.h index d1425a3aa0..3960f53c5a 100644 --- a/src/wayland/surface_p.h +++ b/src/wayland/surface_p.h @@ -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 slide; ContentType contentType = ContentType::None; PresentationHint presentationHint = PresentationHint::VSync; + ColorDescription colorDescription = ColorDescription::sRGB; struct {