Blender V4.3
BKE_pbvh_pixels.hh
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2022 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#pragma once
6
7#include "BLI_math_vector.hh"
8#include "BLI_rect.h"
9#include "BLI_vector.hh"
10
11#include "DNA_image_types.h"
12
13#include "BKE_image.hh"
14#include "BKE_image_wrappers.hh"
15
16#include "IMB_imbuf_types.hh"
17
19
41
55
62
63 struct {
64 bool dirty : 1;
66
67 /* Dirty region of the tile in image space. */
69
71
73 {
74 flags.dirty = false;
76 }
77
78 void mark_dirty(const PackedPixelRow &pixel_row)
79 {
80 int2 start_image_coord(pixel_row.start_image_coordinate.x, pixel_row.start_image_coordinate.y);
81 BLI_rcti_do_minmax_v(&dirty_region, start_image_coord);
82 BLI_rcti_do_minmax_v(&dirty_region, start_image_coord + int2(pixel_row.num_pixels + 1, 0));
83 flags.dirty = true;
84 }
85
87 {
89 flags.dirty = false;
90 }
91};
92
96
97 UDIMTileUndo(short tile_number, rcti &region) : tile_number(tile_number), region(region) {}
98};
99
103struct NodeData {
104 struct {
105 bool dirty : 1;
107
111
113 {
114 flags.dirty = false;
115 }
116
118 {
119 for (UDIMTilePixels &tile : tiles) {
120 if (tile.tile_number == image_tile.get_tile_number()) {
121 return &tile;
122 }
123 }
124 return nullptr;
125 }
126
128 {
129 undo_regions.clear();
130 for (UDIMTilePixels &tile : tiles) {
131 if (tile.pixel_rows.is_empty()) {
132 continue;
133 }
134
135 rcti region;
136 BLI_rcti_init_minmax(&region);
137 for (PackedPixelRow &pixel_row : tile.pixel_rows) {
139 &region, int2(pixel_row.start_image_coordinate.x, pixel_row.start_image_coordinate.y));
140 BLI_rcti_do_minmax_v(&region,
141 int2(pixel_row.start_image_coordinate.x + pixel_row.num_pixels + 1,
142 pixel_row.start_image_coordinate.y + 1));
143 }
144 undo_regions.append(UDIMTileUndo(tile.tile_number, region));
145 }
146 }
147
148 void mark_region(Image &image, const image::ImageTileWrapper &image_tile, ImBuf &image_buffer)
149 {
150 UDIMTilePixels *tile = find_tile_data(image_tile);
151 if (tile && tile->flags.dirty) {
152 if (image_buffer.planes == 8) {
153 image_buffer.planes = 32;
155 }
156 else {
158 &image, image_tile.image_tile, &image_buffer, &tile->dirty_region);
159 }
160 tile->clear_dirty();
161 }
162 }
163
165 {
166 for (UDIMTilePixels &tile : tiles) {
167 if (tile.flags.dirty) {
168 r_dirty_tiles.append_non_duplicates(tile.tile_number);
169 }
170 }
171 }
172
174 {
175 tiles.clear();
176 uv_primitives.clear();
177 }
178
179 static void free_func(void *instance)
180 {
181 NodeData *node_data = static_cast<NodeData *>(instance);
182 MEM_delete(node_data);
183 }
184};
185
186/* -------------------------------------------------------------------- */
200
207
218
219 CopyPixelCommand() = default;
221 : destination(group.start_destination),
222 source_1(group.start_source_1),
223 source_2(),
224 mix_factor(0.0f)
225 {
226 }
227
228 template<typename T>
230 {
231 float4 source_color_1 = tile_buffer.read_pixel(source_1);
232 float4 source_color_2 = tile_buffer.read_pixel(source_2);
233 float4 destination_color = source_color_1 * (1.0f - mix_factor) + source_color_2 * mix_factor;
234 tile_buffer.write_pixel(destination, destination_color);
235 }
236
237 void apply(const DeltaCopyPixelCommand &item)
238 {
239 destination.x += 1;
242 mix_factor = float(item.mix_factor) / 255.0f;
243 }
244
246 {
247 return DeltaCopyPixelCommand(char2(next_command.source_1 - source_1),
248 char2(next_command.source_2 - next_command.source_1),
249 uint8_t(next_command.mix_factor * 255));
250 }
251
252 bool can_be_extended(const CopyPixelCommand &command) const
253 {
254 /* Can only extend sequential pixels. */
255 if (destination.x != command.destination.x - 1 || destination.y != command.destination.y) {
256 return false;
257 }
258
259 /* Can only extend when the delta between with the previous source fits in a single byte. */
260 int2 delta_source_1 = source_1 - command.source_1;
261 if (max_ii(UNPACK2(blender::math::abs(delta_source_1))) > 127) {
262 return false;
263 }
264 return true;
265 }
266};
267
272
274
275 void copy_pixels(ImBuf &tile_buffer, IndexRange group_range) const
276 {
277 if (tile_buffer.float_buffer.data) {
278 image::ImageBufferAccessor<float4> accessor(tile_buffer);
279 copy_pixels<float4>(accessor, group_range);
280 }
281 else {
282 image::ImageBufferAccessor<int> accessor(tile_buffer);
283 copy_pixels<int>(accessor, group_range);
284 }
285 }
286
288 {
289 int decoded_size = command_deltas.size() * sizeof(CopyPixelCommand);
290 int encoded_size = groups.size() * sizeof(CopyPixelGroup) +
291 command_deltas.size() * sizeof(DeltaCopyPixelCommand);
292 printf("Tile %d compression rate: %d->%d = %d%%\n",
294 decoded_size,
295 encoded_size,
296 int(100.0 * float(encoded_size) / float(decoded_size)));
297 }
298
299 private:
300 template<typename T>
301 void copy_pixels(image::ImageBufferAccessor<T> &image_buffer, IndexRange group_range) const
302 {
303 for (const int64_t group_index : group_range) {
304 const CopyPixelGroup &group = groups[group_index];
305 CopyPixelCommand copy_command(group);
306 for (const DeltaCopyPixelCommand &item : Span<const DeltaCopyPixelCommand>(
307 &command_deltas[group.start_delta_index], group.num_deltas))
308 {
309 copy_command.apply(item);
310 copy_command.mix_source_and_write_destination<T>(image_buffer);
311 }
312 }
313 }
314};
315
318
319 std::optional<std::reference_wrapper<CopyPixelTile>> find_tile(image::TileNumber tile_number)
320 {
321 for (CopyPixelTile &tile : tiles) {
322 if (tile.tile_number == tile_number) {
323 return tile;
324 }
325 }
326 return std::nullopt;
327 }
328
329 void clear()
330 {
331 tiles.clear();
332 }
333};
334
340struct PBVHData {
341 /* Per UVPRimitive contains the paint data. */
343
346
348 {
349 this->vert_tris = {};
350 }
351};
352
354void mark_image_dirty(blender::bke::pbvh::Node &node, Image &image, ImageUser &image_user);
355PBVHData &data_get(blender::bke::pbvh::Tree &pbvh);
357
359 Image &image,
360 ImageUser &image_user,
361 image::TileNumber tile_number);
362
363} // namespace blender::bke::pbvh::pixels
void BKE_image_partial_update_mark_region(Image *image, const ImageTile *image_tile, const ImBuf *image_buffer, const rcti *updated_region)
Mark a region of the image to update.
void BKE_image_partial_update_mark_full_update(Image *image)
Mark the whole image to be updated.
MINLINE int max_ii(int a, int b)
void BLI_rcti_init_minmax(struct rcti *rect)
Definition rct.c:478
void BLI_rcti_do_minmax_v(struct rcti *rect, const int xy[2])
Definition rct.c:490
unsigned short ushort
#define UNPACK2(a)
Contains defines and structs used throughout the imbuf module.
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object instance
void append_non_duplicates(const T &value)
#define printf
draw_view in_light_buf[] float
ccl_global const KernelWorkTile * tile
NodeData & node_data_get(blender::bke::pbvh::Node &node)
void mark_image_dirty(blender::bke::pbvh::Node &node, Image &image, ImageUser &image_user)
void copy_pixels(blender::bke::pbvh::Tree &pbvh, Image &image, ImageUser &image_user, image::TileNumber tile_number)
void collect_dirty_tiles(blender::bke::pbvh::Node &node, Vector< image::TileNumber > &r_dirty_tiles)
PBVHData & data_get(blender::bke::pbvh::Tree &pbvh)
T abs(const T &a)
blender::VecBase< int8_t, 2 > char2
VecBase< int32_t, 2 > int2
__int64 int64_t
Definition stdint.h:89
unsigned char uint8_t
Definition stdint.h:78
ImBufFloatBuffer float_buffer
unsigned char planes
void write_pixel(const int2 coordinate, float4 new_value)
float4 read_pixel(const int2 coordinate)
void mix_source_and_write_destination(image::ImageBufferAccessor< T > &tile_buffer) const
DeltaCopyPixelCommand encode_delta(const CopyPixelCommand &next_command) const
bool can_be_extended(const CopyPixelCommand &command) const
void apply(const DeltaCopyPixelCommand &item)
CopyPixelCommand(const CopyPixelGroup &group)
Vector< DeltaCopyPixelCommand > command_deltas
void copy_pixels(ImBuf &tile_buffer, IndexRange group_range) const
CopyPixelTile(image::TileNumber tile_number)
std::optional< std::reference_wrapper< CopyPixelTile > > find_tile(image::TileNumber tile_number)
DeltaCopyPixelCommand(char2 delta_source_1, char2 delta_source_2, uint8_t mix_factor)
void mark_region(Image &image, const image::ImageTileWrapper &image_tile, ImBuf &image_buffer)
UDIMTilePixels * find_tile_data(const image::ImageTileWrapper &image_tile)
static void free_func(void *instance)
struct blender::bke::pbvh::pixels::NodeData::@53 flags
Vector< UVPrimitivePaintInput > uv_primitives
void collect_dirty_tiles(Vector< image::TileNumber > &r_dirty_tiles)
void mark_dirty(const PackedPixelRow &pixel_row)
struct blender::bke::pbvh::pixels::UDIMTilePixels::@52 flags
UDIMTileUndo(short tile_number, rcti &region)