Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/blenkernel/intern/image.c')
-rw-r--r--source/blender/blenkernel/intern/image.c566
1 files changed, 439 insertions, 127 deletions
diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c
index 4c81bd4b019..fca81acf038 100644
--- a/source/blender/blenkernel/intern/image.c
+++ b/source/blender/blenkernel/intern/image.c
@@ -87,6 +87,7 @@
#include "RE_pipeline.h"
#include "GPU_draw.h"
+#include "GPU_texture.h"
#include "BLI_sys_types.h" // for intptr_t support
@@ -111,9 +112,9 @@ static void image_add_view(Image *ima, const char *viewname, const char *filepat
/* max int, to indicate we don't store sequences in ibuf */
#define IMA_NO_INDEX 0x7FEFEFEF
-/* quick lookup: supports 1 million frames, thousand passes */
-#define IMA_MAKE_INDEX(frame, index) (((frame) << 10) + (index))
-#define IMA_INDEX_FRAME(index) ((index) >> 10)
+/* quick lookup: supports 1 million entries, thousand passes */
+#define IMA_MAKE_INDEX(entry, index) (((entry) << 10) + (index))
+#define IMA_INDEX_ENTRY(index) ((index) >> 10)
#if 0
# define IMA_INDEX_PASS(index) (index & ~1023)
#endif
@@ -142,7 +143,7 @@ static void imagecache_keydata(void *userkey, int *framenr, int *proxy, int *ren
{
ImageCacheKey *key = userkey;
- *framenr = IMA_INDEX_FRAME(key->index);
+ *framenr = IMA_INDEX_ENTRY(key->index);
*proxy = IMB_PROXY_NONE;
*render_flags = 0;
}
@@ -165,6 +166,17 @@ static void imagecache_put(Image *image, int index, ImBuf *ibuf)
IMB_moviecache_put(image->cache, &key, ibuf);
}
+static void imagecache_remove(Image *image, int index)
+{
+ if (image->cache == NULL) {
+ return;
+ }
+
+ ImageCacheKey key;
+ key.index = index;
+ IMB_moviecache_remove(image->cache, &key);
+}
+
static struct ImBuf *imagecache_get(Image *image, int index)
{
if (image->cache) {
@@ -257,7 +269,9 @@ void BKE_image_free_buffers_ex(Image *ima, bool do_lock)
GPU_free_image(ima);
}
- ima->ok = IMA_OK;
+ LISTBASE_FOREACH (ImageTile *, tile, &ima->tiles) {
+ tile->ok = IMA_OK;
+ }
if (do_lock) {
BLI_mutex_unlock(image_mutex);
@@ -290,6 +304,8 @@ void BKE_image_free(Image *ima)
BKE_icon_id_delete(&ima->id);
BKE_previewimg_free(&ima->preview);
+
+ BLI_freelistN(&ima->tiles);
}
/* only image block itself */
@@ -299,8 +315,6 @@ static void image_init(Image *ima, short source, short type)
MEMCPY_STRUCT_AFTER(ima, DNA_struct_default_get(Image), id);
- ima->ok = IMA_OK;
-
ima->source = source;
ima->type = type;
@@ -308,6 +322,11 @@ static void image_init(Image *ima, short source, short type)
ima->flag |= IMA_VIEW_AS_RENDER;
}
+ ImageTile *tile = MEM_callocN(sizeof(ImageTile), "Image Tiles");
+ tile->ok = IMA_OK;
+ tile->tile_number = 1001;
+ BLI_addtail(&ima->tiles, tile);
+
if (type == IMA_TYPE_R_RESULT) {
for (int i = 0; i < 8; i++) {
BKE_image_add_renderslot(ima, NULL);
@@ -337,34 +356,42 @@ static Image *image_alloc(Main *bmain, const char *name, short source, short typ
return ima;
}
-/* Get the ibuf from an image cache by it's index and frame.
+/* Get the ibuf from an image cache by it's index and entry.
* Local use here only.
*
* Returns referenced image buffer if it exists, callee is to
* call IMB_freeImBuf to de-reference the image buffer after
* it's done handling it.
*/
-static ImBuf *image_get_cached_ibuf_for_index_frame(Image *ima, int index, int frame)
+static ImBuf *image_get_cached_ibuf_for_index_entry(Image *ima, int index, int entry)
{
if (index != IMA_NO_INDEX) {
- index = IMA_MAKE_INDEX(frame, index);
+ index = IMA_MAKE_INDEX(entry, index);
}
return imagecache_get(ima, index);
}
/* no ima->ibuf anymore, but listbase */
-static void image_assign_ibuf(Image *ima, ImBuf *ibuf, int index, int frame)
+static void image_assign_ibuf(Image *ima, ImBuf *ibuf, int index, int entry)
{
if (ibuf) {
if (index != IMA_NO_INDEX) {
- index = IMA_MAKE_INDEX(frame, index);
+ index = IMA_MAKE_INDEX(entry, index);
}
imagecache_put(ima, index, ibuf);
}
}
+static void image_remove_ibuf(Image *ima, int index, int entry)
+{
+ if (index != IMA_NO_INDEX) {
+ index = IMA_MAKE_INDEX(entry, index);
+ }
+ imagecache_remove(ima, index);
+}
+
static void copy_image_packedfiles(ListBase *lb_dst, const ListBase *lb_src)
{
const ImagePackedFile *imapf_src;
@@ -413,8 +440,11 @@ void BKE_image_copy_data(Main *UNUSED(bmain), Image *ima_dst, const Image *ima_s
BLI_listbase_clear(&ima_dst->anims);
- for (int i = 0; i < TEXTARGET_COUNT; i++) {
- ima_dst->gputexture[i] = NULL;
+ BLI_duplicatelist(&ima_dst->tiles, &ima_src->tiles);
+ LISTBASE_FOREACH (ImageTile *, tile, &ima_dst->tiles) {
+ for (int i = 0; i < TEXTARGET_COUNT; i++) {
+ tile->gputexture[i] = NULL;
+ }
}
if ((flag & LIB_ID_COPY_NO_PREVIEW) == 0) {
@@ -480,14 +510,82 @@ bool BKE_image_scale(Image *image, int width, int height)
bool BKE_image_has_opengl_texture(Image *ima)
{
- for (int i = 0; i < TEXTARGET_COUNT; i++) {
- if (ima->gputexture[i]) {
- return true;
+ LISTBASE_FOREACH (ImageTile *, tile, &ima->tiles) {
+ for (int i = 0; i < TEXTARGET_COUNT; i++) {
+ if (tile->gputexture[i] != NULL) {
+ return true;
+ }
}
}
return false;
}
+ImageTile *BKE_image_get_tile(Image *ima, int tile_number)
+{
+ if (ima == NULL) {
+ return NULL;
+ }
+
+ /* Verify valid tile range. */
+ if ((tile_number != 0) && (tile_number < 1001 || tile_number > IMA_UDIM_MAX)) {
+ return NULL;
+ }
+
+ /* Tile number 0 is a special case and refers to the first tile, typically
+ * coming from non-UDIM-aware code. */
+ if (tile_number == 0 || tile_number == 1001) {
+ return ima->tiles.first;
+ }
+
+ if (ima->source != IMA_SRC_TILED) {
+ return NULL;
+ }
+
+ LISTBASE_FOREACH (ImageTile *, tile, &ima->tiles) {
+ if (tile->tile_number == tile_number) {
+ return tile;
+ }
+ }
+
+ return NULL;
+}
+
+ImageTile *BKE_image_get_tile_from_iuser(Image *ima, ImageUser *iuser)
+{
+ return BKE_image_get_tile(ima, (iuser && iuser->tile) ? iuser->tile : 1001);
+}
+
+int BKE_image_get_tile_from_pos(struct Image *ima,
+ const float uv[2],
+ float new_uv[2],
+ float ofs[2])
+{
+ float local_ofs[2];
+ if (ofs == NULL) {
+ ofs = local_ofs;
+ }
+
+ copy_v2_v2(new_uv, uv);
+ zero_v2(ofs);
+
+ if ((ima->source != IMA_SRC_TILED) || uv[0] < 0.0f || uv[1] < 0.0f || uv[0] >= 10.0f) {
+ return 0;
+ }
+
+ int ix = (int)uv[0];
+ int iy = (int)uv[1];
+ int tile_number = 1001 + 10 * iy + ix;
+
+ if (BKE_image_get_tile(ima, tile_number) == NULL) {
+ return 0;
+ }
+ ofs[0] = ix;
+ ofs[1] = iy;
+ sub_v2_v2(new_uv, ofs);
+
+ return tile_number;
+}
+
static void image_init_color_management(Image *ima)
{
ImBuf *ibuf;
@@ -580,8 +678,10 @@ Image *BKE_image_load_exists_ex(Main *bmain, const char *filepath, bool *r_exist
if (BLI_path_cmp(strtest, str) == 0) {
if ((BKE_image_has_anim(ima) == false) || (ima->id.us == 0)) {
id_us_plus(&ima->id); /* officially should not, it doesn't link here! */
- if (ima->ok == 0) {
- ima->ok = IMA_OK;
+ LISTBASE_FOREACH (ImageTile *, tile, &ima->tiles) {
+ if (tile->ok == 0) {
+ tile->ok = IMA_OK;
+ }
}
if (r_exists) {
*r_exists = true;
@@ -690,10 +790,17 @@ Image *BKE_image_add_generated(Main *bmain,
short gen_type,
const float color[4],
const bool stereo3d,
- const bool is_data)
+ const bool is_data,
+ const bool tiled)
{
/* on save, type is changed to FILE in editsima.c */
- Image *ima = image_alloc(bmain, name, IMA_SRC_GENERATED, IMA_TYPE_UV_TEST);
+ Image *ima;
+ if (tiled) {
+ ima = image_alloc(bmain, name, IMA_SRC_TILED, IMA_TYPE_IMAGE);
+ }
+ else {
+ ima = image_alloc(bmain, name, IMA_SRC_GENERATED, IMA_TYPE_UV_TEST);
+ }
if (ima == NULL) {
return NULL;
}
@@ -718,7 +825,9 @@ Image *BKE_image_add_generated(Main *bmain,
ImBuf *ibuf;
ibuf = add_ibuf_size(
width, height, ima->name, depth, floatbuf, gen_type, color, &ima->colorspace_settings);
- image_assign_ibuf(ima, ibuf, stereo3d ? view_id : IMA_NO_INDEX, 0);
+ int index = tiled ? 0 : IMA_NO_INDEX;
+ int entry = tiled ? 1001 : 0;
+ image_assign_ibuf(ima, ibuf, stereo3d ? view_id : index, entry);
/* image_assign_ibuf puts buffer to the cache, which increments user counter. */
IMB_freeImBuf(ibuf);
@@ -729,7 +838,8 @@ Image *BKE_image_add_generated(Main *bmain,
image_add_view(ima, names[view_id], "");
}
- ima->ok = IMA_OK_LOADED;
+ ImageTile *tile = BKE_image_get_tile(ima, 0);
+ tile->ok = IMA_OK_LOADED;
return ima;
}
@@ -751,7 +861,8 @@ Image *BKE_image_add_from_imbuf(Main *bmain, ImBuf *ibuf, const char *name)
if (ima) {
STRNCPY(ima->name, ibuf->name);
image_assign_ibuf(ima, ibuf, IMA_NO_INDEX, 0);
- ima->ok = IMA_OK_LOADED;
+ ImageTile *tile = BKE_image_get_tile(ima, 0);
+ tile->ok = IMA_OK_LOADED;
}
return ima;
@@ -802,7 +913,7 @@ bool BKE_image_memorypack(Image *ima)
int i;
for (i = 0, iv = ima->views.first; iv; iv = iv->next, i++) {
- ImBuf *ibuf = image_get_cached_ibuf_for_index_frame(ima, i, 0);
+ ImBuf *ibuf = image_get_cached_ibuf_for_index_entry(ima, i, 0);
if (!ibuf) {
ok = false;
@@ -822,7 +933,7 @@ bool BKE_image_memorypack(Image *ima)
ima->views_format = R_IMF_VIEWS_INDIVIDUAL;
}
else {
- ImBuf *ibuf = image_get_cached_ibuf_for_index_frame(ima, IMA_NO_INDEX, 0);
+ ImBuf *ibuf = image_get_cached_ibuf_for_index_entry(ima, IMA_NO_INDEX, 0);
if (ibuf) {
ok = ok && image_memorypack_imbuf(ima, ibuf, ibuf->name);
@@ -1009,7 +1120,7 @@ static bool imagecache_check_free_anim(ImBuf *ibuf, void *UNUSED(userkey), void
{
int except_frame = *(int *)userdata;
return (ibuf->userflags & IB_BITMAPDIRTY) == 0 && (ibuf->index != IMA_NO_INDEX) &&
- (except_frame != IMA_INDEX_FRAME(ibuf->index));
+ (except_frame != IMA_INDEX_ENTRY(ibuf->index));
}
/* except_frame is weak, only works for seqs without offset... */
@@ -3162,7 +3273,7 @@ static void image_tag_reload(Image *ima, ID *iuser_id, ImageUser *iuser, void *c
void BKE_imageuser_default(ImageUser *iuser)
{
memset(iuser, 0, sizeof(ImageUser));
- iuser->ok = true;
+ iuser->ok = 1;
iuser->frames = 100;
iuser->sfra = 1;
}
@@ -3179,6 +3290,26 @@ void BKE_image_init_imageuser(Image *ima, ImageUser *iuser)
}
}
+static void image_free_tile(Image *ima, ImageTile *tile)
+{
+ for (int i = 0; i < TEXTARGET_COUNT; i++) {
+ if (tile->gputexture[i] != NULL) {
+ GPU_texture_free(tile->gputexture[i]);
+ tile->gputexture[i] = NULL;
+ }
+ }
+
+ if (BKE_image_is_multiview(ima)) {
+ const int totviews = BLI_listbase_count(&ima->views);
+ for (int i = 0; i < totviews; i++) {
+ image_remove_ibuf(ima, i, tile->tile_number);
+ }
+ }
+ else {
+ image_remove_ibuf(ima, 0, tile->tile_number);
+ }
+}
+
void BKE_image_signal(Main *bmain, Image *ima, ImageUser *iuser, int signal)
{
if (ima == NULL) {
@@ -3207,7 +3338,7 @@ void BKE_image_signal(Main *bmain, Image *ima, ImageUser *iuser, int signal)
if (ima->source == IMA_SRC_GENERATED) {
if (ima->gen_x == 0 || ima->gen_y == 0) {
- ImBuf *ibuf = image_get_cached_ibuf_for_index_frame(ima, IMA_NO_INDEX, 0);
+ ImBuf *ibuf = image_get_cached_ibuf_for_index_entry(ima, IMA_NO_INDEX, 0);
if (ibuf) {
ima->gen_x = ibuf->x;
ima->gen_y = ibuf->y;
@@ -3225,6 +3356,17 @@ void BKE_image_signal(Main *bmain, Image *ima, ImageUser *iuser, int signal)
ima->name[0] = '\0';
}
+ if (ima->source != IMA_SRC_TILED) {
+ /* Free all but the first tile. */
+ ImageTile *base_tile = BKE_image_get_tile(ima, 0);
+ for (ImageTile *tile = base_tile->next; tile; tile = tile->next) {
+ image_free_tile(ima, tile);
+ MEM_freeN(tile);
+ }
+ base_tile->next = NULL;
+ ima->tiles.last = base_tile;
+ }
+
/* image buffers for non-sequence multilayer will share buffers with RenderResult,
* however sequence multilayer will own buffers. Such logic makes switching from
* single multilayer file to sequence completely unstable
@@ -3234,7 +3376,10 @@ void BKE_image_signal(Main *bmain, Image *ima, ImageUser *iuser, int signal)
*/
BKE_image_free_buffers(ima);
- ima->ok = 1;
+ LISTBASE_FOREACH (ImageTile *, tile, &ima->tiles) {
+ tile->ok = 1;
+ }
+
if (iuser) {
image_tag_frame_recalc(ima, NULL, iuser, ima);
}
@@ -3283,7 +3428,7 @@ void BKE_image_signal(Main *bmain, Image *ima, ImageUser *iuser, int signal)
case IMA_SIGNAL_USER_NEW_IMAGE:
if (iuser) {
iuser->ok = 1;
- if (ima->source == IMA_SRC_FILE || ima->source == IMA_SRC_SEQUENCE) {
+ if (ELEM(ima->source, IMA_SRC_FILE, IMA_SRC_SEQUENCE, IMA_SRC_TILED)) {
if (ima->type == IMA_TYPE_MULTILAYER) {
BKE_image_init_imageuser(ima, iuser);
}
@@ -3293,7 +3438,9 @@ void BKE_image_signal(Main *bmain, Image *ima, ImageUser *iuser, int signal)
case IMA_SIGNAL_COLORMANAGE:
BKE_image_free_buffers(ima);
- ima->ok = 1;
+ LISTBASE_FOREACH (ImageTile *, tile, &ima->tiles) {
+ tile->ok = 1;
+ }
if (iuser) {
iuser->ok = 1;
@@ -3360,6 +3507,107 @@ static RenderPass *image_render_pass_get(RenderLayer *rl,
return rpass_ret;
}
+void BKE_image_get_tile_label(Image *ima, ImageTile *tile, char *label, int len_label)
+{
+ label[0] = '\0';
+ if (ima == NULL || tile == NULL) {
+ return;
+ }
+
+ if (tile->label[0]) {
+ BLI_strncpy(label, tile->label, len_label);
+ }
+ else {
+ BLI_snprintf(label, len_label, "%d", tile->tile_number);
+ }
+}
+
+ImageTile *BKE_image_add_tile(struct Image *ima, int tile_number, const char *label)
+{
+ if (ima->source != IMA_SRC_TILED) {
+ return NULL;
+ }
+
+ if (tile_number < 1001 || tile_number > IMA_UDIM_MAX) {
+ return NULL;
+ }
+
+ /* Search the first tile that has a higher number.
+ * We then insert before that to keep the list sorted. */
+ ImageTile *next_tile;
+ for (next_tile = ima->tiles.first; next_tile; next_tile = next_tile->next) {
+ if (next_tile->tile_number == tile_number) {
+ /* Tile already exists. */
+ return NULL;
+ }
+ if (next_tile->tile_number > tile_number) {
+ break;
+ }
+ }
+
+ ImageTile *tile = MEM_callocN(sizeof(ImageTile), "image new tile");
+ tile->ok = 1;
+ tile->tile_number = tile_number;
+
+ if (next_tile) {
+ BLI_insertlinkbefore(&ima->tiles, next_tile, tile);
+ }
+ else {
+ BLI_addtail(&ima->tiles, tile);
+ }
+
+ if (label) {
+ BLI_strncpy(tile->label, label, sizeof(tile->label));
+ }
+
+ return tile;
+}
+
+bool BKE_image_remove_tile(struct Image *ima, ImageTile *tile)
+{
+ if (ima == NULL || tile == NULL || ima->source != IMA_SRC_TILED) {
+ return false;
+ }
+
+ if (tile == ima->tiles.first) {
+ /* Can't remove first tile. */
+ return false;
+ }
+
+ image_free_tile(ima, tile);
+ BLI_remlink(&ima->tiles, tile);
+ MEM_freeN(tile);
+
+ return true;
+}
+
+bool BKE_image_fill_tile(struct Image *ima,
+ ImageTile *tile,
+ int width,
+ int height,
+ const float color[4],
+ int gen_type,
+ int planes,
+ bool is_float)
+{
+ if (ima == NULL || tile == NULL || ima->source != IMA_SRC_TILED) {
+ return false;
+ }
+
+ image_free_tile(ima, tile);
+
+ ImBuf *tile_ibuf = add_ibuf_size(
+ width, height, ima->name, planes, is_float, gen_type, color, &ima->colorspace_settings);
+
+ if (tile_ibuf != NULL) {
+ image_assign_ibuf(ima, tile_ibuf, 0, tile->tile_number);
+ BKE_image_release_ibuf(ima, tile_ibuf, NULL);
+ tile->ok = 1;
+ return true;
+ }
+ return false;
+}
+
/* if layer or pass changes, we need an index for the imbufs list */
/* note it is called for rendered results, but it doesn't use the index! */
/* and because rendered results use fake layer/passes, don't correct for wrong indices here */
@@ -3421,7 +3669,7 @@ void BKE_image_multiview_index(Image *ima, ImageUser *iuser)
/* and because rendered results use fake layer/passes, don't correct for wrong indices here */
bool BKE_image_is_multilayer(Image *ima)
{
- if (ELEM(ima->source, IMA_SRC_FILE, IMA_SRC_SEQUENCE)) {
+ if (ELEM(ima->source, IMA_SRC_FILE, IMA_SRC_SEQUENCE, IMA_SRC_TILED)) {
if (ima->type == IMA_TYPE_MULTILAYER) {
return true;
}
@@ -3512,7 +3760,7 @@ void BKE_image_release_renderresult(Scene *scene, Image *ima)
bool BKE_image_is_openexr(struct Image *ima)
{
#ifdef WITH_OPENEXR
- if (ELEM(ima->source, IMA_SRC_FILE, IMA_SRC_SEQUENCE)) {
+ if (ELEM(ima->source, IMA_SRC_FILE, IMA_SRC_SEQUENCE, IMA_SRC_TILED)) {
return BLI_path_extension_check(ima->name, ".exr");
}
#else
@@ -3617,7 +3865,7 @@ static void image_create_multilayer(Image *ima, ImBuf *ibuf, int framenr)
#endif /* WITH_OPENEXR */
/* common stuff to do with images after loading */
-static void image_initialize_after_load(Image *ima, ImBuf *UNUSED(ibuf))
+static void image_initialize_after_load(Image *ima, ImageUser *iuser, ImBuf *UNUSED(ibuf))
{
/* Preview is NULL when it has never been used as an icon before.
* Never handle previews/icons outside of main thread. */
@@ -3628,7 +3876,8 @@ static void image_initialize_after_load(Image *ima, ImBuf *UNUSED(ibuf))
/* timer */
BKE_image_tag_time(ima);
- ima->ok = IMA_OK_LOADED;
+ ImageTile *tile = BKE_image_get_tile_from_iuser(ima, iuser);
+ tile->ok = IMA_OK_LOADED;
}
static int imbuf_alpha_flags_for_image(Image *ima)
@@ -3712,19 +3961,25 @@ static ImBuf *load_sequence_single(
}
}
else {
- image_initialize_after_load(ima, ibuf);
+ image_initialize_after_load(ima, iuser, ibuf);
*r_assign = true;
}
#else
- image_initialize_after_load(ima, ibuf);
+ image_initialize_after_load(ima, iuser, ibuf);
*r_assign = true;
#endif
}
+ else {
+ ImageTile *tile = BKE_image_get_tile_from_iuser(ima, iuser);
+ if (tile != NULL) {
+ tile->ok = 0;
+ }
+ }
return ibuf;
}
-static ImBuf *image_load_sequence_file(Image *ima, ImageUser *iuser, int frame)
+static ImBuf *image_load_sequence_file(Image *ima, ImageUser *iuser, int entry, int frame)
{
struct ImBuf *ibuf = NULL;
const bool is_multiview = BKE_image_is_multiview(ima);
@@ -3734,7 +3989,7 @@ static ImBuf *image_load_sequence_file(Image *ima, ImageUser *iuser, int frame)
if (!is_multiview) {
ibuf = load_sequence_single(ima, iuser, frame, 0, &assign);
if (assign) {
- image_assign_ibuf(ima, ibuf, 0, frame);
+ image_assign_ibuf(ima, ibuf, 0, entry);
}
}
else {
@@ -3757,7 +4012,7 @@ static ImBuf *image_load_sequence_file(Image *ima, ImageUser *iuser, int frame)
if (assign) {
for (i = 0; i < totviews; i++) {
- image_assign_ibuf(ima, ibuf_arr[i], i, frame);
+ image_assign_ibuf(ima, ibuf_arr[i], i, entry);
}
}
@@ -3775,9 +4030,10 @@ static ImBuf *image_load_sequence_file(Image *ima, ImageUser *iuser, int frame)
return ibuf;
}
-static ImBuf *image_load_sequence_multilayer(Image *ima, ImageUser *iuser, int frame)
+static ImBuf *image_load_sequence_multilayer(Image *ima, ImageUser *iuser, int entry, int frame)
{
struct ImBuf *ibuf = NULL;
+ ImageTile *tile = BKE_image_get_tile_from_iuser(ima, iuser);
/* either we load from RenderResult, or we have to load a new one */
@@ -3793,7 +4049,7 @@ static ImBuf *image_load_sequence_multilayer(Image *ima, ImageUser *iuser, int f
ima->rr = NULL;
}
- ibuf = image_load_sequence_file(ima, iuser, frame);
+ ibuf = image_load_sequence_file(ima, iuser, entry, frame);
if (ibuf) { /* actually an error */
ima->type = IMA_TYPE_IMAGE;
@@ -3814,17 +4070,17 @@ static ImBuf *image_load_sequence_multilayer(Image *ima, ImageUser *iuser, int f
BKE_imbuf_stamp_info(ima->rr, ibuf);
- image_initialize_after_load(ima, ibuf);
- image_assign_ibuf(ima, ibuf, iuser ? iuser->multi_index : 0, frame);
+ image_initialize_after_load(ima, iuser, ibuf);
+ image_assign_ibuf(ima, ibuf, iuser ? iuser->multi_index : 0, entry);
}
// else printf("pass not found\n");
}
else {
- ima->ok = 0;
+ tile->ok = 0;
}
if (iuser) {
- iuser->ok = ima->ok;
+ iuser->ok = tile->ok;
}
return ibuf;
@@ -3837,6 +4093,8 @@ static ImBuf *load_movie_single(Image *ima, ImageUser *iuser, int frame, const i
ia = BLI_findlink(&ima->anims, view_id);
+ ImageTile *tile = BKE_image_get_tile(ima, 0);
+
if (ia->anim == NULL) {
char str[FILE_MAX];
int flags = IB_rect;
@@ -3876,14 +4134,14 @@ static ImBuf *load_movie_single(Image *ima, ImageUser *iuser, int frame, const i
ibuf = IMB_makeSingleUser(IMB_anim_absolute(ia->anim, fra, IMB_TC_RECORD_RUN, IMB_PROXY_NONE));
if (ibuf) {
- image_initialize_after_load(ima, ibuf);
+ image_initialize_after_load(ima, iuser, ibuf);
}
else {
- ima->ok = 0;
+ tile->ok = 0;
}
}
else {
- ima->ok = 0;
+ tile->ok = 0;
}
return ibuf;
@@ -3894,6 +4152,7 @@ static ImBuf *image_load_movie_file(Image *ima, ImageUser *iuser, int frame)
struct ImBuf *ibuf = NULL;
const bool is_multiview = BKE_image_is_multiview(ima);
const int totfiles = image_num_files(ima);
+ ImageTile *tile = BKE_image_get_tile(ima, 0);
int i;
if (totfiles != BLI_listbase_count_at_most(&ima->anims, totfiles + 1)) {
@@ -3929,7 +4188,7 @@ static ImBuf *image_load_movie_file(Image *ima, ImageUser *iuser, int frame)
image_assign_ibuf(ima, ibuf_arr[i], i, frame);
}
else {
- ima->ok = 0;
+ tile->ok = 0;
}
}
@@ -3948,7 +4207,7 @@ static ImBuf *image_load_movie_file(Image *ima, ImageUser *iuser, int frame)
}
if (iuser) {
- iuser->ok = ima->ok;
+ iuser->ok = tile->ok;
}
return ibuf;
@@ -4020,7 +4279,7 @@ static ImBuf *load_image_single(Image *ima,
else
#endif
{
- image_initialize_after_load(ima, ibuf);
+ image_initialize_after_load(ima, iuser, ibuf);
*r_assign = true;
/* make packed file for autopack */
@@ -4035,7 +4294,8 @@ static ImBuf *load_image_single(Image *ima,
}
}
else {
- ima->ok = 0;
+ ImageTile *tile = BKE_image_get_tile_from_iuser(ima, iuser);
+ tile->ok = 0;
}
return ibuf;
@@ -4109,7 +4369,8 @@ static ImBuf *image_load_image_file(Image *ima, ImageUser *iuser, int cfra)
}
if (iuser) {
- iuser->ok = ima->ok;
+ ImageTile *tile = BKE_image_get_tile(ima, 0);
+ iuser->ok = tile->ok;
}
return ibuf;
@@ -4132,7 +4393,7 @@ static ImBuf *image_get_ibuf_multilayer(Image *ima, ImageUser *iuser)
if (rpass) {
ibuf = IMB_allocImBuf(ima->rr->rectx, ima->rr->recty, 32, 0);
- image_initialize_after_load(ima, ibuf);
+ image_initialize_after_load(ima, iuser, ibuf);
ibuf->rect_float = rpass->rect;
ibuf->flags |= IB_rectfloat;
@@ -4144,11 +4405,12 @@ static ImBuf *image_get_ibuf_multilayer(Image *ima, ImageUser *iuser)
}
}
+ ImageTile *tile = BKE_image_get_tile(ima, 0);
if (ibuf == NULL) {
- ima->ok = 0;
+ tile->ok = 0;
}
if (iuser) {
- iuser->ok = ima->ok;
+ iuser->ok = tile->ok;
}
return ibuf;
@@ -4268,7 +4530,7 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **r_loc
}
}
- ibuf = image_get_cached_ibuf_for_index_frame(ima, IMA_NO_INDEX, 0);
+ ibuf = image_get_cached_ibuf_for_index_entry(ima, IMA_NO_INDEX, 0);
/* make ibuf if needed, and initialize it */
if (ibuf == NULL) {
@@ -4345,7 +4607,8 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **r_loc
ibuf->dither = dither;
- ima->ok = IMA_OK_LOADED;
+ ImageTile *tile = BKE_image_get_tile(ima, 0);
+ tile->ok = IMA_OK_LOADED;
return ibuf;
}
@@ -4355,7 +4618,7 @@ static int image_get_multiview_index(Image *ima, ImageUser *iuser)
const bool is_multilayer = BKE_image_is_multilayer(ima);
const bool is_backdrop = (ima->source == IMA_SRC_VIEWER) && (ima->type == IMA_TYPE_COMPOSITE) &&
(iuser == NULL);
- int index = BKE_image_is_animated(ima) ? 0 : IMA_NO_INDEX;
+ int index = BKE_image_has_multiple_ibufs(ima) ? 0 : IMA_NO_INDEX;
if (is_multilayer) {
return iuser ? iuser->multi_index : index;
@@ -4373,7 +4636,7 @@ static int image_get_multiview_index(Image *ima, ImageUser *iuser)
return index;
}
-static void image_get_frame_and_index(Image *ima, ImageUser *iuser, int *r_frame, int *r_index)
+static void image_get_entry_and_index(Image *ima, ImageUser *iuser, int *r_entry, int *r_index)
{
int frame = 0, index = image_get_multiview_index(ima, iuser);
@@ -4390,7 +4653,7 @@ static void image_get_frame_and_index(Image *ima, ImageUser *iuser, int *r_frame
}
}
- *r_frame = frame;
+ *r_entry = frame;
*r_index = index;
}
@@ -4400,58 +4663,75 @@ static void image_get_frame_and_index(Image *ima, ImageUser *iuser, int *r_frame
* call IMB_freeImBuf to de-reference the image buffer after
* it's done handling it.
*/
-static ImBuf *image_get_cached_ibuf(Image *ima, ImageUser *iuser, int *r_frame, int *r_index)
+static ImBuf *image_get_cached_ibuf(Image *ima, ImageUser *iuser, int *r_entry, int *r_index)
{
ImBuf *ibuf = NULL;
- int frame = 0, index = image_get_multiview_index(ima, iuser);
+ int entry = 0, index = image_get_multiview_index(ima, iuser);
/* see if we already have an appropriate ibuf, with image source and type */
if (ima->source == IMA_SRC_MOVIE) {
- frame = iuser ? iuser->framenr : ima->lastframe;
- ibuf = image_get_cached_ibuf_for_index_frame(ima, index, frame);
- ima->lastframe = frame;
+ entry = iuser ? iuser->framenr : ima->lastframe;
+ ibuf = image_get_cached_ibuf_for_index_entry(ima, index, entry);
+ ima->lastframe = entry;
}
else if (ima->source == IMA_SRC_SEQUENCE) {
if (ima->type == IMA_TYPE_IMAGE) {
- frame = iuser ? iuser->framenr : ima->lastframe;
- ibuf = image_get_cached_ibuf_for_index_frame(ima, index, frame);
- ima->lastframe = frame;
+ entry = iuser ? iuser->framenr : ima->lastframe;
+ ibuf = image_get_cached_ibuf_for_index_entry(ima, index, entry);
+ ima->lastframe = entry;
/* counter the fact that image is set as invalid when loading a frame
* that is not in the cache (through image_acquire_ibuf for instance),
* yet we have valid frames in the cache loaded */
if (ibuf) {
- ima->ok = IMA_OK_LOADED;
+ ImageTile *tile = BKE_image_get_tile(ima, 0);
+ tile->ok = IMA_OK_LOADED;
if (iuser) {
- iuser->ok = ima->ok;
+ iuser->ok = tile->ok;
}
}
}
else if (ima->type == IMA_TYPE_MULTILAYER) {
- frame = iuser ? iuser->framenr : ima->lastframe;
- ibuf = image_get_cached_ibuf_for_index_frame(ima, index, frame);
+ entry = iuser ? iuser->framenr : ima->lastframe;
+ ibuf = image_get_cached_ibuf_for_index_entry(ima, index, entry);
}
}
else if (ima->source == IMA_SRC_FILE) {
if (ima->type == IMA_TYPE_IMAGE) {
- ibuf = image_get_cached_ibuf_for_index_frame(ima, index, 0);
+ ibuf = image_get_cached_ibuf_for_index_entry(ima, index, 0);
}
else if (ima->type == IMA_TYPE_MULTILAYER) {
- ibuf = image_get_cached_ibuf_for_index_frame(ima, index, 0);
+ ibuf = image_get_cached_ibuf_for_index_entry(ima, index, 0);
}
}
else if (ima->source == IMA_SRC_GENERATED) {
- ibuf = image_get_cached_ibuf_for_index_frame(ima, index, 0);
+ ibuf = image_get_cached_ibuf_for_index_entry(ima, index, 0);
}
else if (ima->source == IMA_SRC_VIEWER) {
/* always verify entirely, not that this shouldn't happen
* as part of texture sampling in rendering anyway, so not
* a big bottleneck */
}
+ else if (ima->source == IMA_SRC_TILED) {
+ if (ELEM(ima->type, IMA_TYPE_IMAGE, IMA_TYPE_MULTILAYER)) {
+ entry = (iuser && iuser->tile) ? iuser->tile : 1001;
+ ibuf = image_get_cached_ibuf_for_index_entry(ima, index, entry);
+
+ if ((ima->type == IMA_TYPE_IMAGE) && ibuf != NULL) {
+ ImageTile *tile = BKE_image_get_tile(ima, entry);
+ tile->ok = IMA_OK_LOADED;
+
+ /* iuser->ok is useless for tiled images because iuser->tile changes all the time. */
+ if (iuser != NULL) {
+ iuser->ok = 1;
+ }
+ }
+ }
+ }
- if (r_frame) {
- *r_frame = frame;
+ if (r_entry) {
+ *r_entry = entry;
}
if (r_index) {
@@ -4467,12 +4747,17 @@ BLI_INLINE bool image_quick_test(Image *ima, ImageUser *iuser)
return false;
}
+ ImageTile *tile = BKE_image_get_tile_from_iuser(ima, iuser);
+
if (iuser) {
if (iuser->ok == 0) {
return false;
}
}
- else if (ima->ok == 0) {
+ else if (tile == NULL) {
+ return false;
+ }
+ else if (tile->ok == 0) {
return false;
}
@@ -4486,7 +4771,7 @@ BLI_INLINE bool image_quick_test(Image *ima, ImageUser *iuser)
static ImBuf *image_acquire_ibuf(Image *ima, ImageUser *iuser, void **r_lock)
{
ImBuf *ibuf = NULL;
- int frame = 0, index = 0;
+ int entry = 0, index = 0;
if (r_lock) {
*r_lock = NULL;
@@ -4497,29 +4782,40 @@ static ImBuf *image_acquire_ibuf(Image *ima, ImageUser *iuser, void **r_lock)
return NULL;
}
- ibuf = image_get_cached_ibuf(ima, iuser, &frame, &index);
+ ibuf = image_get_cached_ibuf(ima, iuser, &entry, &index);
if (ibuf == NULL) {
/* we are sure we have to load the ibuf, using source and type */
if (ima->source == IMA_SRC_MOVIE) {
/* source is from single file, use flipbook to store ibuf */
- ibuf = image_load_movie_file(ima, iuser, frame);
+ ibuf = image_load_movie_file(ima, iuser, entry);
}
else if (ima->source == IMA_SRC_SEQUENCE) {
if (ima->type == IMA_TYPE_IMAGE) {
/* regular files, ibufs in flipbook, allows saving */
- ibuf = image_load_sequence_file(ima, iuser, frame);
+ ibuf = image_load_sequence_file(ima, iuser, entry, entry);
}
/* no else; on load the ima type can change */
if (ima->type == IMA_TYPE_MULTILAYER) {
/* only 1 layer/pass stored in imbufs, no exrhandle anim storage, no saving */
- ibuf = image_load_sequence_multilayer(ima, iuser, frame);
+ ibuf = image_load_sequence_multilayer(ima, iuser, entry, entry);
+ }
+ }
+ else if (ima->source == IMA_SRC_TILED) {
+ if (ima->type == IMA_TYPE_IMAGE) {
+ /* regular files, ibufs in flipbook, allows saving */
+ ibuf = image_load_sequence_file(ima, iuser, entry, 0);
+ }
+ /* no else; on load the ima type can change */
+ if (ima->type == IMA_TYPE_MULTILAYER) {
+ /* only 1 layer/pass stored in imbufs, no exrhandle anim storage, no saving */
+ ibuf = image_load_sequence_multilayer(ima, iuser, entry, 0);
}
}
else if (ima->source == IMA_SRC_FILE) {
if (ima->type == IMA_TYPE_IMAGE) {
- ibuf = image_load_image_file(ima, iuser, frame); /* cfra only for '#', this global is OK */
+ ibuf = image_load_image_file(ima, iuser, entry); /* cfra only for '#', this global is OK */
}
/* no else; on load the ima type can change */
if (ima->type == IMA_TYPE_MULTILAYER) {
@@ -4548,7 +4844,8 @@ static ImBuf *image_acquire_ibuf(Image *ima, ImageUser *iuser, void **r_lock)
ima->gen_color,
&ima->colorspace_settings);
image_assign_ibuf(ima, ibuf, index, 0);
- ima->ok = IMA_OK_LOADED;
+ ImageTile *tile = BKE_image_get_tile(ima, 0);
+ tile->ok = IMA_OK_LOADED;
}
else if (ima->source == IMA_SRC_VIEWER) {
if (ima->type == IMA_TYPE_R_RESULT) {
@@ -4564,14 +4861,14 @@ static ImBuf *image_acquire_ibuf(Image *ima, ImageUser *iuser, void **r_lock)
*r_lock = ima;
/* XXX anim play for viewer nodes not yet supported */
- frame = 0; // XXX iuser ? iuser->framenr : 0;
- ibuf = image_get_cached_ibuf_for_index_frame(ima, index, frame);
+ entry = 0; // XXX iuser ? iuser->framenr : 0;
+ ibuf = image_get_cached_ibuf_for_index_entry(ima, index, entry);
if (!ibuf) {
/* Composite Viewer, all handled in compositor */
/* fake ibuf, will be filled in compositor */
ibuf = IMB_allocImBuf(256, 256, 32, IB_rect | IB_rectfloat);
- image_assign_ibuf(ima, ibuf, index, frame);
+ image_assign_ibuf(ima, ibuf, index, entry);
}
}
}
@@ -4655,13 +4952,13 @@ bool BKE_image_has_ibuf(Image *ima, ImageUser *iuser)
/* ******** Pool for image buffers ******** */
-typedef struct ImagePoolEntry {
- struct ImagePoolEntry *next, *prev;
+typedef struct ImagePoolItem {
+ struct ImagePoolItem *next, *prev;
Image *image;
ImBuf *ibuf;
int index;
- int frame;
-} ImagePoolEntry;
+ int entry;
+} ImagePoolItem;
typedef struct ImagePool {
ListBase image_buffers;
@@ -4671,7 +4968,7 @@ typedef struct ImagePool {
ImagePool *BKE_image_pool_new(void)
{
ImagePool *pool = MEM_callocN(sizeof(ImagePool), "Image Pool");
- pool->memory_pool = BLI_mempool_create(sizeof(ImagePoolEntry), 0, 128, BLI_MEMPOOL_NOP);
+ pool->memory_pool = BLI_mempool_create(sizeof(ImagePoolItem), 0, 128, BLI_MEMPOOL_NOP);
return pool;
}
@@ -4680,9 +4977,9 @@ void BKE_image_pool_free(ImagePool *pool)
{
/* Use single lock to dereference all the image buffers. */
BLI_mutex_lock(image_mutex);
- for (ImagePoolEntry *entry = pool->image_buffers.first; entry != NULL; entry = entry->next) {
- if (entry->ibuf) {
- IMB_freeImBuf(entry->ibuf);
+ for (ImagePoolItem *item = pool->image_buffers.first; item != NULL; item = item->next) {
+ if (item->ibuf != NULL) {
+ IMB_freeImBuf(item->ibuf);
}
}
BLI_mutex_unlock(image_mutex);
@@ -4691,17 +4988,17 @@ void BKE_image_pool_free(ImagePool *pool)
MEM_freeN(pool);
}
-BLI_INLINE ImBuf *image_pool_find_entry(
- ImagePool *pool, Image *image, int frame, int index, bool *found)
+BLI_INLINE ImBuf *image_pool_find_item(
+ ImagePool *pool, Image *image, int entry, int index, bool *found)
{
- ImagePoolEntry *entry;
+ ImagePoolItem *item;
*found = false;
- for (entry = pool->image_buffers.first; entry; entry = entry->next) {
- if (entry->image == image && entry->frame == frame && entry->index == index) {
+ for (item = pool->image_buffers.first; item; item = item->next) {
+ if (item->image == image && item->entry == entry && item->index == index) {
*found = true;
- return entry->ibuf;
+ return item->ibuf;
}
}
@@ -4711,7 +5008,7 @@ BLI_INLINE ImBuf *image_pool_find_entry(
ImBuf *BKE_image_pool_acquire_ibuf(Image *ima, ImageUser *iuser, ImagePool *pool)
{
ImBuf *ibuf;
- int index, frame;
+ int index, entry;
bool found;
if (!image_quick_test(ima, iuser)) {
@@ -4723,32 +5020,32 @@ ImBuf *BKE_image_pool_acquire_ibuf(Image *ima, ImageUser *iuser, ImagePool *pool
return BKE_image_acquire_ibuf(ima, iuser, NULL);
}
- image_get_frame_and_index(ima, iuser, &frame, &index);
+ image_get_entry_and_index(ima, iuser, &entry, &index);
- ibuf = image_pool_find_entry(pool, ima, frame, index, &found);
+ ibuf = image_pool_find_item(pool, ima, entry, index, &found);
if (found) {
return ibuf;
}
BLI_mutex_lock(image_mutex);
- ibuf = image_pool_find_entry(pool, ima, frame, index, &found);
+ ibuf = image_pool_find_item(pool, ima, entry, index, &found);
- /* will also create entry even in cases image buffer failed to load,
+ /* will also create item even in cases image buffer failed to load,
* prevents trying to load the same buggy file multiple times
*/
if (!found) {
- ImagePoolEntry *entry;
+ ImagePoolItem *item;
ibuf = image_acquire_ibuf(ima, iuser, NULL);
- entry = BLI_mempool_alloc(pool->memory_pool);
- entry->image = ima;
- entry->frame = frame;
- entry->index = index;
- entry->ibuf = ibuf;
+ item = BLI_mempool_alloc(pool->memory_pool);
+ item->image = ima;
+ item->entry = entry;
+ item->index = index;
+ item->ibuf = ibuf;
- BLI_addtail(&pool->image_buffers, entry);
+ BLI_addtail(&pool->image_buffers, item);
}
BLI_mutex_unlock(image_mutex);
@@ -4946,13 +5243,20 @@ void BKE_image_user_file_path(ImageUser *iuser, Image *ima, char *filepath)
BLI_strncpy(filepath, ima->name, FILE_MAX);
}
- if (ima->source == IMA_SRC_SEQUENCE) {
+ if (ELEM(ima->source, IMA_SRC_SEQUENCE, IMA_SRC_TILED)) {
char head[FILE_MAX], tail[FILE_MAX];
unsigned short numlen;
- int frame = iuser ? iuser->framenr : ima->lastframe;
+
+ int index;
+ if (ima->source == IMA_SRC_SEQUENCE) {
+ index = iuser ? iuser->framenr : ima->lastframe;
+ }
+ else {
+ index = (iuser && iuser->tile) ? iuser->tile : 1001;
+ }
BLI_stringdec(filepath, head, tail, &numlen);
- BLI_stringenc(filepath, head, tail, numlen, frame);
+ BLI_stringenc(filepath, head, tail, numlen, index);
}
BLI_path_abs(filepath, ID_BLEND_PATH_FROM_GLOBAL(&ima->id));
@@ -5031,15 +5335,16 @@ void BKE_image_get_aspect(Image *image, float *aspx, float *aspy)
}
}
-unsigned char *BKE_image_get_pixels_for_frame(struct Image *image, int frame)
+unsigned char *BKE_image_get_pixels_for_frame(struct Image *image, int frame, int tile)
{
- ImageUser iuser = {NULL};
+ ImageUser iuser;
+ BKE_imageuser_default(&iuser);
void *lock;
ImBuf *ibuf;
unsigned char *pixels = NULL;
iuser.framenr = frame;
- iuser.ok = true;
+ iuser.tile = tile;
ibuf = BKE_image_acquire_ibuf(image, &iuser, &lock);
@@ -5060,15 +5365,16 @@ unsigned char *BKE_image_get_pixels_for_frame(struct Image *image, int frame)
return pixels;
}
-float *BKE_image_get_float_pixels_for_frame(struct Image *image, int frame)
+float *BKE_image_get_float_pixels_for_frame(struct Image *image, int frame, int tile)
{
- ImageUser iuser = {NULL};
+ ImageUser iuser;
+ BKE_imageuser_default(&iuser);
void *lock;
ImBuf *ibuf;
float *pixels = NULL;
iuser.framenr = frame;
- iuser.ok = true;
+ iuser.tile = tile;
ibuf = BKE_image_acquire_ibuf(image, &iuser, &lock);
@@ -5117,6 +5423,12 @@ bool BKE_image_is_animated(Image *image)
return ELEM(image->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE);
}
+/* Checks whether the image consists of multiple buffers. */
+bool BKE_image_has_multiple_ibufs(Image *image)
+{
+ return ELEM(image->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE, IMA_SRC_TILED);
+}
+
/* Image modifications */
bool BKE_image_is_dirty_writable(Image *image, bool *r_is_writable)
{
@@ -5233,7 +5545,7 @@ ImBuf *BKE_image_get_ibuf_with_name(Image *image, const char *name)
* References the result, #BKE_image_release_ibuf is to be called to de-reference.
* Use lock=NULL when calling #BKE_image_release_ibuf().
*
- * TODO(sergey): This is actually "get first entry from the cache", which is
+ * TODO(sergey): This is actually "get first item from the cache", which is
* not so much predictable. But using first loaded image buffer
* was also malicious logic and all the areas which uses this
* function are to be re-considered.