From de3df99e12a5ac9a5c65ca2e2a1bcc7c3d3066fe Mon Sep 17 00:00:00 2001 From: Alexandr Virodov Date: Thu, 18 May 2023 16:21:39 -0400 Subject: [PATCH 1/2] Do not pass explicit allocator to isyntax_load_tile(), instead take it from *isyntax. streamer not updated. --- src/isyntax/isyntax.c | 17 ++++++++--------- src/isyntax/isyntax.h | 3 +-- src/isyntax/isyntax_reader.c | 3 --- 3 files changed, 9 insertions(+), 14 deletions(-) diff --git a/src/isyntax/isyntax.c b/src/isyntax/isyntax.c index a98e695..f6e3c0e 100644 --- a/src/isyntax/isyntax.c +++ b/src/isyntax/isyntax.c @@ -1977,7 +1977,6 @@ u32 isyntax_idwt_tile_for_color_channel(isyntax_t* isyntax, isyntax_image_t* wsi } void isyntax_load_tile(isyntax_t* isyntax, isyntax_image_t* wsi, i32 scale, i32 tile_x, i32 tile_y, - block_allocator_t* ll_coeff_block_allocator, u32* out_buffer_or_null, enum isyntax_pixel_format_t pixel_format) { // printf("@@@ isyntax_load_tile scale=%d tile_x=%d tile_y=%d\n", scale, tile_x, tile_y); isyntax_level_t* level = wsi->levels + scale; @@ -2036,25 +2035,25 @@ void isyntax_load_tile(isyntax_t* isyntax, isyntax_image_t* wsi, i32 scale, i32 // TODO(avirodov): instead of releasing here, skip copy if still allocated. if (child_top_left->color_channels[color].coeff_ll) { - block_free(ll_coeff_block_allocator, child_top_left->color_channels[color].coeff_ll); + block_free(isyntax->ll_coeff_block_allocator, child_top_left->color_channels[color].coeff_ll); } if (child_top_right->color_channels[color].coeff_ll) { - block_free(ll_coeff_block_allocator, child_top_right->color_channels[color].coeff_ll); + block_free(isyntax->ll_coeff_block_allocator, child_top_right->color_channels[color].coeff_ll); } if (child_bottom_left->color_channels[color].coeff_ll) { - block_free(ll_coeff_block_allocator, child_bottom_left->color_channels[color].coeff_ll); + block_free(isyntax->ll_coeff_block_allocator, child_bottom_left->color_channels[color].coeff_ll); } if (child_bottom_right->color_channels[color].coeff_ll) { - block_free(ll_coeff_block_allocator, child_bottom_right->color_channels[color].coeff_ll); + block_free(isyntax->ll_coeff_block_allocator, child_bottom_right->color_channels[color].coeff_ll); } // NOTE: malloc() and free() can become a bottleneck, they don't scale well especially across many threads. // We use a custom block allocator to address this. i64 start_malloc = get_clock(); - child_top_left->color_channels[color].coeff_ll = (icoeff_t*)block_alloc(ll_coeff_block_allocator); - child_top_right->color_channels[color].coeff_ll = (icoeff_t*)block_alloc(ll_coeff_block_allocator); - child_bottom_left->color_channels[color].coeff_ll = (icoeff_t*)block_alloc(ll_coeff_block_allocator); - child_bottom_right->color_channels[color].coeff_ll = (icoeff_t*)block_alloc(ll_coeff_block_allocator); + child_top_left->color_channels[color].coeff_ll = (icoeff_t*)block_alloc(isyntax->ll_coeff_block_allocator); + child_top_right->color_channels[color].coeff_ll = (icoeff_t*)block_alloc(isyntax->ll_coeff_block_allocator); + child_bottom_left->color_channels[color].coeff_ll = (icoeff_t*)block_alloc(isyntax->ll_coeff_block_allocator); + child_bottom_right->color_channels[color].coeff_ll = (icoeff_t*)block_alloc(isyntax->ll_coeff_block_allocator); elapsed_malloc += get_seconds_elapsed(start_malloc, get_clock()); i32 dest_stride = block_width; // Blit top left child LL block diff --git a/src/isyntax/isyntax.h b/src/isyntax/isyntax.h index 99ca08b..2e27b94 100644 --- a/src/isyntax/isyntax.h +++ b/src/isyntax/isyntax.h @@ -397,8 +397,7 @@ void isyntax_set_work_queue(isyntax_t* isyntax, work_queue_t* work_queue); bool isyntax_open(isyntax_t* isyntax, const char* filename, bool init_allocators); void isyntax_destroy(isyntax_t* isyntax); void isyntax_idwt(icoeff_t* idwt, i32 quadrant_width, i32 quadrant_height, bool output_steps_as_png, const char* png_name); -void isyntax_load_tile(isyntax_t* isyntax, isyntax_image_t* wsi, i32 scale, i32 tile_x, i32 tile_y, block_allocator_t* ll_coeff_block_allocator, - u32* out_buffer_or_null, enum isyntax_pixel_format_t pixel_format); +void isyntax_load_tile(isyntax_t* isyntax, isyntax_image_t* wsi, i32 scale, i32 tile_x, i32 tile_y, u32* out_buffer_or_null, enum isyntax_pixel_format_t pixel_format); u32 isyntax_get_adjacent_tiles_mask(isyntax_level_t* level, i32 tile_x, i32 tile_y); u32 isyntax_get_adjacent_tiles_mask_only_existing(isyntax_level_t* level, i32 tile_x, i32 tile_y); u32 isyntax_idwt_tile_for_color_channel(isyntax_t* isyntax, isyntax_image_t* wsi, i32 scale, i32 tile_x, i32 tile_y, i32 color, icoeff_t* dest_buffer); diff --git a/src/isyntax/isyntax_reader.c b/src/isyntax/isyntax_reader.c index 3cd2627..5c99efa 100644 --- a/src/isyntax/isyntax_reader.c +++ b/src/isyntax/isyntax_reader.c @@ -206,7 +206,6 @@ static void isyntax_openslide_idwt(isyntax_cache_t* cache, isyntax_t* isyntax, i ASSERT(pixels_buffer != NULL); // Shouldn't be asking for idwt at level 0 if we're not going to use the result for pixels. isyntax_load_tile(isyntax, &isyntax->images[isyntax->wsi_image_index], tile->tile_scale, tile->tile_x, tile->tile_y, - &cache->ll_coeff_block_allocator, pixels_buffer, pixel_format); return; } @@ -216,7 +215,6 @@ static void isyntax_openslide_idwt(isyntax_cache_t* cache, isyntax_t* isyntax, i // the lls in the tile. Currently need to recompute idwt. isyntax_load_tile(isyntax, &isyntax->images[isyntax->wsi_image_index], tile->tile_scale, tile->tile_x, tile->tile_y, - &cache->ll_coeff_block_allocator, pixels_buffer, pixel_format); return; } @@ -231,7 +229,6 @@ static void isyntax_openslide_idwt(isyntax_cache_t* cache, isyntax_t* isyntax, i isyntax_load_tile(isyntax, &isyntax->images[isyntax->wsi_image_index], tile->tile_scale, tile->tile_x, tile->tile_y, - &cache->ll_coeff_block_allocator, /*pixels_buffer=*/NULL, /*pixel_format=*/0); } From 7755e6d6aab7cddf1777a8ee564bbe7129d69f02 Mon Sep 17 00:00:00 2001 From: Alexandr Virodov Date: Thu, 18 May 2023 16:46:31 -0400 Subject: [PATCH 2/2] Make cache management global only and move it under the libisyntax api. --- src/isyntax/isyntax.c | 32 +++++++------ src/isyntax/isyntax_reader.c | 91 +++++++++++++++++++++++++++++------- src/isyntax/isyntax_reader.h | 5 ++ src/isyntax_example.c | 9 +--- src/libisyntax.c | 77 +++++------------------------- src/libisyntax.h | 18 ++----- 6 files changed, 113 insertions(+), 119 deletions(-) diff --git a/src/isyntax/isyntax.c b/src/isyntax/isyntax.c index f6e3c0e..e20aa97 100644 --- a/src/isyntax/isyntax.c +++ b/src/isyntax/isyntax.c @@ -3347,6 +3347,22 @@ void isyntax_destroy(isyntax_t* isyntax) { if (isyntax->h_coeff_block_allocator->is_valid) { block_allocator_destroy(isyntax->h_coeff_block_allocator); } + } else { + // Need to individually deallocate tiles from a shared allocator, especially if not tracked via a cache. + isyntax_image_t* wsi_image = isyntax->images + isyntax->wsi_image_index; + for (i32 i = 0; i < wsi_image->level_count; ++i) { + isyntax_level_t* level = wsi_image->levels + i; + if (level->tiles) { + for (i32 j = 0; j < level->tile_count; ++j) { + isyntax_tile_t* tile = level->tiles + j; + for (i32 color = 0; color < 3; ++color) { + isyntax_tile_channel_t* channel = tile->color_channels + color; + if (channel->coeff_ll) free(channel->coeff_ll); + if (channel->coeff_h) free(channel->coeff_h); + } + } + } + } } if (isyntax->black_dummy_coeff) { free(isyntax->black_dummy_coeff); @@ -3375,20 +3391,8 @@ void isyntax_destroy(isyntax_t* isyntax) { } for (i32 i = 0; i < image->level_count; ++i) { isyntax_level_t* level = image->levels + i; - if (level->tiles) { -#if 0 - for (i32 j = 0; j < level->tile_count; ++j) { - isyntax_tile_t* tile = level->tiles + j; - for (i32 color = 0; color < 3; ++color) { - isyntax_tile_channel_t* channel = tile->color_channels + color; - if (channel->coeff_ll) free(channel->coeff_ll); - if (channel->coeff_h) free(channel->coeff_h); - } - } -#endif - free(level->tiles); - level->tiles = NULL; - } + free(level->tiles); + level->tiles = NULL; } } } diff --git a/src/isyntax/isyntax_reader.c b/src/isyntax/isyntax_reader.c index 5c99efa..b84b082 100644 --- a/src/isyntax/isyntax_reader.c +++ b/src/isyntax/isyntax_reader.c @@ -31,6 +31,78 @@ #define LOG(msg, ...) console_print(msg, ##__VA_ARGS__) #define LOG_VAR(fmt, var) console_print("%s: %s=" fmt "\n", __FUNCTION__, #var, var) +isyntax_cache_t* isyntax_cache_create(const char* debug_name_or_null, int32_t cache_size) +{ + isyntax_cache_t* cache_ptr = malloc(sizeof(isyntax_cache_t)); + memset(cache_ptr, 0, sizeof(*cache_ptr)); + tile_list_init(&cache_ptr->cache_list, debug_name_or_null); + cache_ptr->target_cache_size = cache_size; + cache_ptr->mutex = benaphore_create(); + + // Note: rest of initialization is deferred to the first injection, as that is where we will know the block size. + return cache_ptr; +} + +void isyntax_cache_inject(isyntax_cache_t* isyntax_cache, isyntax_t* isyntax) { + ASSERT(isyntax->ll_coeff_block_allocator == NULL); + ASSERT(isyntax->h_coeff_block_allocator == NULL); + + if (!isyntax_cache->h_coeff_block_allocator.is_valid || !isyntax_cache->ll_coeff_block_allocator.is_valid) { + // Shouldn't ever partially initialize. + ASSERT(!isyntax_cache->h_coeff_block_allocator.is_valid); + ASSERT(!isyntax_cache->ll_coeff_block_allocator.is_valid); + + isyntax_cache->allocator_block_width = isyntax->block_width; + isyntax_cache->allocator_block_height = isyntax->block_height; + size_t ll_coeff_block_size = isyntax->block_width * isyntax->block_height * sizeof(icoeff_t); + size_t block_allocator_maximum_capacity_in_blocks = GIGABYTES(32) / ll_coeff_block_size; + size_t ll_coeff_block_allocator_capacity_in_blocks = block_allocator_maximum_capacity_in_blocks / 4; + size_t h_coeff_block_size = ll_coeff_block_size * 3; + size_t h_coeff_block_allocator_capacity_in_blocks = ll_coeff_block_allocator_capacity_in_blocks * 3; + isyntax_cache->ll_coeff_block_allocator = block_allocator_create(ll_coeff_block_size, ll_coeff_block_allocator_capacity_in_blocks, MEGABYTES(256)); + isyntax_cache->h_coeff_block_allocator = block_allocator_create(h_coeff_block_size, h_coeff_block_allocator_capacity_in_blocks, MEGABYTES(256)); + } + + // having multiple iSyntax with different block sizes opened with a shared cache is not supported. + ASSERT(isyntax_cache->allocator_block_width == isyntax->block_width); + ASSERT(isyntax_cache->allocator_block_height == isyntax->block_height); + + isyntax->ll_coeff_block_allocator = &isyntax_cache->ll_coeff_block_allocator; + isyntax->h_coeff_block_allocator = &isyntax_cache->h_coeff_block_allocator; + isyntax->is_block_allocator_owned = false; +} + +void isyntax_cache_destroy(isyntax_cache_t* isyntax_cache) { + if (isyntax_cache->ll_coeff_block_allocator.is_valid) { + block_allocator_destroy(&isyntax_cache->ll_coeff_block_allocator); + } + if (isyntax_cache->h_coeff_block_allocator.is_valid) { + block_allocator_destroy(&isyntax_cache->h_coeff_block_allocator); + } + benaphore_destroy(&isyntax_cache->mutex); + free(isyntax_cache); +} + +void isyntax_cache_trim(isyntax_cache_t* isyntax_cache, i32 target_size) { + // TODO(avirodov): later will need to skip tiles that are reserved by other threads. + while (isyntax_cache->cache_list.count > target_size) { + isyntax_tile_t* tile = isyntax_cache->cache_list.tail; + tile_list_remove(&isyntax_cache->cache_list, tile); + for (int i = 0; i < 3; ++i) { + if (tile->has_ll) { + block_free(&isyntax_cache->ll_coeff_block_allocator, tile->color_channels[i].coeff_ll); + tile->color_channels[i].coeff_ll = NULL; + } + if (tile->has_h) { + block_free(&isyntax_cache->h_coeff_block_allocator, tile->color_channels[i].coeff_h); + tile->color_channels[i].coeff_h = NULL; + } + } + tile->has_ll = false; + tile->has_h = false; + } +} + void tile_list_init(isyntax_tile_list_t* list, const char* dbg_name) { list->head = NULL; list->tail = NULL; @@ -393,23 +465,6 @@ void isyntax_tile_read(isyntax_t* isyntax, isyntax_cache_t* cache, int scale, in // Cache trim. Since we have the result already, it is possible that tiles from this run will be trimmed here // if cache is small or work happened on other threads. - // TODO(avirodov): later will need to skip tiles that are reserved by other threads. - while (cache->cache_list.count > cache->target_cache_size) { - isyntax_tile_t* tile = cache->cache_list.tail; - tile_list_remove(&cache->cache_list, tile); - for (int i = 0; i < 3; ++i) { - if (tile->has_ll) { - block_free(&cache->ll_coeff_block_allocator, tile->color_channels[i].coeff_ll); - tile->color_channels[i].coeff_ll = NULL; - } - if (tile->has_h) { - block_free(&cache->h_coeff_block_allocator, tile->color_channels[i].coeff_h); - tile->color_channels[i].coeff_h = NULL; - } - } - tile->has_ll = false; - tile->has_h = false; - } - + isyntax_cache_trim(cache, cache->target_cache_size); benaphore_unlock(&cache->mutex); } diff --git a/src/isyntax/isyntax_reader.h b/src/isyntax/isyntax_reader.h index 9eccf57..ec7f1b1 100644 --- a/src/isyntax/isyntax_reader.h +++ b/src/isyntax/isyntax_reader.h @@ -28,3 +28,8 @@ void isyntax_tile_read(isyntax_t* isyntax, isyntax_cache_t* cache, int scale, in void tile_list_init(isyntax_tile_list_t* list, const char* dbg_name); void tile_list_remove(isyntax_tile_list_t* list, isyntax_tile_t* tile); + +isyntax_cache_t* isyntax_cache_create(const char* debug_name_or_null, int32_t cache_size); +void isyntax_cache_inject(isyntax_cache_t* isyntax_cache, isyntax_t* isyntax); +void isyntax_cache_trim(isyntax_cache_t* isyntax_cache, i32 target_size); +void isyntax_cache_destroy(isyntax_cache_t* isyntax_cache); diff --git a/src/isyntax_example.c b/src/isyntax_example.c index fd62009..18b43e7 100644 --- a/src/isyntax_example.c +++ b/src/isyntax_example.c @@ -44,7 +44,7 @@ int main(int argc, char** argv) { libisyntax_init(); isyntax_t* isyntax; - if (libisyntax_open(filename, /*is_init_allocators=*/0, &isyntax) != LIBISYNTAX_OK) { + if (libisyntax_open(filename, &isyntax) != LIBISYNTAX_OK) { printf("Failed to open %s\n", filename); return -1; } @@ -66,13 +66,9 @@ int main(int argc, char** argv) { LOG_VAR("%d", tile_width); LOG_VAR("%d", tile_height); - isyntax_cache_t *isyntax_cache = NULL; - CHECK_LIBISYNTAX_OK(libisyntax_cache_create("example cache", 2000, &isyntax_cache)); - CHECK_LIBISYNTAX_OK(libisyntax_cache_inject(isyntax_cache, isyntax)); - // RGBA is what stbi expects. uint32_t *pixels_rgba = malloc(tile_width * tile_height * 4); - CHECK_LIBISYNTAX_OK(libisyntax_tile_read(isyntax, isyntax_cache, level, tile_x, tile_y, + CHECK_LIBISYNTAX_OK(libisyntax_tile_read(isyntax, level, tile_x, tile_y, pixels_rgba, LIBISYNTAX_PIXEL_FORMAT_RGBA)); printf("Writing %s...\n", output_png); @@ -80,7 +76,6 @@ int main(int argc, char** argv) { printf("Done writing %s.\n", output_png); free(pixels_rgba); - libisyntax_cache_destroy(isyntax_cache); } else if (argc >= 4) { diff --git a/src/libisyntax.c b/src/libisyntax.c index 954abe0..495a2cb 100644 --- a/src/libisyntax.c +++ b/src/libisyntax.c @@ -204,6 +204,8 @@ static benaphore_t* libisyntax_get_global_mutex() { return &libisyntax_global_mutex; } +static isyntax_cache_t* global_isyntax_cache = NULL; + isyntax_error_t libisyntax_init() { // Lock-unlock to ensure that all parallel calls to libisyntax_init() wait for the actual initialization to complete. benaphore_lock(libisyntax_get_global_mutex()); @@ -214,20 +216,22 @@ isyntax_error_t libisyntax_init() { get_system_info(false); DBGCTR_COUNT(dbgctr_init_thread_pool_counter); init_thread_pool(); + global_isyntax_cache = isyntax_cache_create("global", 2000); // TODO(avirodov): size hint. libisyntax_global_init_complete = true; } benaphore_unlock(libisyntax_get_global_mutex()); return LIBISYNTAX_OK; } -isyntax_error_t libisyntax_open(const char* filename, int32_t is_init_allocators, isyntax_t** out_isyntax) { +isyntax_error_t libisyntax_open(const char* filename, isyntax_t** out_isyntax) { // Note(avirodov): intentionally not changing api of isyntax_open. We can do that later if needed and reduce // the size/count of wrappers. isyntax_t* result = malloc(sizeof(isyntax_t)); memset(result, 0, sizeof(*result)); - bool success = isyntax_open(result, filename, is_init_allocators); + bool success = isyntax_open(result, filename, /*is_init_allocators=*/false); if (success) { + isyntax_cache_inject(global_isyntax_cache, result); *out_isyntax = result; return LIBISYNTAX_OK; } else { @@ -237,6 +241,8 @@ isyntax_error_t libisyntax_open(const char* filename, int32_t is_init_allocators } void libisyntax_close(isyntax_t* isyntax) { + // Force removal of this isyntax's tiles (and all other tiles as a side effect) from global cache here. + isyntax_cache_trim(global_isyntax_cache, /*target_size=*/0); isyntax_destroy(isyntax); free(isyntax); } @@ -293,69 +299,10 @@ float libisyntax_level_get_mpp_y(const isyntax_level_t* level) { return level->um_per_pixel_y; } -isyntax_error_t libisyntax_cache_create(const char* debug_name_or_null, int32_t cache_size, - isyntax_cache_t** out_isyntax_cache) -{ - isyntax_cache_t* cache_ptr = malloc(sizeof(isyntax_cache_t)); - memset(cache_ptr, 0, sizeof(*cache_ptr)); - tile_list_init(&cache_ptr->cache_list, debug_name_or_null); - cache_ptr->target_cache_size = cache_size; - cache_ptr->mutex = benaphore_create(); - - // Note: rest of initialization is deferred to the first injection, as that is where we will know the block size. - - *out_isyntax_cache = cache_ptr; - return LIBISYNTAX_OK; -} - -isyntax_error_t libisyntax_cache_inject(isyntax_cache_t* isyntax_cache, isyntax_t* isyntax) { - // TODO(avirodov): consider refactoring implementation to another file, here and in destroy. - if (isyntax->ll_coeff_block_allocator != NULL || isyntax->h_coeff_block_allocator != NULL) { - return LIBISYNTAX_INVALID_ARGUMENT; - } - - if (!isyntax_cache->h_coeff_block_allocator.is_valid || !isyntax_cache->ll_coeff_block_allocator.is_valid) { - // Shouldn't ever partially initialize. - ASSERT(!isyntax_cache->h_coeff_block_allocator.is_valid); - ASSERT(!isyntax_cache->ll_coeff_block_allocator.is_valid); - - isyntax_cache->allocator_block_width = isyntax->block_width; - isyntax_cache->allocator_block_height = isyntax->block_height; - size_t ll_coeff_block_size = isyntax->block_width * isyntax->block_height * sizeof(icoeff_t); - size_t block_allocator_maximum_capacity_in_blocks = GIGABYTES(32) / ll_coeff_block_size; - size_t ll_coeff_block_allocator_capacity_in_blocks = block_allocator_maximum_capacity_in_blocks / 4; - size_t h_coeff_block_size = ll_coeff_block_size * 3; - size_t h_coeff_block_allocator_capacity_in_blocks = ll_coeff_block_allocator_capacity_in_blocks * 3; - isyntax_cache->ll_coeff_block_allocator = block_allocator_create(ll_coeff_block_size, ll_coeff_block_allocator_capacity_in_blocks, MEGABYTES(256)); - isyntax_cache->h_coeff_block_allocator = block_allocator_create(h_coeff_block_size, h_coeff_block_allocator_capacity_in_blocks, MEGABYTES(256)); - } - - if (isyntax_cache->allocator_block_width != isyntax->block_width || - isyntax_cache->allocator_block_height != isyntax->block_height) { - return LIBISYNTAX_FATAL; // Not implemented, see todo in libisyntax.h. - } - - isyntax->ll_coeff_block_allocator = &isyntax_cache->ll_coeff_block_allocator; - isyntax->h_coeff_block_allocator = &isyntax_cache->h_coeff_block_allocator; - isyntax->is_block_allocator_owned = false; - return LIBISYNTAX_OK; -} - -void libisyntax_cache_destroy(isyntax_cache_t* isyntax_cache) { - if (isyntax_cache->ll_coeff_block_allocator.is_valid) { - block_allocator_destroy(&isyntax_cache->ll_coeff_block_allocator); - } - if (isyntax_cache->h_coeff_block_allocator.is_valid) { - block_allocator_destroy(&isyntax_cache->h_coeff_block_allocator); - } - benaphore_destroy(&isyntax_cache->mutex); - free(isyntax_cache); -} // TODO(pvalkema): should we allow passing a stride for the pixels_buffer, to allow blitting into buffers // that are not exactly the height/width of the region? -isyntax_error_t libisyntax_tile_read(isyntax_t* isyntax, isyntax_cache_t* isyntax_cache, - int32_t level, int64_t tile_x, int64_t tile_y, +isyntax_error_t libisyntax_tile_read(isyntax_t* isyntax, int32_t level, int64_t tile_x, int64_t tile_y, uint32_t* pixels_buffer, int32_t pixel_format) { if (pixel_format <= _LIBISYNTAX_PIXEL_FORMAT_START || pixel_format >= _LIBISYNTAX_PIXEL_FORMAT_END) { return LIBISYNTAX_INVALID_ARGUMENT; @@ -364,13 +311,13 @@ isyntax_error_t libisyntax_tile_read(isyntax_t* isyntax, isyntax_cache_t* isynta // TODO(avirodov): if isyntax_cache is null, we can support using allocators that are in isyntax object, // if is_init_allocators = 1 when created. Not sure is needed. - isyntax_tile_read(isyntax, isyntax_cache, level, tile_x, tile_y, pixels_buffer, pixel_format); + isyntax_tile_read(isyntax, global_isyntax_cache, level, tile_x, tile_y, pixels_buffer, pixel_format); return LIBISYNTAX_OK; } #define PER_LEVEL_PADDING 3 -isyntax_error_t libisyntax_read_region(isyntax_t* isyntax, isyntax_cache_t* isyntax_cache, int32_t level, +isyntax_error_t libisyntax_read_region(isyntax_t* isyntax, int32_t level, int64_t x, int64_t y, int64_t width, int64_t height, uint32_t* pixels_buffer, int32_t pixel_format) { @@ -415,7 +362,7 @@ isyntax_error_t libisyntax_read_region(isyntax_t* isyntax, isyntax_cache_t* isyn // TODO(pvalkema): be more robust here ASSERT(tile_x < current_level->width_in_tiles); ASSERT(tile_y < current_level->height_in_tiles); - CHECK_LIBISYNTAX_OK(libisyntax_tile_read(isyntax, isyntax_cache, level, tile_x, tile_y, tile_pixels, pixel_format)); + CHECK_LIBISYNTAX_OK(libisyntax_tile_read(isyntax, level, tile_x, tile_y, tile_pixels, pixel_format)); // Copy the relevant portion of the tile to the region for (int64_t i = 0; i < copy_height; ++i) { diff --git a/src/libisyntax.h b/src/libisyntax.h index 4b95a50..259c3d1 100644 --- a/src/libisyntax.h +++ b/src/libisyntax.h @@ -41,7 +41,7 @@ typedef struct isyntax_cache_t isyntax_cache_t; //== Common API == // TODO(avirodov): are repeated calls of libisyntax_init() allowed? Currently I believe not. isyntax_error_t libisyntax_init(); -isyntax_error_t libisyntax_open(const char* filename, int32_t is_init_allocators, isyntax_t** out_isyntax); +isyntax_error_t libisyntax_open(const char* filename, isyntax_t** out_isyntax); void libisyntax_close(isyntax_t* isyntax); //== Getters API == @@ -60,26 +60,14 @@ int32_t libisyntax_level_get_height(const isyntax_level_t* level) float libisyntax_level_get_mpp_x(const isyntax_level_t* level); float libisyntax_level_get_mpp_y(const isyntax_level_t* level); -//== Cache API == -isyntax_error_t libisyntax_cache_create(const char* debug_name_or_null, int32_t cache_size, - isyntax_cache_t** out_isyntax_cache); -// Note: returns LIBISYNTAX_INVALID_ARGUMENT if isyntax_to_inject was not initialized with is_init_allocators = 0. -// TODO(avirodov): this function will fail if the isyntax object has different block size than the first isyntax injected. -// Block size variation was not observed in practice, and a proper fix may include supporting multiple block sizes -// within isyntax_cache_t implementation. -isyntax_error_t libisyntax_cache_inject(isyntax_cache_t* isyntax_cache, isyntax_t* isyntax); -void libisyntax_cache_destroy(isyntax_cache_t* isyntax_cache); - - //== Tile API == // Reads a tile into a user-supplied buffer. Buffer size should be [tile_width * tile_height * 4], as returned by // `libisyntax_get_tile_width()`/`libisyntax_get_tile_height()`. The caller is responsible for managing the buffer // allocation/deallocation. // pixel_format is one of isyntax_pixel_format_t. -isyntax_error_t libisyntax_tile_read(isyntax_t* isyntax, isyntax_cache_t* isyntax_cache, - int32_t level, int64_t tile_x, int64_t tile_y, +isyntax_error_t libisyntax_tile_read(isyntax_t* isyntax, int32_t level, int64_t tile_x, int64_t tile_y, uint32_t* pixels_buffer, int32_t pixel_format); -isyntax_error_t libisyntax_read_region(isyntax_t* isyntax, isyntax_cache_t* isyntax_cache, int32_t level, +isyntax_error_t libisyntax_read_region(isyntax_t* isyntax, int32_t level, int64_t x, int64_t y, int64_t width, int64_t height, uint32_t* pixels_buffer, int32_t pixel_format);