basisu_gpu_texture.h 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. // basisu_gpu_texture.h
  2. // Copyright (C) 2019-2021 Binomial LLC. All Rights Reserved.
  3. //
  4. // Licensed under the Apache License, Version 2.0 (the "License");
  5. // you may not use this file except in compliance with the License.
  6. // You may obtain a copy of the License at
  7. //
  8. // http://www.apache.org/licenses/LICENSE-2.0
  9. //
  10. // Unless required by applicable law or agreed to in writing, software
  11. // distributed under the License is distributed on an "AS IS" BASIS,
  12. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. // See the License for the specific language governing permissions and
  14. // limitations under the License.
  15. #pragma once
  16. #include "../transcoder/basisu.h"
  17. #include "basisu_etc.h"
  18. namespace basisu
  19. {
  20. // GPU texture "image"
  21. class gpu_image
  22. {
  23. public:
  24. enum { cMaxBlockSize = 12 };
  25. gpu_image()
  26. {
  27. clear();
  28. }
  29. gpu_image(texture_format fmt, uint32_t width, uint32_t height)
  30. {
  31. init(fmt, width, height);
  32. }
  33. void clear()
  34. {
  35. m_fmt = texture_format::cInvalidTextureFormat;
  36. m_width = 0;
  37. m_height = 0;
  38. m_block_width = 0;
  39. m_block_height = 0;
  40. m_blocks_x = 0;
  41. m_blocks_y = 0;
  42. m_qwords_per_block = 0;
  43. m_blocks.clear();
  44. }
  45. inline texture_format get_format() const { return m_fmt; }
  46. // Width/height in pixels
  47. inline uint32_t get_pixel_width() const { return m_width; }
  48. inline uint32_t get_pixel_height() const { return m_height; }
  49. // Width/height in blocks, row pitch is assumed to be m_blocks_x.
  50. inline uint32_t get_blocks_x() const { return m_blocks_x; }
  51. inline uint32_t get_blocks_y() const { return m_blocks_y; }
  52. // Size of each block in pixels
  53. inline uint32_t get_block_width() const { return m_block_width; }
  54. inline uint32_t get_block_height() const { return m_block_height; }
  55. inline uint32_t get_qwords_per_block() const { return m_qwords_per_block; }
  56. inline uint32_t get_total_blocks() const { return m_blocks_x * m_blocks_y; }
  57. inline uint32_t get_bytes_per_block() const { return get_qwords_per_block() * sizeof(uint64_t); }
  58. inline uint32_t get_row_pitch_in_bytes() const { return get_bytes_per_block() * get_blocks_x(); }
  59. inline const uint64_vec &get_blocks() const { return m_blocks; }
  60. inline const uint64_t *get_ptr() const { return &m_blocks[0]; }
  61. inline uint64_t *get_ptr() { return &m_blocks[0]; }
  62. inline uint32_t get_size_in_bytes() const { return get_total_blocks() * get_qwords_per_block() * sizeof(uint64_t); }
  63. inline const void *get_block_ptr(uint32_t block_x, uint32_t block_y, uint32_t element_index = 0) const
  64. {
  65. assert(block_x < m_blocks_x && block_y < m_blocks_y);
  66. return &m_blocks[(block_x + block_y * m_blocks_x) * m_qwords_per_block + element_index];
  67. }
  68. inline void *get_block_ptr(uint32_t block_x, uint32_t block_y, uint32_t element_index = 0)
  69. {
  70. assert(block_x < m_blocks_x && block_y < m_blocks_y && element_index < m_qwords_per_block);
  71. return &m_blocks[(block_x + block_y * m_blocks_x) * m_qwords_per_block + element_index];
  72. }
  73. void init(texture_format fmt, uint32_t width, uint32_t height)
  74. {
  75. m_fmt = fmt;
  76. m_width = width;
  77. m_height = height;
  78. m_block_width = basisu::get_block_width(m_fmt);
  79. m_block_height = basisu::get_block_height(m_fmt);
  80. m_blocks_x = (m_width + m_block_width - 1) / m_block_width;
  81. m_blocks_y = (m_height + m_block_height - 1) / m_block_height;
  82. m_qwords_per_block = basisu::get_qwords_per_block(m_fmt);
  83. m_blocks.resize(0);
  84. m_blocks.resize(m_blocks_x * m_blocks_y * m_qwords_per_block);
  85. }
  86. bool unpack(image& img) const;
  87. void override_dimensions(uint32_t w, uint32_t h)
  88. {
  89. m_width = w;
  90. m_height = h;
  91. }
  92. private:
  93. texture_format m_fmt;
  94. uint32_t m_width, m_height, m_blocks_x, m_blocks_y, m_block_width, m_block_height, m_qwords_per_block;
  95. uint64_vec m_blocks;
  96. };
  97. typedef basisu::vector<gpu_image> gpu_image_vec;
  98. // KTX file writing
  99. bool create_ktx_texture_file(uint8_vec &ktx_data, const basisu::vector<gpu_image_vec>& gpu_images, bool cubemap_flag);
  100. bool write_compressed_texture_file(const char *pFilename, const basisu::vector<gpu_image_vec>& g, bool cubemap_flag);
  101. inline bool write_compressed_texture_file(const char *pFilename, const gpu_image_vec &g)
  102. {
  103. basisu::vector<gpu_image_vec> a;
  104. a.push_back(g);
  105. return write_compressed_texture_file(pFilename, a, false);
  106. }
  107. bool write_compressed_texture_file(const char *pFilename, const gpu_image &g);
  108. bool write_3dfx_out_file(const char* pFilename, const gpu_image& gi);
  109. // GPU texture block unpacking
  110. void unpack_etc2_eac(const void *pBlock_bits, color_rgba *pPixels);
  111. bool unpack_bc1(const void *pBlock_bits, color_rgba *pPixels, bool set_alpha);
  112. void unpack_bc4(const void *pBlock_bits, uint8_t *pPixels, uint32_t stride);
  113. bool unpack_bc3(const void *pBlock_bits, color_rgba *pPixels);
  114. void unpack_bc5(const void *pBlock_bits, color_rgba *pPixels);
  115. bool unpack_bc7_mode6(const void *pBlock_bits, color_rgba *pPixels);
  116. bool unpack_bc7(const void* pBlock_bits, color_rgba* pPixels);
  117. void unpack_atc(const void* pBlock_bits, color_rgba* pPixels);
  118. bool unpack_fxt1(const void* p, color_rgba* pPixels);
  119. bool unpack_pvrtc2(const void* p, color_rgba* pPixels);
  120. void unpack_etc2_eac_r(const void *p, color_rgba* pPixels, uint32_t c);
  121. void unpack_etc2_eac_rg(const void* p, color_rgba* pPixels);
  122. // unpack_block() is primarily intended to unpack texture data created by the transcoder.
  123. // For some texture formats (like ETC2 RGB, PVRTC2, FXT1) it's not a complete implementation.
  124. bool unpack_block(texture_format fmt, const void *pBlock, color_rgba *pPixels);
  125. } // namespace basisu