diff options
Diffstat (limited to 'source/blender/blenkernel/intern/image.c')
-rw-r--r-- | source/blender/blenkernel/intern/image.c | 146 |
1 files changed, 111 insertions, 35 deletions
diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index f4ba1ff8b92..d87290e1eb4 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -229,12 +229,26 @@ static void image_blend_write(BlendWriter *writer, ID *id, const void *id_addres { Image *ima = (Image *)id; const bool is_undo = BLO_write_is_undo(writer); - if (ima->id.us > 0 || is_undo) { - ImagePackedFile *imapf; - BLI_assert(ima->packedfile == NULL); + /* Clear all data that isn't read to reduce false detection of changed image during memfile undo. + */ + ima->lastused = 0; + ima->cache = NULL; + ima->gpuflag = 0; + BLI_listbase_clear(&ima->anims); + BLI_listbase_clear(&ima->gpu_refresh_areas); + for (int i = 0; i < 3; i++) { + for (int j = 0; j < 2; j++) { + ima->gputexture[i][j] = NULL; + } + } + + ImagePackedFile *imapf; + + BLI_assert(ima->packedfile == NULL); + if (!is_undo) { /* Do not store packed files in case this is a library override ID. */ - if (ID_IS_OVERRIDE_LIBRARY(ima) && !is_undo) { + if (ID_IS_OVERRIDE_LIBRARY(ima)) { BLI_listbase_clear(&ima->packedfiles); } else { @@ -244,29 +258,29 @@ static void image_blend_write(BlendWriter *writer, ID *id, const void *id_addres ima->packedfile = imapf->packedfile; } } + } - /* write LibData */ - BLO_write_id_struct(writer, Image, id_address, &ima->id); - BKE_id_blend_write(writer, &ima->id); + /* write LibData */ + BLO_write_id_struct(writer, Image, id_address, &ima->id); + BKE_id_blend_write(writer, &ima->id); - for (imapf = ima->packedfiles.first; imapf; imapf = imapf->next) { - BLO_write_struct(writer, ImagePackedFile, imapf); - BKE_packedfile_blend_write(writer, imapf->packedfile); - } + for (imapf = ima->packedfiles.first; imapf; imapf = imapf->next) { + BLO_write_struct(writer, ImagePackedFile, imapf); + BKE_packedfile_blend_write(writer, imapf->packedfile); + } - BKE_previewimg_blend_write(writer, ima->preview); + BKE_previewimg_blend_write(writer, ima->preview); - LISTBASE_FOREACH (ImageView *, iv, &ima->views) { - BLO_write_struct(writer, ImageView, iv); - } - BLO_write_struct(writer, Stereo3dFormat, ima->stereo3d_format); + LISTBASE_FOREACH (ImageView *, iv, &ima->views) { + BLO_write_struct(writer, ImageView, iv); + } + BLO_write_struct(writer, Stereo3dFormat, ima->stereo3d_format); - BLO_write_struct_list(writer, ImageTile, &ima->tiles); + BLO_write_struct_list(writer, ImageTile, &ima->tiles); - ima->packedfile = NULL; + ima->packedfile = NULL; - BLO_write_struct_list(writer, RenderSlot, &ima->renderslots); - } + BLO_write_struct_list(writer, RenderSlot, &ima->renderslots); } static void image_blend_read_data(BlendDataReader *reader, ID *id) @@ -300,6 +314,7 @@ static void image_blend_read_data(BlendDataReader *reader, ID *id) LISTBASE_FOREACH (ImageTile *, tile, &ima->tiles) { tile->ok = IMA_OK; } + ima->lastused = 0; ima->gpuflag = 0; BLI_listbase_clear(&ima->gpu_refresh_areas); } @@ -519,7 +534,7 @@ void BKE_image_free_buffers(Image *ima) } /** Free (or release) any data used by this image (does not free the image itself). */ -void BKE_image_free(Image *ima) +void BKE_image_free_data(Image *ima) { image_free_data(&ima->id); } @@ -670,24 +685,27 @@ bool BKE_image_has_opengl_texture(Image *ima) return false; } +static int image_get_tile_number_from_iuser(Image *ima, const ImageUser *iuser) +{ + BLI_assert(ima != NULL && ima->tiles.first); + ImageTile *tile = ima->tiles.first; + return (iuser && iuser->tile) ? iuser->tile : tile->tile_number; +} + 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 + /* Tiles 0 and 1001 are a special case and refer to the first tile, typically * coming from non-UDIM-aware code. */ if (ELEM(tile_number, 0, 1001)) { return ima->tiles.first; } - if (ima->source != IMA_SRC_TILED) { + /* Must have a tiled image and a valid tile number at this point. */ + if (ima->source != IMA_SRC_TILED || tile_number < 1001 || tile_number > IMA_UDIM_MAX) { return NULL; } @@ -702,7 +720,7 @@ ImageTile *BKE_image_get_tile(Image *ima, int tile_number) ImageTile *BKE_image_get_tile_from_iuser(Image *ima, const ImageUser *iuser) { - return BKE_image_get_tile(ima, (iuser && iuser->tile) ? iuser->tile : 1001); + return BKE_image_get_tile(ima, image_get_tile_number_from_iuser(ima, iuser)); } int BKE_image_get_tile_from_pos(struct Image *ima, @@ -1020,7 +1038,7 @@ Image *BKE_image_add_generated(Main *bmain, int view_id; const char *names[2] = {STEREO_LEFT_NAME, STEREO_RIGHT_NAME}; - /* STRNCPY(ima->filepath, name); */ /* don't do this, this writes in ain invalid filepath! */ + // STRNCPY(ima->filepath, name); /* don't do this, this writes in ain invalid filepath! */ ima->gen_x = width; ima->gen_y = height; ima->gen_type = gen_type; @@ -3803,8 +3821,8 @@ bool BKE_image_remove_tile(struct Image *ima, ImageTile *tile) return false; } - if (tile == ima->tiles.first) { - /* Can't remove first tile. */ + if (BLI_listbase_is_single(&ima->tiles)) { + /* Can't remove the last remaining tile. */ return false; } @@ -3815,6 +3833,64 @@ bool BKE_image_remove_tile(struct Image *ima, ImageTile *tile) return true; } +void BKE_image_reassign_tile(struct Image *ima, ImageTile *tile, int new_tile_number) +{ + if (ima == NULL || tile == NULL || ima->source != IMA_SRC_TILED) { + return; + } + + if (new_tile_number < 1001 || new_tile_number > IMA_UDIM_MAX) { + return; + } + + const int old_tile_number = tile->tile_number; + tile->tile_number = new_tile_number; + + if (BKE_image_is_multiview(ima)) { + const int totviews = BLI_listbase_count(&ima->views); + for (int i = 0; i < totviews; i++) { + ImBuf *ibuf = image_get_cached_ibuf_for_index_entry(ima, i, old_tile_number); + image_remove_ibuf(ima, i, old_tile_number); + image_assign_ibuf(ima, ibuf, i, new_tile_number); + IMB_freeImBuf(ibuf); + } + } + else { + ImBuf *ibuf = image_get_cached_ibuf_for_index_entry(ima, 0, old_tile_number); + image_remove_ibuf(ima, 0, old_tile_number); + image_assign_ibuf(ima, ibuf, 0, new_tile_number); + IMB_freeImBuf(ibuf); + } + + for (int eye = 0; eye < 2; eye++) { + /* Reallocate GPU tile array. */ + if (ima->gputexture[TEXTARGET_2D_ARRAY][eye] != NULL) { + GPU_texture_free(ima->gputexture[TEXTARGET_2D_ARRAY][eye]); + ima->gputexture[TEXTARGET_2D_ARRAY][eye] = NULL; + } + if (ima->gputexture[TEXTARGET_TILE_MAPPING][eye] != NULL) { + GPU_texture_free(ima->gputexture[TEXTARGET_TILE_MAPPING][eye]); + ima->gputexture[TEXTARGET_TILE_MAPPING][eye] = NULL; + } + } +} + +static int tile_sort_cb(const void *a, const void *b) +{ + const ImageTile *tile_a = a; + const ImageTile *tile_b = b; + return (tile_a->tile_number > tile_b->tile_number) ? 1 : 0; +} + +void BKE_image_sort_tiles(struct Image *ima) +{ + if (ima == NULL || ima->source != IMA_SRC_TILED) { + return; + } + + BLI_listbase_sort(&ima->tiles, tile_sort_cb); +} + bool BKE_image_fill_tile(struct Image *ima, ImageTile *tile, int width, @@ -4890,7 +4966,7 @@ static void image_get_entry_and_index(Image *ima, ImageUser *iuser, int *r_entry } } else if (ima->source == IMA_SRC_TILED) { - frame = (iuser && iuser->tile) ? iuser->tile : 1001; + frame = image_get_tile_number_from_iuser(ima, iuser); } *r_entry = frame; @@ -4955,7 +5031,7 @@ static ImBuf *image_get_cached_ibuf(Image *ima, ImageUser *iuser, int *r_entry, } else if (ima->source == IMA_SRC_TILED) { if (ELEM(ima->type, IMA_TYPE_IMAGE, IMA_TYPE_MULTILAYER)) { - entry = (iuser && iuser->tile) ? iuser->tile : 1001; + entry = image_get_tile_number_from_iuser(ima, iuser); ibuf = image_get_cached_ibuf_for_index_entry(ima, index, entry); if ((ima->type == IMA_TYPE_IMAGE) && ibuf != NULL) { @@ -5507,7 +5583,7 @@ void BKE_image_user_file_path(ImageUser *iuser, Image *ima, char *filepath) index = iuser ? iuser->framenr : ima->lastframe; } else { - index = (iuser && iuser->tile) ? iuser->tile : 1001; + index = image_get_tile_number_from_iuser(ima, iuser); } BLI_path_sequence_decode(filepath, head, tail, &numlen); |