87 if (pixel_offset < 0) {
101 return static_cast<struct PartialUpdateUser *
>(
static_cast<void *
>(user));
117 return static_cast<struct PartialUpdateRegister *
>(
static_cast<void *
>(partial_update_register));
141 const void *debug_image_;
165 std::vector<bool> chunk_dirty_flags_;
167 bool has_dirty_chunks_ =
false;
215 start_x_chunk =
max_ii(0, start_x_chunk);
216 start_y_chunk =
max_ii(0, start_y_chunk);
227 if (end_x_chunk < 0) {
230 if (end_y_chunk < 0) {
239 for (
int chunk_y = start_y_chunk; chunk_y <= end_y_chunk; chunk_y++) {
240 for (
int chunk_x = start_x_chunk; chunk_x <= end_x_chunk; chunk_x++) {
242 chunk_dirty_flags_[chunk_index] =
true;
245 has_dirty_chunks_ =
true;
250 return has_dirty_chunks_;
258 const int previous_chunk_len = chunk_dirty_flags_.size();
260 chunk_dirty_flags_.resize(chunk_len);
266 for (
int index = 0; index <
min_ii(chunk_len, previous_chunk_len); index++) {
267 chunk_dirty_flags_[index] =
false;
269 has_dirty_chunks_ =
false;
279 for (
int chunk_index = 0; chunk_index < chunk_len; chunk_index++) {
280 chunk_dirty_flags_[chunk_index] = chunk_dirty_flags_[chunk_index] |
281 other.chunk_dirty_flags_[chunk_index];
283 has_dirty_chunks_ |= other.has_dirty_chunks_;
289 const int chunk_index = chunk_y *
chunk_x_len + chunk_x;
290 return chunk_dirty_flags_[chunk_index];
311 if (tile_changeset.tile_number == image_tile->
tile_number) {
312 return tile_changeset;
318 tiles.append_as(tile_changeset);
327 if (tile_changeset.tile_number == image_tile->
tile_number) {
365 if (has_dirty_chunks && resolution_changed && !
history.is_empty()) {
408 if (num_items_to_remove == 0) {
411 history.remove(0, num_items_to_remove);
440 std::optional<TileChangeset> changed_chunks = std::nullopt;
442 if (!
history[index].has_tile(image_tile)) {
447 if (!changed_chunks.has_value()) {
448 changed_chunks = std::make_optional<TileChangeset>();
450 changed_chunks->tile_number = image_tile->
tile_number;
453 changed_chunks->merge(tile_changeset);
455 return changed_chunks;
461 if (
image->runtime.partial_update_register ==
nullptr) {
464 image->runtime.partial_update_register =
wrap(partial_update_register);
466 return image->runtime.partial_update_register;
470 PartialUpdateUser *user)
497 if (!changed_chunks.has_value()) {
500 if (!changed_chunks->has_dirty_chunks()) {
505 for (
int chunk_y = 0; chunk_y < changed_chunks->chunk_y_len; chunk_y++) {
506 for (
int chunk_x = 0; chunk_x < changed_chunks->chunk_x_len; chunk_x++) {
507 if (!changed_chunks->is_chunk_dirty(chunk_x, chunk_y)) {
551 user_impl->debug_image_ =
image;
556 return wrap(user_impl);
562 MEM_delete<PartialUpdateUserImpl>(user_impl);
570 image->runtime.partial_update_register);
571 if (partial_update_register) {
572 MEM_delete<PartialUpdateRegisterImpl>(partial_update_register);
574 image->runtime.partial_update_register =
nullptr;
579 const ImBuf *image_buffer,
580 const rcti *updated_region)
584 partial_updater->
mark_region(image_tile, updated_region);
#define LISTBASE_FOREACH(type, var, list)
MINLINE int min_ii(int a, int b)
MINLINE int max_ii(int a, int b)
void BLI_rcti_init(struct rcti *rect, int xmin, int xmax, int ymin, int ymax)
Contains defines and structs used throughout the imbuf module.
depth_tx normal_tx diffuse_light_tx specular_light_tx volume_light_tx environment_tx ambient_occlusion_tx aov_value_tx in_weight_img image(1, GPU_R32F, Qualifier::WRITE, ImageType::FLOAT_2D_ARRAY, "out_weight_img") .image(3
void BKE_image_partial_update_mark_region(Image *image, const ImageTile *image_tile, const ImBuf *image_buffer, const rcti *updated_region)
struct PartialUpdateUser * BKE_image_partial_update_create(const struct Image *image)
Create a new PartialUpdateUser. An Object that contains data to use partial updates.
void BKE_image_partial_update_free(PartialUpdateUser *user)
free a partial update user.
void BKE_image_partial_update_mark_full_update(Image *image)
Mark the whole image to be updated.
void BKE_image_partial_update_register_free(Image *image)
ccl_gpu_kernel_postfix ccl_global KernelWorkTile * tiles
ccl_global const KernelWorkTile * tile
static PartialUpdateUserImpl * unwrap(struct PartialUpdateUser *user)
static PartialUpdateRegister * image_partial_update_register_ensure(Image *image)
constexpr int MAX_HISTORY_LEN
Max number of changesets to keep in history.
ePartialUpdateCollectResult BKE_image_partial_update_collect_changes(struct Image *image, struct PartialUpdateUser *user)
collect the partial update since the last request.
ePartialUpdateIterResult BKE_image_partial_update_get_next_change(struct PartialUpdateUser *user, struct PartialUpdateRegion *r_region)
ePartialUpdateCollectResult
Result codes of BKE_image_partial_update_collect_changes.
@ PartialChangesDetected
Changes detected since the last time requested.
@ FullUpdateNeeded
Unable to construct partial updates. Caller should perform a full update.
@ NoChangesDetected
No changes detected since the last time requested.
constexpr ChangesetID UnknownChangesetID
static struct PartialUpdateUser * wrap(PartialUpdateUserImpl *user)
constexpr int CHUNK_SIZE
Size of chunks to track changes.
static int chunk_number_for_pixel(int pixel_offset)
get the chunk number for the give pixel coordinate.
ePartialUpdateIterResult
Return codes of BKE_image_partial_update_get_next_change.
@ Finished
no tiles left when iterating over tiles.
@ ChangeAvailable
a chunk was available and has been loaded.
Changeset keeping track of changes for an image.
void clear()
Clear this changeset.
bool has_dirty_chunks
Keep track if any of the tiles have dirty chunks.
bool has_tile(const ImageTile *image_tile)
Does this changeset contain data for the given tile.
TileChangeset & operator[](const ImageTile *image_tile)
Retrieve the TileChangeset for the given ImageTile.
struct rcti region
region of the image that has been updated. Region can be bigger than actual changes.
TileNumber tile_number
Tile number (UDIM) that this region belongs to.
Partial update changes stored inside the image runtime.
void update_resolution(const ImageTile *image_tile, const ImBuf *image_buffer)
void commit_current_changeset()
Move the current changeset to the history and resets the current changeset.
void ensure_empty_changeset()
void mark_region(const ImageTile *image_tile, const rcti *updated_region)
ChangesetID first_changeset_id
changeset id of the first changeset kept in history.
ChangesetID last_changeset_id
changeset id of the top changeset kept in history.
void limit_history()
Limit the number of items in the changeset.
Changeset current_changeset
The current changeset. New changes will be added to this changeset.
std::optional< TileChangeset > changed_tile_chunks_since(const ImageTile *image_tile, const ChangesetID from_changeset)
collect all historic changes since a given changeset.
bool can_construct(ChangesetID changeset_id)
Vector< Changeset > history
history of changesets.
Vector< PartialUpdateRegion > updated_regions
regions that have been updated.
void clear_updated_regions()
Clear the list of updated regions.
ChangesetID last_changeset_id
last changeset id that was seen by this user.
Dirty chunks of an ImageTile.
int tile_width
Width of the tile in pixels.
bool has_dirty_chunks() const
void init_chunks(int chunk_x_len_, int chunk_y_len_)
void merge(const TileChangeset &other)
Merge the given changeset into the receiver.
void mark_chunks_dirty(int start_x_chunk, int start_y_chunk, int end_x_chunk, int end_y_chunk)
bool update_resolution(const ImBuf *image_buffer)
Update the resolution of the tile.
int chunk_y_len
Number of chunks along the y-axis.
bool is_chunk_dirty(int chunk_x, int chunk_y) const
has a chunk changed inside this changeset.
int chunk_x_len
Number of chunks along the x-axis.
void mark_region(const rcti *updated_region)
int tile_height
Height of the tile in pixels.