Phosphor
Qt6 / Wayland library suite for window-management tools
 
Loading...
Searching...
No Matches
ZoneUniformExtension.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
8
9#include <QMutex>
10#include <QMutexLocker>
11#include <atomic>
12#include <cstring>
13
14namespace PhosphorRendering {
15
33{
34public:
36 {
37 std::memset(&m_data, 0, sizeof(m_data));
38 }
39
40 int extensionSize() const override
41 {
42 return static_cast<int>(sizeof(m_data));
43 }
44
45 void write(char* buffer, int offset) const override
46 {
47 QMutexLocker lock(&m_mutex);
48 std::memcpy(buffer + offset, &m_data, sizeof(m_data));
49 }
50
51 bool isDirty() const override
52 {
53 return m_dirty.load(std::memory_order_acquire);
54 }
55
56 void clearDirty() override
57 {
58 m_dirty.store(false, std::memory_order_release);
59 }
60
64 void updateFromZones(const QVector<ZoneData>& zones)
65 {
66 QMutexLocker lock(&m_mutex);
67 for (int i = 0; i < MaxZones; ++i) {
68 if (i < zones.size()) {
69 const ZoneData& zone = zones[i];
70 m_data.zoneRects[i][0] = static_cast<float>(zone.rect.x());
71 m_data.zoneRects[i][1] = static_cast<float>(zone.rect.y());
72 m_data.zoneRects[i][2] = static_cast<float>(zone.rect.width());
73 m_data.zoneRects[i][3] = static_cast<float>(zone.rect.height());
74 m_data.zoneFillColors[i][0] = static_cast<float>(zone.fillColor.redF());
75 m_data.zoneFillColors[i][1] = static_cast<float>(zone.fillColor.greenF());
76 m_data.zoneFillColors[i][2] = static_cast<float>(zone.fillColor.blueF());
77 m_data.zoneFillColors[i][3] = static_cast<float>(zone.fillColor.alphaF());
78 m_data.zoneBorderColors[i][0] = static_cast<float>(zone.borderColor.redF());
79 m_data.zoneBorderColors[i][1] = static_cast<float>(zone.borderColor.greenF());
80 m_data.zoneBorderColors[i][2] = static_cast<float>(zone.borderColor.blueF());
81 m_data.zoneBorderColors[i][3] = static_cast<float>(zone.borderColor.alphaF());
82 m_data.zoneParams[i][0] = zone.borderRadius;
83 m_data.zoneParams[i][1] = zone.borderWidth;
84 m_data.zoneParams[i][2] = zone.isHighlighted ? 1.0f : 0.0f;
85 m_data.zoneParams[i][3] = static_cast<float>(zone.zoneNumber);
86 } else {
87 std::memset(m_data.zoneRects[i], 0, sizeof(m_data.zoneRects[i]));
88 std::memset(m_data.zoneFillColors[i], 0, sizeof(m_data.zoneFillColors[i]));
89 std::memset(m_data.zoneBorderColors[i], 0, sizeof(m_data.zoneBorderColors[i]));
90 std::memset(m_data.zoneParams[i], 0, sizeof(m_data.zoneParams[i]));
91 }
92 }
93 m_dirty.store(true, std::memory_order_release);
94 }
95
96private:
98 struct alignas(16) ZoneExtensionData
99 {
100 float zoneRects[MaxZones][4];
101 float zoneFillColors[MaxZones][4];
102 float zoneBorderColors[MaxZones][4];
103 float zoneParams[MaxZones][4];
104 };
105
106 static_assert(sizeof(ZoneExtensionData) == MaxZones * 4 * sizeof(float) * 4,
107 "ZoneExtensionData must be MaxZones * 4 arrays * 4 floats");
108 // Field offsets must match the GLSL UBO layout in common.glsl exactly.
109 // Reordering or inserting fields here silently breaks shader rendering
110 // (no compile error, just wrong colors/positions on every zone).
111 static_assert(offsetof(ZoneExtensionData, zoneRects) == 0, "zoneRects must be first");
112 static_assert(offsetof(ZoneExtensionData, zoneFillColors) == sizeof(float[MaxZones][4]),
113 "zoneFillColors must follow zoneRects with no gap");
114 static_assert(offsetof(ZoneExtensionData, zoneBorderColors) == 2 * sizeof(float[MaxZones][4]),
115 "zoneBorderColors must follow zoneFillColors with no gap");
116 static_assert(offsetof(ZoneExtensionData, zoneParams) == 3 * sizeof(float[MaxZones][4]),
117 "zoneParams must follow zoneBorderColors with no gap");
118 // Verify ZoneExtensionData is binary-identical to the zone region of
119 // ZoneShaderUniforms (BaseUniforms + this == ZoneShaderUniforms layout).
120 static_assert(sizeof(ZoneExtensionData) == sizeof(ZoneShaderUniforms) - sizeof(PhosphorShaders::BaseUniforms),
121 "ZoneExtensionData size must match ZoneShaderUniforms zone region size");
122
123 ZoneExtensionData m_data;
124 mutable QMutex m_mutex;
125 std::atomic<bool> m_dirty{true};
126};
127
128} // namespace PhosphorRendering
IUniformExtension implementation for zone data.
Definition ZoneUniformExtension.h:33
ZoneUniformExtension()
Definition ZoneUniformExtension.h:35
void write(char *buffer, int offset) const override
Write extension data into buffer starting at offset.
Definition ZoneUniformExtension.h:45
bool isDirty() const override
Whether the extension data has changed since the last write.
Definition ZoneUniformExtension.h:51
int extensionSize() const override
Size in bytes of the extension region (must respect std140 alignment).
Definition ZoneUniformExtension.h:40
void updateFromZones(const QVector< ZoneData > &zones)
Update zone data from a vector of ZoneData.
Definition ZoneUniformExtension.h:64
void clearDirty() override
Mark as clean after a successful write.
Definition ZoneUniformExtension.h:56
Interface for appending custom uniform data after the base UBO layout.
Definition IUniformExtension.h:18
Definition ShaderCompiler.h:15
constexpr int MaxZones
Maximum number of zones the zone-aware UBO supports.
Definition ZoneShaderCommon.h:23
Per-zone payload pushed into the UBO each frame.
Definition ZoneShaderCommon.h:86
float borderWidth
Definition ZoneShaderCommon.h:91
QRectF rect
Definition ZoneShaderCommon.h:87
QColor borderColor
Definition ZoneShaderCommon.h:89
int zoneNumber
Definition ZoneShaderCommon.h:93
QColor fillColor
Definition ZoneShaderCommon.h:88
float borderRadius
Definition ZoneShaderCommon.h:90
bool isHighlighted
Definition ZoneShaderCommon.h:92
GPU uniform buffer layout following std140 rules (base region).
Definition BaseUniforms.h:37