/** ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** * Copyright 2018 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ #ifndef XENIA_GPU_TEXTURE_UTIL_H_ #define XENIA_GPU_TEXTURE_UTIL_H_ #include #include "xenia/base/math.h" #include "xenia/gpu/texture_info.h" namespace xe { namespace gpu { namespace texture_util { // This namespace replaces texture_extent and most of texture_info for // simplicity. // Calculates width, height and depth of the image backing the guest mipmap (or // the base level if mip is 0). void GetGuestMipBlocks(Dimension dimension, uint32_t width, uint32_t height, uint32_t depth, TextureFormat format, uint32_t mip, uint32_t& width_blocks_out, uint32_t& height_blocks_out, uint32_t& depth_blocks_out); // Calculates the number of bytes required to store a single mip level - width, // height and depth must be obtained via GetGuestMipExtent. uint32_t GetGuestMipStorageSize(uint32_t width_blocks, uint32_t height_blocks, uint32_t depth_blocks, bool is_tiled, TextureFormat format, uint32_t* row_pitch_out); // Gets the number of the mipmap level where the packed mips are stored. inline uint32_t GetPackedMipLevel(uint32_t width, uint32_t height) { uint32_t log2_size = xe::log2_ceil(std::min(width, height)); return log2_size > 4 ? log2_size - 4 : 0; } // Gets the offset of the mipmap within the tail in blocks, or zeros (and // returns false) if the mip level is not packed. Width, height and depth are in // texels. For non-3D textures, set depth to 1. bool GetPackedMipOffset(uint32_t width, uint32_t height, uint32_t depth, TextureFormat format, uint32_t mip, uint32_t& x_blocks, uint32_t& y_blocks, uint32_t& z_blocks); // Calculates the index of the smallest mip (1x1x1 for unpacked or min(w,h)<=16 // packed mips) for a texture. For non-3D textures, set the depth to 1. inline uint32_t GetSmallestMipLevel(uint32_t width, uint32_t height, uint32_t depth, bool packed_mips) { uint32_t size = std::max(width, height); size = std::max(size, depth); uint32_t smallest_mip = xe::log2_ceil(size); if (packed_mips) { smallest_mip = std::min(smallest_mip, GetPackedMipLevel(width, height)); } return smallest_mip; } } // namespace texture_util } // namespace gpu } // namespace xe #endif // XENIA_GPU_TEXTURE_UTIL_H_