Pulp 1.88.0
Cross-platform audio plugin framework
Loading...
Searching...
No Matches
dirty_tracker.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <algorithm>
4#include <cstdint>
5#include <vector>
6
7namespace pulp::render {
8
14public:
15 struct Rect {
16 float x = 0, y = 0, w = 0, h = 0;
17
18 bool intersects(const Rect& other) const {
19 return x < other.x + other.w && x + w > other.x &&
20 y < other.y + other.h && y + h > other.y;
21 }
22
24 Rect merged(const Rect& other) const {
25 float nx = std::min(x, other.x);
26 float ny = std::min(y, other.y);
27 return {nx, ny,
28 std::max(x + w, other.x + other.w) - nx,
29 std::max(y + h, other.y + other.h) - ny};
30 }
31
32 float area() const { return w * h; }
33 };
34
36 void invalidate(const Rect& rect) {
37 if (rect.w <= 0 || rect.h <= 0) return;
38 dirty_rects_.push_back(rect);
39 coalesce_if_needed();
40 }
41
43 void invalidate(float x, float y, float w, float h) {
44 invalidate({x, y, w, h});
45 }
46
49 full_repaint_ = true;
50 dirty_rects_.clear();
51 }
52
54 bool is_dirty() const { return full_repaint_ || !dirty_rects_.empty(); }
55
57 bool needs_full_repaint() const { return full_repaint_; }
58
60 const std::vector<Rect>& dirty_rects() const { return dirty_rects_; }
61
64 void clear() {
65 dirty_rects_.clear();
66 full_repaint_ = false;
67 ++frame_count_;
68 }
69
71 Rect bounds() const {
72 if (dirty_rects_.empty()) return {};
73 Rect b = dirty_rects_[0];
74 for (size_t i = 1; i < dirty_rects_.size(); ++i)
75 b = b.merged(dirty_rects_[i]);
76 return b;
77 }
78
81 void set_viewport(float width, float height, float full_repaint_threshold = 0.6f) {
82 viewport_w_ = width;
83 viewport_h_ = height;
84 full_repaint_threshold_ = full_repaint_threshold;
85 }
86
88 void set_debug_overlay(bool enabled) { debug_overlay_ = enabled; }
89 bool debug_overlay() const { return debug_overlay_; }
90
92 uint64_t frame_count() const { return frame_count_; }
93
94private:
95 void coalesce_if_needed() {
96 // If we have too many small rects, merge nearby ones
97 if (dirty_rects_.size() > max_rects_) {
98 coalesce();
99 }
100
101 // If dirty area exceeds threshold, switch to full repaint
102 if (viewport_w_ > 0 && viewport_h_ > 0) {
103 float total_area = 0;
104 for (auto& r : dirty_rects_) total_area += r.area();
105 if (total_area > viewport_w_ * viewport_h_ * full_repaint_threshold_) {
107 }
108 }
109 }
110
111 void coalesce() {
112 // Simple greedy merge: combine overlapping/adjacent rects
113 bool merged = true;
114 while (merged) {
115 merged = false;
116 for (size_t i = 0; i < dirty_rects_.size(); ++i) {
117 for (size_t j = i + 1; j < dirty_rects_.size(); ++j) {
118 auto combined = dirty_rects_[i].merged(dirty_rects_[j]);
119 // Merge if the bounding box isn't much larger than the sum
120 float sum_area = dirty_rects_[i].area() + dirty_rects_[j].area();
121 if (combined.area() < sum_area * 1.5f ||
122 dirty_rects_[i].intersects(dirty_rects_[j])) {
123 dirty_rects_[i] = combined;
124 dirty_rects_.erase(dirty_rects_.begin() + static_cast<long>(j));
125 merged = true;
126 break;
127 }
128 }
129 if (merged) break;
130 }
131 }
132 }
133
134 std::vector<Rect> dirty_rects_;
135 bool full_repaint_ = true; // First frame is always full
136 bool debug_overlay_ = false;
137 float viewport_w_ = 0;
138 float viewport_h_ = 0;
139 float full_repaint_threshold_ = 0.6f;
140 uint64_t frame_count_ = 0;
141 static constexpr size_t max_rects_ = 16;
142};
143
144} // namespace pulp::render
Tracks rectangular regions that need repainting.
Definition dirty_tracker.hpp:13
void set_viewport(float width, float height, float full_repaint_threshold=0.6f)
Set the viewport size.
Definition dirty_tracker.hpp:81
Rect bounds() const
Get the bounding rect of all dirty regions (for partial repaints).
Definition dirty_tracker.hpp:71
bool needs_full_repaint() const
Returns true if the entire viewport needs repainting.
Definition dirty_tracker.hpp:57
uint64_t frame_count() const
Frame counter for multi-frame history tracking.
Definition dirty_tracker.hpp:92
const std::vector< Rect > & dirty_rects() const
Get the list of dirty rectangles (empty if full repaint).
Definition dirty_tracker.hpp:60
void invalidate_all()
Mark the entire viewport as dirty (forces full repaint).
Definition dirty_tracker.hpp:48
void set_debug_overlay(bool enabled)
Enable/disable debug overlay (draws dirty regions with colored flash).
Definition dirty_tracker.hpp:88
void invalidate(const Rect &rect)
Mark a rectangular region as needing repaint.
Definition dirty_tracker.hpp:36
bool debug_overlay() const
Definition dirty_tracker.hpp:89
bool is_dirty() const
Returns true if any region needs repainting.
Definition dirty_tracker.hpp:54
void invalidate(float x, float y, float w, float h)
Mark a rectangular region as needing repaint (convenience overload).
Definition dirty_tracker.hpp:43
void clear()
Clear all dirty state after a frame has been painted.
Definition dirty_tracker.hpp:64
Definition gpu_fwd.hpp:31
@ i
Definition formant_filter_bank.hpp:20
@ j
Definition input_events.hpp:40
Definition dirty_tracker.hpp:15
Rect merged(const Rect &other) const
Merge two rects into their bounding box.
Definition dirty_tracker.hpp:24
bool intersects(const Rect &other) const
Definition dirty_tracker.hpp:18
float area() const
Definition dirty_tracker.hpp:32
float x
Definition dirty_tracker.hpp:16
float y
Definition dirty_tracker.hpp:16
float h
Definition dirty_tracker.hpp:16
float w
Definition dirty_tracker.hpp:16