MayaFlux 0.2.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
WindowContainer.hpp
Go to the documentation of this file.
1#pragma once
2
4
5namespace MayaFlux::Core {
6class Window;
7}
8
9namespace MayaFlux::Kakshya {
10
11/**
12 * @class WindowContainer
13 * @brief SignalSourceContainer wrapping a live GLFW/Vulkan window surface.
14 *
15 * Exposes a window's rendered surface as addressable N-dimensional data.
16 * Dimensions follow IMAGE_COLOR convention:
17 * dims[0] → SPATIAL_Y (height)
18 * dims[1] → SPATIAL_X (width)
19 * dims[2] → CHANNEL
20 *
21 * Region semantics:
22 * Regions are registered through the inherited RegionGroup API
23 * (add_region_group / get_all_region_groups / remove_region_group).
24 * load_region() and unload_region() are no-ops on this container — all
25 * surface data is always available after a GPU readback; region selection
26 * is a processor concern, not a container concern.
27 *
28 * Processing model:
29 * - The default processor (WindowAccessProcessor) performs one full-surface
30 * GPU readback per process() call into processed_data[0].
31 * - The processing chain (SpatialRegionProcessor) extracts registered
32 * regions from the readback as separate DataVariant entries.
33 * - get_region_data() crops directly from processed_data[0] if it is
34 * non-empty; returns empty if no readback has occurred yet.
35 * - The container never calls process() itself — callers drive the chain.
36 *
37 * Write semantics (compositing) are deferred to a future processor.
38 */
39class MAYAFLUX_API WindowContainer : public SignalSourceContainer {
40public:
41 /**
42 * @brief Construct from an existing managed window.
43 * @param window Live window whose surface will be addressed as NDData.
44 */
45 explicit WindowContainer(std::shared_ptr<Core::Window> window);
46
47 ~WindowContainer() override = default;
48
53
54 /**
55 * @brief The underlying window.
56 */
57 [[nodiscard]] std::shared_ptr<Core::Window> get_window() const { return m_window; }
58
59 // =========================================================================
60 // NDDimensionalContainer
61 // =========================================================================
62
63 [[nodiscard]] std::vector<DataDimension> get_dimensions() const override;
64 [[nodiscard]] uint64_t get_total_elements() const override;
65 [[nodiscard]] MemoryLayout get_memory_layout() const override;
66 void set_memory_layout(MemoryLayout layout) override;
67
68 /**
69 * @brief Extract data for all regions across all region groups that
70 * spatially intersect @p region.
71 * Crops from the last full-surface readback — no GPU work.
72 * Returns empty if no readback has been performed yet.
73 */
74 [[nodiscard]] std::vector<DataVariant> get_region_data(const Region& region) const override;
75 void set_region_data(const Region& region, const std::vector<DataVariant>& data) override;
76
77 [[nodiscard]] std::vector<DataVariant> get_region_group_data(const RegionGroup& group) const override;
78 [[nodiscard]] std::vector<DataVariant> get_segments_data(const std::vector<RegionSegment>& segments) const override;
79
80 [[nodiscard]] double get_value_at(const std::vector<uint64_t>& coordinates) const override;
81 void set_value_at(const std::vector<uint64_t>& coordinates, double value) override;
82
83 [[nodiscard]] uint64_t coordinates_to_linear_index(const std::vector<uint64_t>& coordinates) const override;
84 [[nodiscard]] std::vector<uint64_t> linear_index_to_coordinates(uint64_t linear_index) const override;
85
86 void clear() override;
87 void lock() override;
88 void unlock() override;
89 bool try_lock() override;
90
91 [[nodiscard]] const void* get_raw_data() const override;
92 [[nodiscard]] bool has_data() const override;
93
94 [[nodiscard]] ContainerDataStructure& get_structure() override { return m_structure; }
95 [[nodiscard]] const ContainerDataStructure& get_structure() const override { return m_structure; }
96 void set_structure(ContainerDataStructure s) override { m_structure = std::move(s); }
97
98 // -------------------------------------------------------------------------
99 // RegionGroup API — primary region registration interface.
100 // -------------------------------------------------------------------------
101
102 void add_region_group(const RegionGroup& group) override;
103 [[nodiscard]] const RegionGroup& get_region_group(const std::string& name) const override;
104 [[nodiscard]] std::unordered_map<std::string, RegionGroup> get_all_region_groups() const override;
105 void remove_region_group(const std::string& name) override;
106
107 /**
108 * @brief No-op. All surface data is continuously available after readback.
109 * Register regions via add_region_group() instead.
110 */
111 void load_region(const Region& region) override;
112
113 /**
114 * @brief No-op. See load_region().
115 */
116 void unload_region(const Region& region) override;
117
118 /**
119 * @brief Always returns true. Surface data is available after any readback.
120 */
121 [[nodiscard]] bool is_region_loaded(const Region& region) const override;
122
123 // =========================================================================
124 // SignalSourceContainer
125 // =========================================================================
126
127 [[nodiscard]] ProcessingState get_processing_state() const override;
128 void update_processing_state(ProcessingState new_state) override;
129
130 void register_state_change_callback(
131 std::function<void(const std::shared_ptr<SignalSourceContainer>&, ProcessingState)> callback) override;
132 void unregister_state_change_callback() override;
133
134 [[nodiscard]] bool is_ready_for_processing() const override;
135 void mark_ready_for_processing(bool ready) override;
136
137 void create_default_processor() override;
138 void process_default() override;
139
140 void set_default_processor(const std::shared_ptr<DataProcessor>& processor) override;
141 [[nodiscard]] std::shared_ptr<DataProcessor> get_default_processor() const override;
142
143 [[nodiscard]] std::shared_ptr<DataProcessingChain> get_processing_chain() override;
144 void set_processing_chain(const std::shared_ptr<DataProcessingChain>& chain) override;
145
146 // -------------------------------------------------------------------------
147 // Consumer tracking — dimension_index and reader_id are opaque slot handles.
148 // Tracks whether all registered consumers have read processed_data[0] this
149 // cycle. The slot index argument exists for interface compliance; internally
150 // this container tracks a single consumer count across all slots.
151 // -------------------------------------------------------------------------
152 uint32_t register_dimension_reader(uint32_t dimension_index) override;
153 void unregister_dimension_reader(uint32_t dimension_index) override;
154 [[nodiscard]] bool has_active_readers() const override;
155 void mark_dimension_consumed(uint32_t dimension_index, uint32_t reader_id) override;
156 [[nodiscard]] bool all_dimensions_consumed() const override;
157
158 [[nodiscard]] std::vector<DataVariant>& get_processed_data() override;
159 [[nodiscard]] const std::vector<DataVariant>& get_processed_data() const override;
160 [[nodiscard]] const std::vector<DataVariant>& get_data() override;
161
162 void mark_buffers_for_processing(bool) override { }
163 void mark_buffers_for_removal() override { }
164
165 [[nodiscard]] DataAccess channel_data(size_t channel_index) override;
166 [[nodiscard]] std::vector<DataAccess> all_channel_data() override;
167
168private:
169 std::shared_ptr<Core::Window> m_window;
170
172 std::vector<DataVariant> m_data;
173 std::vector<DataVariant> m_processed_data;
174
175 std::unordered_map<std::string, RegionGroup> m_region_groups;
176
177 std::shared_ptr<DataProcessor> m_default_processor;
178 std::shared_ptr<DataProcessingChain> m_processing_chain;
179
180 std::atomic<ProcessingState> m_processing_state { ProcessingState::IDLE };
181 std::atomic<bool> m_ready_for_processing { false };
182
183 std::function<void(const std::shared_ptr<SignalSourceContainer>&, ProcessingState)> m_state_callback;
184
185 mutable std::shared_mutex m_data_mutex;
186 mutable std::mutex m_state_mutex;
187
188 std::atomic<uint32_t> m_registered_readers { 0 };
189 std::atomic<uint32_t> m_consumed_readers { 0 };
190 std::atomic<uint32_t> m_next_reader_id { 0 };
191
192 void setup_dimensions();
193};
194
195} // namespace MayaFlux::Kakshya
Type-erased accessor for NDData with semantic view construction.
Data-driven interface for managing arbitrary processable signal sources.
std::function< void(const std::shared_ptr< SignalSourceContainer > &, ProcessingState)> m_state_callback
~WindowContainer() override=default
void mark_buffers_for_removal() override
Mark associated buffers for removal from the system.
WindowContainer & operator=(const WindowContainer &)=delete
WindowContainer(WindowContainer &&)=delete
std::shared_ptr< Core::Window > m_window
ContainerDataStructure & get_structure() override
Get the data structure defining this container's layout.
WindowContainer & operator=(WindowContainer &&)=delete
std::vector< DataVariant > m_processed_data
std::unordered_map< std::string, RegionGroup > m_region_groups
std::vector< DataVariant > m_data
std::shared_ptr< DataProcessingChain > m_processing_chain
std::shared_ptr< DataProcessor > m_default_processor
void set_structure(ContainerDataStructure s) override
Set the data structure for this container.
WindowContainer(const WindowContainer &)=delete
void mark_buffers_for_processing(bool) override
Mark associated buffers for processing in the next cycle.
std::shared_ptr< Core::Window > get_window() const
The underlying window.
const ContainerDataStructure & get_structure() const override
SignalSourceContainer wrapping a live GLFW/Vulkan window surface.
ProcessingState
Represents the current processing lifecycle state of a container.
std::optional< RegionGroup > get_region_group(const std::unordered_map< std::string, RegionGroup > &groups, const std::string &name)
Get a RegionGroup by name from a group map.
void add_region_group(std::unordered_map< std::string, RegionGroup > &groups, const RegionGroup &group)
Add a RegionGroup to a group map.
MemoryLayout
Memory layout for multi-dimensional data.
Definition NDData.hpp:36
void remove_region_group(std::unordered_map< std::string, RegionGroup > &groups, const std::string &name)
Remove a RegionGroup by name from a group map.
Container structure for consistent dimension ordering.
Organizes related signal regions into a categorized collection.
Represents a point or span in N-dimensional space.
Definition Region.hpp:67