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 <QPointF>
14#include <QSizeF>
15#include <QVector4D>
16
17#include <atomic>
18#include <cstring>
19
20namespace PhosphorAnimation {
21
73{
74public:
76 {
77 std::memset(&m_data, 0, sizeof(m_data));
78 // iAnchorRectInTexture defaults to the (0, 0, 1, 1) identity —
79 // a card-sized anchor with no capture margin. memset leaves it
80 // (0, 0, 0, 0); a zero width/height would collapse every
81 // surfaceColor sample to the texture's corner texel (and divide
82 // animation.vert's remap by zero) before the first geometry
83 // sync lands a real value.
84 m_data.iAnchorRectInTexture[2] = 1.0f;
85 m_data.iAnchorRectInTexture[3] = 1.0f;
86 }
87
88 int extensionSize() const override
89 {
90 return static_cast<int>(sizeof(m_data));
91 }
92
93 void write(char* buffer, int offset) const override
94 {
95 QMutexLocker lock(&m_mutex);
96 std::memcpy(buffer + offset, &m_data, sizeof(m_data));
97 }
98
99 bool isDirty() const override
100 {
101 return m_dirty.load(std::memory_order_acquire);
102 }
103
104 void clearDirty() override
105 {
106 m_dirty.store(false, std::memory_order_release);
107 }
108
118 bool requiresPhysicalResolution() const override
119 {
120 return false;
121 }
122
136 void setISurfaceScreenPos(const QVector4D& pos)
137 {
138 QMutexLocker lock(&m_mutex);
139 if (m_data.iSurfaceScreenPos[0] == pos.x() && m_data.iSurfaceScreenPos[1] == pos.y()
140 && m_data.iSurfaceScreenPos[2] == pos.z() && m_data.iSurfaceScreenPos[3] == pos.w()) {
141 return;
142 }
143 m_data.iSurfaceScreenPos[0] = static_cast<float>(pos.x());
144 m_data.iSurfaceScreenPos[1] = static_cast<float>(pos.y());
145 m_data.iSurfaceScreenPos[2] = static_cast<float>(pos.z());
146 m_data.iSurfaceScreenPos[3] = static_cast<float>(pos.w());
147 m_dirty.store(true, std::memory_order_release);
148 }
149
162 void setIAnchorSize(const QSizeF& size)
163 {
164 QMutexLocker lock(&m_mutex);
165 const float w = static_cast<float>(size.width());
166 const float h = static_cast<float>(size.height());
167 if (m_data.iAnchorSize[0] == w && m_data.iAnchorSize[1] == h) {
168 return;
169 }
170 m_data.iAnchorSize[0] = w;
171 m_data.iAnchorSize[1] = h;
172 m_dirty.store(true, std::memory_order_release);
173 }
174
199 void setIAnchorPosInFbo(const QPointF& pos)
200 {
201 QMutexLocker lock(&m_mutex);
202 const float x = static_cast<float>(pos.x());
203 const float y = static_cast<float>(pos.y());
204 if (m_data.iAnchorPosInFbo[0] == x && m_data.iAnchorPosInFbo[1] == y) {
205 return;
206 }
207 m_data.iAnchorPosInFbo[0] = x;
208 m_data.iAnchorPosInFbo[1] = y;
209 m_dirty.store(true, std::memory_order_release);
210 }
211
226 void setIAnchorRectInTexture(const QVector4D& rect)
227 {
228 QMutexLocker lock(&m_mutex);
229 if (m_data.iAnchorRectInTexture[0] == rect.x() && m_data.iAnchorRectInTexture[1] == rect.y()
230 && m_data.iAnchorRectInTexture[2] == rect.z() && m_data.iAnchorRectInTexture[3] == rect.w()) {
231 return;
232 }
233 m_data.iAnchorRectInTexture[0] = static_cast<float>(rect.x());
234 m_data.iAnchorRectInTexture[1] = static_cast<float>(rect.y());
235 m_data.iAnchorRectInTexture[2] = static_cast<float>(rect.z());
236 m_data.iAnchorRectInTexture[3] = static_cast<float>(rect.w());
237 m_dirty.store(true, std::memory_order_release);
238 }
239
240private:
248 struct alignas(16) AnimationExtensionData
249 {
250 float iSurfaceScreenPos[4]; // offset 0 (16 bytes), UBO offset 672 = 0 + sizeof(BaseUniforms)
251 float iAnchorSize[2]; // offset 16 (8 bytes), UBO offset 688
252 float iAnchorPosInFbo[2]; // offset 24 (8 bytes), UBO offset 696. Anchor's top-left
253 // position inside the shader item's FBO, in logical pixels.
254 // See setIAnchorPosInFbo's docstring for the per-extent math
255 // contract this enables.
256 float iAnchorRectInTexture[4]; // offset 32 (16 bytes), UBO offset 704. Card's UV sub-rect
257 // within uTexture0. offset 32 is already 16-aligned, so
258 // std140 inserts no pad before it. See
259 // setIAnchorRectInTexture's docstring.
260 };
261 static_assert(sizeof(AnimationExtensionData) == 48,
262 "AnimationExtensionData must be exactly 48 bytes — std140 vec4-aligned, no trailing pad");
263 static_assert(sizeof(PhosphorShaders::BaseUniforms) + sizeof(AnimationExtensionData) == 720,
264 "BaseUniforms + AnimationExtensionData must total 720 bytes — matches the trailing-field "
265 "layout declared in data/animations/shared/animation_uniforms.glsl");
266 static_assert(sizeof(PhosphorShaders::BaseUniforms) == 672,
267 "BaseUniforms must remain at 672 bytes — growing it shifts ZoneUniformExtension's "
268 "zoneRects offset and breaks every zone shader compiled against `data/overlays/shared/"
269 "common.glsl`. AnimationUniformExtension exists precisely to avoid that growth.");
270
271 AnimationExtensionData m_data;
272 mutable QMutex m_mutex;
273 std::atomic<bool> m_dirty{true};
274};
275
276} // namespace PhosphorAnimation
IUniformExtension that appends animation-shader spatial uniforms after PhosphorShaders::BaseUniforms ...
Definition AnimationUniformExtension.h:73
void setIAnchorPosInFbo(const QPointF &pos)
Anchor's top-left position inside the shader item's FBO, in logical pixels.
Definition AnimationUniformExtension.h:199
int extensionSize() const override
Size in bytes of the extension region (must respect std140 alignment).
Definition AnimationUniformExtension.h:88
void clearDirty() override
Mark as clean after a successful write.
Definition AnimationUniformExtension.h:104
AnimationUniformExtension()
Definition AnimationUniformExtension.h:75
bool requiresPhysicalResolution() const override
Animation shaders pair iResolution with logical-pixel extension fields (iAnchorSize,...
Definition AnimationUniformExtension.h:118
void setISurfaceScreenPos(const QVector4D &pos)
Surface origin in logical screen pixels (.xy) plus host screen dimensions (.zw).
Definition AnimationUniformExtension.h:136
void write(char *buffer, int offset) const override
Write extension data into buffer starting at offset.
Definition AnimationUniformExtension.h:93
bool isDirty() const override
Whether the extension data has changed since the last write.
Definition AnimationUniformExtension.h:99
void setIAnchorSize(const QSizeF &size)
Anchor (card) pixel size in logical pixels.
Definition AnimationUniformExtension.h:162
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:226
Interface for appending custom uniform data after the base UBO layout.
Definition IUniformExtension.h:18
Definition AnimatedValue.h:32
GPU uniform buffer layout following std140 rules (base region).
Definition BaseUniforms.h:37