Phosphor
Qt6 / Wayland library suite for window-management tools
 
Loading...
Searching...
No Matches
AnimationUniformExtension.h
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2026 fuddlesworth
2// SPDX-License-Identifier: LGPL-2.1-or-later
3
4#pragma once
5
6#include <PhosphorAnimation/phosphoranimation_export.h>
7
10
11#include <QMutex>
12#include <QMutexLocker>
13#include <QSizeF>
14#include <QVector4D>
15
16#include <atomic>
17#include <cstring>
18
19namespace PhosphorAnimation {
20
68{
69public:
71 {
72 std::memset(&m_data, 0, sizeof(m_data));
73 // iAnchorRectInTexture defaults to the (0, 0, 1, 1) identity —
74 // a card-sized anchor with no capture margin. memset leaves it
75 // (0, 0, 0, 0); a zero width/height would collapse every
76 // surfaceColor sample to the texture's corner texel (and divide
77 // animation.vert's remap by zero) before the first geometry
78 // sync lands a real value.
79 m_data.iAnchorRectInTexture[2] = 1.0f;
80 m_data.iAnchorRectInTexture[3] = 1.0f;
81 }
82
83 int extensionSize() const override
84 {
85 return static_cast<int>(sizeof(m_data));
86 }
87
88 void write(char* buffer, int offset) const override
89 {
90 QMutexLocker lock(&m_mutex);
91 std::memcpy(buffer + offset, &m_data, sizeof(m_data));
92 }
93
94 bool isDirty() const override
95 {
96 return m_dirty.load(std::memory_order_acquire);
97 }
98
99 void clearDirty() override
100 {
101 m_dirty.store(false, std::memory_order_release);
102 }
103
113 bool requiresPhysicalResolution() const override
114 {
115 return false;
116 }
117
130 void setISurfaceScreenPos(const QVector4D& pos)
131 {
132 QMutexLocker lock(&m_mutex);
133 if (m_data.iSurfaceScreenPos[0] == pos.x() && m_data.iSurfaceScreenPos[1] == pos.y()
134 && m_data.iSurfaceScreenPos[2] == pos.z() && m_data.iSurfaceScreenPos[3] == pos.w()) {
135 return;
136 }
137 m_data.iSurfaceScreenPos[0] = static_cast<float>(pos.x());
138 m_data.iSurfaceScreenPos[1] = static_cast<float>(pos.y());
139 m_data.iSurfaceScreenPos[2] = static_cast<float>(pos.z());
140 m_data.iSurfaceScreenPos[3] = static_cast<float>(pos.w());
141 m_dirty.store(true, std::memory_order_release);
142 }
143
155 void setIAnchorSize(const QSizeF& size)
156 {
157 QMutexLocker lock(&m_mutex);
158 const float w = static_cast<float>(size.width());
159 const float h = static_cast<float>(size.height());
160 if (m_data.iAnchorSize[0] == w && m_data.iAnchorSize[1] == h) {
161 return;
162 }
163 m_data.iAnchorSize[0] = w;
164 m_data.iAnchorSize[1] = h;
165 m_dirty.store(true, std::memory_order_release);
166 }
167
192 void setIAnchorPosInFbo(const QPointF& pos)
193 {
194 QMutexLocker lock(&m_mutex);
195 const float x = static_cast<float>(pos.x());
196 const float y = static_cast<float>(pos.y());
197 if (m_data.iAnchorPosInFbo[0] == x && m_data.iAnchorPosInFbo[1] == y) {
198 return;
199 }
200 m_data.iAnchorPosInFbo[0] = x;
201 m_data.iAnchorPosInFbo[1] = y;
202 m_dirty.store(true, std::memory_order_release);
203 }
204
219 void setIAnchorRectInTexture(const QVector4D& rect)
220 {
221 QMutexLocker lock(&m_mutex);
222 if (m_data.iAnchorRectInTexture[0] == rect.x() && m_data.iAnchorRectInTexture[1] == rect.y()
223 && m_data.iAnchorRectInTexture[2] == rect.z() && m_data.iAnchorRectInTexture[3] == rect.w()) {
224 return;
225 }
226 m_data.iAnchorRectInTexture[0] = static_cast<float>(rect.x());
227 m_data.iAnchorRectInTexture[1] = static_cast<float>(rect.y());
228 m_data.iAnchorRectInTexture[2] = static_cast<float>(rect.z());
229 m_data.iAnchorRectInTexture[3] = static_cast<float>(rect.w());
230 m_dirty.store(true, std::memory_order_release);
231 }
232
233private:
241 struct alignas(16) AnimationExtensionData
242 {
243 float iSurfaceScreenPos[4]; // offset 0 (16 bytes), UBO offset 672 = 0 + sizeof(BaseUniforms)
244 float iAnchorSize[2]; // offset 16 (8 bytes), UBO offset 688
245 float iAnchorPosInFbo[2]; // offset 24 (8 bytes), UBO offset 696. Anchor's top-left
246 // position inside the shader item's FBO, in logical pixels.
247 // See setIAnchorPosInFbo's docstring for the per-extent math
248 // contract this enables.
249 float iAnchorRectInTexture[4]; // offset 32 (16 bytes), UBO offset 704. Card's UV sub-rect
250 // within uTexture0. offset 32 is already 16-aligned, so
251 // std140 inserts no pad before it. See
252 // setIAnchorRectInTexture's docstring.
253 };
254 static_assert(sizeof(AnimationExtensionData) == 48,
255 "AnimationExtensionData must be exactly 48 bytes — std140 vec4-aligned, no trailing pad");
256 static_assert(sizeof(PhosphorShaders::BaseUniforms) + sizeof(AnimationExtensionData) == 720,
257 "BaseUniforms + AnimationExtensionData must total 720 bytes — matches the trailing-field "
258 "layout declared in data/animations/shared/animation_uniforms.glsl");
259 static_assert(sizeof(PhosphorShaders::BaseUniforms) == 672,
260 "BaseUniforms must remain at 672 bytes — growing it shifts ZoneUniformExtension's "
261 "zoneRects offset and breaks every zone shader compiled against `data/shaders/shared/"
262 "common.glsl`. AnimationUniformExtension exists precisely to avoid that growth.");
263
264 AnimationExtensionData m_data;
265 mutable QMutex m_mutex;
266 std::atomic<bool> m_dirty{true};
267};
268
269} // namespace PhosphorAnimation
IUniformExtension that appends animation-shader spatial uniforms after PhosphorShaders::BaseUniforms ...
Definition AnimationUniformExtension.h:68
void setIAnchorPosInFbo(const QPointF &pos)
Anchor's top-left position inside the shader item's FBO, in logical pixels.
Definition AnimationUniformExtension.h:192
int extensionSize() const override
Size in bytes of the extension region (must respect std140 alignment).
Definition AnimationUniformExtension.h:83
void clearDirty() override
Mark as clean after a successful write.
Definition AnimationUniformExtension.h:99
AnimationUniformExtension()
Definition AnimationUniformExtension.h:70
bool requiresPhysicalResolution() const override
Animation shaders pair iResolution with logical-pixel extension fields (iAnchorSize,...
Definition AnimationUniformExtension.h:113
void setISurfaceScreenPos(const QVector4D &pos)
Surface origin in logical screen pixels (.xy) plus host screen dimensions (.zw).
Definition AnimationUniformExtension.h:130
void write(char *buffer, int offset) const override
Write extension data into buffer starting at offset.
Definition AnimationUniformExtension.h:88
bool isDirty() const override
Whether the extension data has changed since the last write.
Definition AnimationUniformExtension.h:94
void setIAnchorSize(const QSizeF &size)
Anchor (card) pixel size in logical pixels.
Definition AnimationUniformExtension.h:155
void setIAnchorRectInTexture(const QVector4D &rect)
Card's UV sub-rect within uTexture0, as (x, y, width, height) in the captured texture's [0,...
Definition AnimationUniformExtension.h:219
Interface for appending custom uniform data after the base UBO layout.
Definition IUniformExtension.h:18
Definition AnimatedValue.h:31
GPU uniform buffer layout following std140 rules (base region).
Definition BaseUniforms.h:37