| 132 | } |
| 133 | |
| 134 | static Ref<Image> _dds_load_layer(Ref<FileAccess> p_file, DDSFormat p_dds_format, uint32_t p_width, uint32_t p_height, uint32_t p_mipmaps, uint32_t p_pitch, uint32_t p_flags, Vector<uint8_t> &r_src_data) { |
| 135 | const DDSFormatInfo &info = dds_format_info[p_dds_format]; |
| 136 | |
| 137 | uint32_t w = p_width; |
| 138 | uint32_t h = p_height; |
| 139 | |
| 140 | if (info.compressed) { |
| 141 | // BC compressed. |
| 142 | w += w % info.divisor; |
| 143 | h += h % info.divisor; |
| 144 | if (w != p_width) { |
| 145 | WARN_PRINT(vformat("%s: DDS width '%d' is not divisible by %d. This is not allowed as per the DDS specification, attempting to load anyway.", p_file->get_path(), p_width, info.divisor)); |
| 146 | } |
| 147 | if (h != p_height) { |
| 148 | WARN_PRINT(vformat("%s: DDS height '%d' is not divisible by %d. This is not allowed as per the DDS specification, attempting to load anyway.", p_file->get_path(), p_height, info.divisor)); |
| 149 | } |
| 150 | |
| 151 | uint32_t size = MAX(1u, (w + 3) / 4) * MAX(1u, (h + 3) / 4) * info.block_size; |
| 152 | |
| 153 | if (p_flags & DDSD_LINEARSIZE) { |
| 154 | ERR_FAIL_COND_V_MSG(size != p_pitch, Ref<Resource>(), "DDS header flags specify that a linear size of the top-level image is present, but the specified size does not match the expected value."); |
| 155 | } else { |
| 156 | ERR_FAIL_COND_V_MSG(p_pitch != 0, Ref<Resource>(), "DDS header flags specify that no linear size will given for the top-level image, but a non-zero linear size value is present in the header."); |
| 157 | } |
| 158 | |
| 159 | for (uint32_t i = 1; i < p_mipmaps; i++) { |
| 160 | w = MAX(1u, w >> 1); |
| 161 | h = MAX(1u, h >> 1); |
| 162 | |
| 163 | uint32_t bsize = MAX(1u, (w + 3) / 4) * MAX(1u, (h + 3) / 4) * info.block_size; |
| 164 | size += bsize; |
| 165 | } |
| 166 | |
| 167 | r_src_data.resize(size); |
| 168 | uint8_t *wb = r_src_data.ptrw(); |
| 169 | p_file->get_buffer(wb, size); |
| 170 | |
| 171 | } else { |
| 172 | // Generic uncompressed. |
| 173 | uint32_t size = p_width * p_height * info.block_size; |
| 174 | |
| 175 | for (uint32_t i = 1; i < p_mipmaps; i++) { |
| 176 | w = MAX(1u, w >> 1); |
| 177 | h = MAX(1u, h >> 1); |
| 178 | size += w * h * info.block_size; |
| 179 | } |
| 180 | |
| 181 | // Calculate the space these formats will take up after decoding. |
| 182 | switch (p_dds_format) { |
| 183 | case DDS_BGR5A1: |
| 184 | case DDS_B2GR3A8: |
| 185 | case DDS_LUMINANCE_ALPHA_4: |
| 186 | size = size * 2; |
| 187 | break; |
| 188 | |
| 189 | case DDS_B2GR3: |
| 190 | size = size * 3; |
| 191 | break; |
no test coverage detected