CYD-UI
A C++ library for building native graphic user interfaces
Loading...
Searching...
No Matches
compositing.cppm
Go to the documentation of this file.
1// Copyright (c) 2024, Víctor Castillo Agüero.
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4module;
5#include <cairomm-1.16/cairomm/cairomm.h>
6#include <tracy/Tracy.hpp>
7
8#define SDL_MAIN_HANDLED
9#include <SDL3/SDL.h>
10
11export module cydui.graphics:compositing;
12
13import std;
14
15import fabric.profiling;
16
17import :api;
18export import cydui.graphics.vector;
19
22
23export import :dev_texture;
24
25export namespace cydui::compositing {
26 using namespace vg;
27 using namespace std::chrono_literals;
28
30 enum {
33
34 int x, y, orig_x, orig_y;
35 int w, h;
36 double rot = 0.0;
37 double scale_x = 1.0;
38 double scale_y = 1.0;
39 bool animated = false;
40
43
44 bool operator==(const compositing_operation_t &other) const {
45 return x == other.x && y == other.y && orig_x == other.orig_x && orig_y == other.orig_y
46 && w == other.w && h == other.h && scale_x == other.scale_x && scale_y == other.scale_y
47 && rot == other.rot && animated == other.animated;
48
49 }
50 };
51
54 parent = parent_;
55 is_flattened = (not op.animated)
57 and (parent != nullptr)
58 and (op.x >= 0) && (op.y >= 0)
59 and ((op.x + op.w) <= parent->op.w)
60 and ((op.y + op.h) <= parent->op.h));
61
62 if (is_flattened) {
63 flattening_target = parent->flattening_target;
64 flatten_x = parent->flatten_x + op.x;
65 flatten_y = parent->flatten_y + op.y;
66 } else {
67 flattening_target = this;
68 flatten_x = 0;
69 flatten_y = 0;
70 }
71 }
72
73 bool is_flattened_node() const {
74 return is_flattened;
75 }
76
78 flattening_target->flattening_dirty = true;
79 }
80
82 return flattening_target->flattening_dirty;
83 }
84
85 void start_render(graphics::window_t* render_target) {
86 if (is_flattened) {
87 pixel_stride = flattening_target->pixel_stride;
88 pixels = &parent->pixels[op.x + (pixel_stride >> 2) * op.y];
89 } else {
90 ZoneScopedN("Start render");
91
92 if (rendered_texture.is_locked()) {
93 rendered_texture.unlock();
94 }
95 if (op.w == 0 or op.h == 0) {
96 rendered_texture.resize(render_target->renderer, 1, 1);
97 } else if (op.w != rendered_texture.width() || op.h != rendered_texture.height()) {
98 rendered_texture.resize(render_target->renderer, op.w, op.h);
99 }
100
101 pixel_stride = rendered_texture.width() * sizeof(pixel_t);
102 pixels = static_cast<pixel_t*>(rendered_texture.lock());
103 }
104 }
105
106 void render(graphics::window_t* render_target) {
107 if (op.w == 0 or op.h == 0) {
108 return;
109 }
110 ZoneScopedN("Render Node");
111
112 pixelmap_editor_t editor {op.w, op.h, pixels, pixel_stride};
113
114 if (not is_flattened) {
115 editor.clear();
116 }
117 editor->begin_new_path();
118 editor->rectangle(0, 0, op.w, op.h);
119 editor->clip();
120
121 if (not graphics.empty()) {
122 for (const auto &element: graphics.elements) {
123 element->_internal_set_origin(
124 op.orig_x,
125 op.orig_y
126 );
127 element->apply_to(editor);
128 }
129 }
130
131 flattening_target->dirty_ = true;
132 }
133
135 if (dirty_) {
136 ZoneScopedN("Flush Rendered Texture");
137 rendered_texture.unlock();
138 composite_texture.resize(render_target->renderer, rendered_texture.width(), rendered_texture.height());
139 dirty_ = false;
140 }
141 }
142
144 ZoneScopedN("Clear Composite Texture");
145 if (not is_flattened) {
146 composite_texture.clear(render_target->renderer);
147 }
148 }
149
150 void compose_own(graphics::window_t* render_target) {
151 ZoneScopedN("Compose Own");
152 if (is_flattened) return;
153 flush_rendered_texture(render_target);
154 SDL_FRect dst {
155 .x = 0,
156 .y = 0,
157 .w = rendered_texture.width(),
158 .h = rendered_texture.height(),
159 };
160 rendered_texture.copy_into(render_target->renderer, composite_texture, &dst, false);
161 }
162
163 void compose(graphics::window_t* render_target, compositing_node_t* other) {
164 ZoneScopedN("Compose Child");
165 SDL_Renderer* renderer = render_target->renderer;
166
167 auto& target = is_flattened? flattening_target->composite_texture : composite_texture;
168
169 float w_ = other->composite_texture.width();
170 float h_ = other->composite_texture.height();
171
172 target.resize(
173 renderer,
174 std::max(float{target.width()}, flatten_x + other->op.x + w_),
175 std::max(target.height(), flatten_y + other->op.y + h_),
176 true
177 );
178
179 SDL_FRect src {
180 .x = 0,
181 .y = 0,
182 .w = w_,
183 .h = h_,
184 };
185 SDL_FRect dst {
186 .x = static_cast<float>(flatten_x + other->op.x),
187 .y = static_cast<float>(flatten_y + other->op.y),
188 .w = w_,
189 .h = h_,
190 };
191 other->composite_texture.copy_into(renderer, target, &dst, true, &src);
192 }
193
194 private:
195 bool dirty_ = true;
196
197 compositing_node_t* parent = nullptr;
198 compositing_node_t* flattening_target = nullptr;
199 bool flattening_dirty = false;
200 bool is_flattened = false;
201 int pixel_stride = 0;
202
203 int flatten_x = 0;
204 int flatten_y = 0;
205 public:
206 unsigned long id = 0;
209
212 pixel_t* pixels;
213 };
214
216 graphics::window_t* render_target = nullptr;
217 prof::context_t* profiler = nullptr;
218
219 public:
222
225
226 void set_render_target(graphics::window_t* _render_target, prof::context_t* _profiler) {
227 render_target = _render_target;
228 profiler = _profiler;
229 }
230
232 auto* rtarget = render_target;
233 if (root != nullptr) {
234 SDL_SetRenderDrawColor(rtarget->renderer, 0, 0, 0, 0);
235 SDL_RenderClear(rtarget->renderer);
236
237 SDL_Texture* texture = root->composite_texture.sdl_texture();
238 SDL_FRect src {
239 .x = 0,
240 .y = 0,
241 .w = root->composite_texture.width(),
242 .h = root->composite_texture.height()
243 };
244 SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND_PREMULTIPLIED);
245
246 SDL_RenderTexture(rtarget->renderer, texture, &src, &src);
247 SDL_RenderPresent(rtarget->renderer);
248 }
249 }
250 };
251}
void compose(compositing_node_t *root)
void set_render_target(graphics::window_t *_render_target, prof::context_t *_profiler)
void compose_own(graphics::window_t *render_target)
void start_render(graphics::window_t *render_target)
void set_parent(compositing_node_t *parent_)
void flush_rendered_texture(graphics::window_t *render_target)
void compose(graphics::window_t *render_target, compositing_node_t *other)
void render(graphics::window_t *render_target)
void clear_composite_texture(graphics::window_t *render_target)
bool operator==(const compositing_operation_t &other) const
enum cydui::compositing::compositing_operation_t::@321126061026340171363272107326127342244210103306 op
std::function< void(compositing_operation_t &op)> _fix_dimensions
void copy_into(SDL_Renderer *renderer, device_texture_t &other, SDL_FRect *dst, bool blend=true, SDL_FRect *src_=nullptr)
SDL_Renderer * renderer
Definition window.cppm:41