diff --git a/src/libpisp/backend/backend.cpp b/src/libpisp/backend/backend.cpp index edf3cc1..26fdde5 100644 --- a/src/libpisp/backend/backend.cpp +++ b/src/libpisp/backend/backend.cpp @@ -23,7 +23,6 @@ BackEnd::BackEnd(Config const &config, PiSPVariant const &variant) if (config_.max_tile_width > max_tile_width) PISP_LOG(fatal, "Configured max tile width " << config_.max_tile_width << " exceeds " << max_tile_width); - smart_resize_.resize(2, { 0, 0 }); smart_resize_dirty_ = 0; const char *env = std::getenv("LIBPISP_BE_CONFIG_FILE"); diff --git a/src/libpisp/backend/backend.hpp b/src/libpisp/backend/backend.hpp index cb5a4d2..0d572d3 100644 --- a/src/libpisp/backend/backend.hpp +++ b/src/libpisp/backend/backend.hpp @@ -7,11 +7,11 @@ */ #pragma once +#include #include #include #include #include -#include #include "common/shm_mutex.hpp" #include "tiling/pisp_tiling.hpp" @@ -24,6 +24,13 @@ namespace libpisp { +using TileArray = std::array; + +// We use std::array> insead of std::map<.,.> to ensure this object provides a standard layout. +using YcbcrMap = std::array, 16>; +using ResampleMap = std::array, 16>; +using ResampleList = std::array, 16>; + class BackEnd final { public: @@ -51,8 +58,8 @@ class BackEnd final struct SmartResize { - uint16_t width; - uint16_t height; + uint16_t width = 0; + uint16_t height = 0; }; BackEnd(Config const &user_config, PiSPVariant const &variant); @@ -165,7 +172,7 @@ class BackEnd final void finaliseConfig(); void updateSmartResize(); void updateTiles(); - std::vector retilePipeline(TilingConfig const &tiling_config); + TileArray retilePipeline(TilingConfig const &tiling_config); void finaliseTiling(); void getOutputSize(int output_num, uint16_t *width, uint16_t *height, pisp_image_format_config const &ifmt) const; @@ -178,18 +185,17 @@ class BackEnd final pisp_image_format_config max_input_; bool retile_; bool finalise_tiling_; - std::vector tiles_; + TileArray tiles_; int num_tiles_x_, num_tiles_y_; mutable ShmMutex mutex_; - std::vector smart_resize_; + std::array smart_resize_; uint32_t smart_resize_dirty_; // Default config - // We use std::vector> insead of std::map<.,.> to ensure this object provides a standard layout. - std::vector> ycbcr_map_; - std::vector> inverse_ycbcr_map_; - std::vector> resample_filter_map_; - std::vector> resample_select_list_; + YcbcrMap ycbcr_map_; + YcbcrMap inverse_ycbcr_map_; + ResampleMap resample_filter_map_; + ResampleList resample_select_list_; pisp_be_sharpen_config default_sharpen_; pisp_be_sh_fc_combine_config default_shfc_; }; diff --git a/src/libpisp/backend/backend_default_config.cpp b/src/libpisp/backend/backend_default_config.cpp index b0163b7..3286d89 100644 --- a/src/libpisp/backend/backend_default_config.cpp +++ b/src/libpisp/backend/backend_default_config.cpp @@ -133,10 +133,11 @@ void initialise_gamma(pisp_be_gamma_config &gamma, const json &root) } } -void read_resample(std::vector> &resample_filter_map, - std::vector> &resample_select_list, const json &root) +void read_resample(libpisp::ResampleMap &resample_filter_map, libpisp::ResampleList &resample_select_list, + const json &root) { auto &filters = root["resample"]["filters"]; + unsigned int i = 0, j = 0; for (auto const &[name, filter] : filters.items()) { @@ -148,22 +149,28 @@ void read_resample(std::vector> throw std::runtime_error("read_resample: Incorrect number of filter coefficients"); memcpy(r.coef, coefs.data(), sizeof(r.coef)); - resample_filter_map.emplace_back(name, r); + resample_filter_map[i++] = { name, r }; + if (i == resample_filter_map.size()) + break; } + i = 0; auto &smart = root["resample"]["smart_selection"]; for (auto &scale : smart["downscale"]) - resample_select_list.emplace_back(scale.get(), std::string {}); + { + resample_select_list[i++] = { scale.get(), std::string {} }; + if (i == resample_select_list.size()) + break; + } - unsigned int i = 0; for (auto &filter : smart["filter"]) { - resample_select_list[i].second = filter.get(); - if (++i == resample_select_list.size()) + resample_select_list[j++].second = filter.get(); + if (j == resample_select_list.size()) break; } - if (i != resample_select_list.size()) - throw std::runtime_error("read_resample: Incorrect number of filters"); + if (j != i) + throw std::runtime_error("read_resample: Incorrect number of smart filters/downscale factors"); } // Macros for the sharpening filters, to avoid repeating the same code 5 times @@ -222,10 +229,10 @@ void read_sharpen(pisp_be_sharpen_config &sharpen, pisp_be_sh_fc_combine_config shfc.y_factor = params["shfc_y_factor"].get() * (1 << 8); } -void read_ycbcr(std::vector> &ycbcr_map, - std::vector> &inverse_ycbcr_map, const json &root) +void read_ycbcr(libpisp::YcbcrMap &ycbcr_map, libpisp::YcbcrMap &inverse_ycbcr_map, const json &root) { auto encoding = root["colour_encoding"]; + unsigned int i = 0; for (auto const &[format, enc] : encoding.items()) { @@ -247,15 +254,17 @@ void read_ycbcr(std::vector> &ycbcr_m memcpy(ccm.offsets, offsets.data(), sizeof(ccm.offsets)); if (key == "ycbcr") - ycbcr_map.emplace_back(format, ccm); + ycbcr_map[i] = { format, ccm }; else - inverse_ycbcr_map.emplace_back(format, ccm); + inverse_ycbcr_map[i] = { format, ccm }; } + + if (++i == ycbcr_map.size()) + break; } } -void get_matrix(pisp_be_ccm_config &matrix, const std::vector> &map, - const std::string &colour_space) +void get_matrix(pisp_be_ccm_config &matrix, const libpisp::YcbcrMap &map, const std::string &colour_space) { memset(matrix.coeffs, 0, sizeof(matrix.coeffs)); memset(matrix.offsets, 0, sizeof(matrix.offsets)); diff --git a/src/libpisp/backend/backend_prepare.cpp b/src/libpisp/backend/backend_prepare.cpp index 689fa19..13accb0 100644 --- a/src/libpisp/backend/backend_prepare.cpp +++ b/src/libpisp/backend/backend_prepare.cpp @@ -304,12 +304,13 @@ void finalise_output(pisp_be_output_format_config &config) throw std::runtime_error("finalise_output: image stride should be at least 16-byte aligned"); } -void check_tiles(std::vector const &tiles, uint32_t rgb_enables, unsigned int numBranches, - TilingConfig const &tiling_config) +void check_tiles(TileArray const &tiles, uint32_t rgb_enables, unsigned int numBranches, unsigned int num_tiles, + TilingConfig const &tiling_config) { - int tile_num = 0; - for (auto &tile : tiles) + for (unsigned int tile_num = 0; tile_num < num_tiles; tile_num++) { + const pisp_tile &tile = tiles[tile_num]; + PISP_ASSERT(tile.input_width && tile.input_height); // zero inputs shouldn't be possible if (tile.input_width < PISP_BACK_END_MIN_TILE_WIDTH || tile.input_height < PISP_BACK_END_MIN_TILE_HEIGHT) @@ -361,7 +362,6 @@ void check_tiles(std::vector const &tiles, uint32_t rgb_enables, unsi throw std::runtime_error("Tile height too small at output"); } } - tile_num++; } } @@ -729,7 +729,8 @@ void BackEnd::updateTiles() // outside the actual image width (and we've chosen not to handle compression like that). tiling_config.compressed_input = false; tiles_ = retilePipeline(tiling_config); - check_tiles(tiles_, c.global.rgb_enables, variant_.BackEndNumBranches(0), tiling_config); + check_tiles(tiles_, c.global.rgb_enables, variant_.BackEndNumBranches(0), num_tiles_x_ * num_tiles_y_, + tiling_config); finalise_tiling_ = true; } @@ -740,7 +741,7 @@ void BackEnd::updateTiles() } } -std::vector BackEnd::retilePipeline(TilingConfig const &tiling_config) +TileArray BackEnd::retilePipeline(TilingConfig const &tiling_config) { // The tiling library provides tiles in a SW Tile structure. Tile tiles[PISP_BACK_END_NUM_TILES]; @@ -750,11 +751,11 @@ std::vector BackEnd::retilePipeline(TilingConfig const &tiling_config num_tiles_x_ = grid.dx; num_tiles_y_ = grid.dy; - std::vector tile_vector(num_tiles_x_ * num_tiles_y_); + TileArray tile_array; // Finally convert the Tiles into pisp_tiles. for (int i = 0; i < num_tiles_x_ * num_tiles_y_; i++) { - pisp_tile &t = tile_vector[i]; + pisp_tile &t = tile_array[i]; memset(&t, 0, sizeof(pisp_tile)); t.edge = 0; @@ -892,14 +893,16 @@ std::vector BackEnd::retilePipeline(TilingConfig const &tiling_config } } } - return tile_vector; + return tile_array; } void BackEnd::finaliseTiling() { // Update tile parameters (offsets/strides) from on the BE pipeline configuration. - for (pisp_tile &t : tiles_) + for (int i = 0; i < num_tiles_x_ * num_tiles_y_; i++) { + pisp_tile &t = tiles_[i]; + calculate_input_addr_offset(t.input_offset_x, t.input_offset_y, be_config_.input_format, &t.input_addr_offset, &t.input_addr_offset2); calculate_input_addr_offset(t.input_offset_x, t.input_offset_y, be_config_.tdn_input_format,