Blender V5.0
image_partial_update_test.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2020 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4#include "testing/testing.h"
5
6#include "BLI_rect.h"
7
8#include "CLG_log.h"
9
10#include "GHOST_Path-api.hh"
11
12#include "BKE_appdir.hh"
13#include "BKE_global.hh"
14#include "BKE_idtype.hh"
15#include "BKE_image.hh"
17#include "BKE_main.hh"
18
19#include "IMB_imbuf.hh"
20#include "IMB_moviecache.hh"
21
22#include "DNA_image_types.h"
23
25
26constexpr float black_color[4] = {0.0f, 0.0f, 0.0f, 1.0f};
27
28class ImagePartialUpdateTest : public testing::Test {
29 protected:
34 ImageUser image_user = {nullptr};
36 PartialUpdateUser *partial_update_user;
37
38 private:
39 Image *create_test_image(int width, int height)
40 {
42 width,
43 height,
44 "Test Image",
45 32,
46 true,
49 false,
50 false,
51 false);
52 }
53
54 protected:
55 void SetUp() override
56 {
57 CLG_init();
60 IMB_init();
61
63 /* Required by usage of #ID_BLEND_PATH_FROM_GLOBAL in #add_ibuf_for_tile. */
65 G_MAIN = bmain;
66 /* Creating an image generates a memory-leak during tests. */
67 image = create_test_image(1024, 1024);
69 image_buffer = BKE_image_acquire_ibuf(image, nullptr, nullptr);
70
72 }
73
74 void TearDown() override
75 {
78
79 /* Restore original main in G_MAIN. */
82
84 IMB_exit();
87 CLG_exit();
88 }
89};
90
92{
94 /* First tile should always return a full update. */
97 /* Second invoke should now detect no changes. */
100
101 /* Mark full update */
103
104 /* Validate need full update followed by no changes. */
109}
110
112{
114 /* First tile should always return a full update. */
117 /* Second invoke should now detect no changes. */
120
121 /* Mark region. */
122 rcti region;
123 BLI_rcti_init(&region, 10, 20, 40, 50);
124 BKE_image_partial_update_mark_region(image, image_tile, image_buffer, &region);
125
126 /* Partial Update should be available. */
129
130 /* Check tiles. */
131 PartialUpdateRegion changed_region;
132 ePartialUpdateIterResult iter_result;
133 iter_result = BKE_image_partial_update_get_next_change(partial_update_user, &changed_region);
135 EXPECT_EQ(BLI_rcti_inside_rcti(&changed_region.region, &region), true);
136 iter_result = BKE_image_partial_update_get_next_change(partial_update_user, &changed_region);
138
141}
142
143TEST_F(ImagePartialUpdateTest, mark_unconnected_tiles)
144{
146 /* First tile should always return a full update. */
149 /* Second invoke should now detect no changes. */
152
153 /* Mark region. */
154 rcti region_a;
155 BLI_rcti_init(&region_a, 10, 20, 40, 50);
156 BKE_image_partial_update_mark_region(image, image_tile, image_buffer, &region_a);
157 rcti region_b;
158 BLI_rcti_init(&region_b, 710, 720, 740, 750);
159 BKE_image_partial_update_mark_region(image, image_tile, image_buffer, &region_b);
160
161 /* Partial Update should be available. */
164
165 /* Check tiles. */
166 PartialUpdateRegion changed_region;
167 ePartialUpdateIterResult iter_result;
168 iter_result = BKE_image_partial_update_get_next_change(partial_update_user, &changed_region);
170 EXPECT_EQ(BLI_rcti_inside_rcti(&changed_region.region, &region_b), true);
171 iter_result = BKE_image_partial_update_get_next_change(partial_update_user, &changed_region);
173 EXPECT_EQ(BLI_rcti_inside_rcti(&changed_region.region, &region_a), true);
174 iter_result = BKE_image_partial_update_get_next_change(partial_update_user, &changed_region);
176
179}
180
181TEST_F(ImagePartialUpdateTest, donot_mark_outside_image)
182{
184 /* First tile should always return a full update. */
187 /* Second invoke should now detect no changes. */
190
191 /* Mark region. */
192 rcti region;
193 /* Axis. */
194 BLI_rcti_init(&region, -100, 0, 50, 100);
195 BKE_image_partial_update_mark_region(image, image_tile, image_buffer, &region);
198
199 BLI_rcti_init(&region, 1024, 1100, 50, 100);
200 BKE_image_partial_update_mark_region(image, image_tile, image_buffer, &region);
203
204 BLI_rcti_init(&region, 50, 100, -100, 0);
205 BKE_image_partial_update_mark_region(image, image_tile, image_buffer, &region);
208
209 BLI_rcti_init(&region, 50, 100, 1024, 1100);
210 BKE_image_partial_update_mark_region(image, image_tile, image_buffer, &region);
213
214 /* Diagonals. */
215 BLI_rcti_init(&region, -100, 0, -100, 0);
216 BKE_image_partial_update_mark_region(image, image_tile, image_buffer, &region);
219
220 BLI_rcti_init(&region, -100, 0, 1024, 1100);
221 BKE_image_partial_update_mark_region(image, image_tile, image_buffer, &region);
224
225 BLI_rcti_init(&region, 1024, 1100, -100, 0);
226 BKE_image_partial_update_mark_region(image, image_tile, image_buffer, &region);
229
230 BLI_rcti_init(&region, 1024, 1100, 1024, 1100);
231 BKE_image_partial_update_mark_region(image, image_tile, image_buffer, &region);
234}
235
237{
239 /* First tile should always return a full update. */
242 /* Second invoke should now detect no changes. */
245
246 /* Mark region. */
247 rcti region;
248 BLI_rcti_init(&region, 0, 1, 0, 1);
249 BKE_image_partial_update_mark_region(image, image_tile, image_buffer, &region);
252
255 BLI_rcti_init(&region, 1023, 1024, 0, 1);
256 BKE_image_partial_update_mark_region(image, image_tile, image_buffer, &region);
259
262 BLI_rcti_init(&region, 1023, 1024, 1023, 1024);
263 BKE_image_partial_update_mark_region(image, image_tile, image_buffer, &region);
266
269 BLI_rcti_init(&region, 1023, 1024, 0, 1);
270 BKE_image_partial_update_mark_region(image, image_tile, image_buffer, &region);
273}
274
275TEST_F(ImagePartialUpdateTest, sequential_mark_region)
276{
278 /* First tile should always return a full update. */
281 /* Second invoke should now detect no changes. */
284
285 {
286 /* Mark region. */
287 rcti region;
288 BLI_rcti_init(&region, 10, 20, 40, 50);
289 BKE_image_partial_update_mark_region(image, image_tile, image_buffer, &region);
290
291 /* Partial Update should be available. */
294
295 /* Check tiles. */
296 PartialUpdateRegion changed_region;
297 ePartialUpdateIterResult iter_result;
298 iter_result = BKE_image_partial_update_get_next_change(partial_update_user, &changed_region);
300 EXPECT_EQ(BLI_rcti_inside_rcti(&changed_region.region, &region), true);
301 iter_result = BKE_image_partial_update_get_next_change(partial_update_user, &changed_region);
303
306 }
307
308 {
309 /* Mark different region. */
310 rcti region;
311 BLI_rcti_init(&region, 710, 720, 740, 750);
312 BKE_image_partial_update_mark_region(image, image_tile, image_buffer, &region);
313
314 /* Partial Update should be available. */
317
318 /* Check tiles. */
319 PartialUpdateRegion changed_region;
320 ePartialUpdateIterResult iter_result;
321 iter_result = BKE_image_partial_update_get_next_change(partial_update_user, &changed_region);
323 EXPECT_EQ(BLI_rcti_inside_rcti(&changed_region.region, &region), true);
324 iter_result = BKE_image_partial_update_get_next_change(partial_update_user, &changed_region);
326
329 }
330}
331
332TEST_F(ImagePartialUpdateTest, mark_multiple_chunks)
333{
335 /* First tile should always return a full update. */
338 /* Second invoke should now detect no changes. */
341
342 /* Mark region. */
343 rcti region;
344 BLI_rcti_init(&region, 300, 700, 300, 700);
345 BKE_image_partial_update_mark_region(image, image_tile, image_buffer, &region);
346
347 /* Partial Update should be available. */
350
351 /* Check tiles. */
352 PartialUpdateRegion changed_region;
353 int num_chunks_found = 0;
354 while (BKE_image_partial_update_get_next_change(partial_update_user, &changed_region) ==
356 {
357 BLI_rcti_isect(&changed_region.region, &region, nullptr);
358 num_chunks_found++;
359 }
360 EXPECT_EQ(num_chunks_found, 4);
361}
362
364{
365 PartialUpdateChecker<NoTileData> checker(image, &image_user, partial_update_user);
366 /* First tile should always return a full update. */
369 /* Second invoke should now detect no changes. */
370 changes = checker.collect_changes();
372
373 /* Mark region. */
374 rcti region;
375 BLI_rcti_init(&region, 300, 700, 300, 700);
376 BKE_image_partial_update_mark_region(image, image_tile, image_buffer, &region);
377
378 /* Partial Update should be available. */
379 changes = checker.collect_changes();
381
382 /* Check tiles. */
383 int num_tiles_found = 0;
385 BLI_rcti_isect(&changes.changed_region.region, &region, nullptr);
386 num_tiles_found++;
387 }
388 EXPECT_EQ(num_tiles_found, 4);
389}
390
391} // namespace blender::bke::image::partial_update
void BKE_appdir_init()
Definition appdir.cc:93
void BKE_appdir_exit()
Definition appdir.cc:101
#define G_MAIN
void BKE_idtype_init()
Definition idtype.cc:121
ImBuf * BKE_image_acquire_ibuf(Image *ima, ImageUser *iuser, void **r_lock)
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_release_ibuf(Image *ima, ImBuf *ibuf, void *lock)
void BKE_image_partial_update_free(PartialUpdateUser *user)
free a partial update user.
PartialUpdateUser * BKE_image_partial_update_create(const Image *image)
Create a new PartialUpdateUser. An Object that contains data to use partial updates.
void BKE_image_partial_update_mark_full_update(Image *image)
Mark the whole image to be updated.
Image * BKE_image_add_generated(Main *bmain, unsigned int width, unsigned int height, const char *name, int depth, int floatbuf, short gen_type, const float color[4], bool stereo3d, bool is_data, bool tiled)
Main * BKE_main_new()
Definition main.cc:89
void BKE_main_free(Main *bmain)
Definition main.cc:192
EXPECT_EQ(BLI_expr_pylike_eval(expr, nullptr, 0, &result), EXPR_PYLIKE_INVALID)
void BLI_rcti_init(struct rcti *rect, int xmin, int xmax, int ymin, int ymax)
Definition rct.cc:414
bool BLI_rcti_isect(const struct rcti *src1, const struct rcti *src2, struct rcti *dest)
bool BLI_rcti_inside_rcti(const rcti *rct_a, const rcti *rct_b)
Definition rct.cc:198
void CLG_exit()
Definition clog.cc:880
void CLG_init()
Definition clog.cc:873
@ IMA_GENTYPE_BLANK
GHOST_TSuccess GHOST_DisposeSystemPaths()
void IMB_exit()
Definition module.cc:21
void IMB_init()
Definition module.cc:15
void IMB_moviecache_destruct()
ePartialUpdateCollectResult BKE_image_partial_update_collect_changes(Image *image, PartialUpdateUser *user)
collect the partial update since the last request.
TEST_F(ImagePartialUpdateTest, mark_full_update)
ePartialUpdateIterResult BKE_image_partial_update_get_next_change(PartialUpdateUser *user, 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.
ePartialUpdateIterResult
Return codes of BKE_image_partial_update_get_next_change.
ePartialUpdateIterResult get_next_change()
Load the next changed region.
CollectResult collect_changes()
Check for new changes since the last time this method was invoked for this user.
rcti region
region of the image that has been updated. Region can be bigger than actual changes.
void * BKE_image_get_tile
Definition stubs.c:36