decoders.cpp 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. // Copyright 2018 yuzu Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #include <cmath>
  5. #include <cstring>
  6. #include "common/assert.h"
  7. #include "core/memory.h"
  8. #include "video_core/gpu.h"
  9. #include "video_core/textures/decoders.h"
  10. #include "video_core/textures/texture.h"
  11. namespace Tegra::Texture {
  12. /**
  13. * Calculates the offset of an (x, y) position within a swizzled texture.
  14. * Taken from the Tegra X1 TRM.
  15. */
  16. static u32 GetSwizzleOffset(u32 x, u32 y, u32 image_width, u32 bytes_per_pixel, u32 block_height) {
  17. // Round up to the next gob
  18. const u32 image_width_in_gobs{(image_width * bytes_per_pixel + 63) / 64};
  19. u32 GOB_address = 0 + (y / (8 * block_height)) * 512 * block_height * image_width_in_gobs +
  20. (x * bytes_per_pixel / 64) * 512 * block_height +
  21. (y % (8 * block_height) / 8) * 512;
  22. x *= bytes_per_pixel;
  23. u32 address = GOB_address + ((x % 64) / 32) * 256 + ((y % 8) / 2) * 64 + ((x % 32) / 16) * 32 +
  24. (y % 2) * 16 + (x % 16);
  25. return address;
  26. }
  27. void CopySwizzledData(u32 width, u32 height, u32 bytes_per_pixel, u32 out_bytes_per_pixel,
  28. u8* swizzled_data, u8* unswizzled_data, bool unswizzle, u32 block_height) {
  29. u8* data_ptrs[2];
  30. for (unsigned y = 0; y < height; ++y) {
  31. for (unsigned x = 0; x < width; ++x) {
  32. u32 swizzle_offset = GetSwizzleOffset(x, y, width, bytes_per_pixel, block_height);
  33. u32 pixel_index = (x + y * width) * out_bytes_per_pixel;
  34. data_ptrs[unswizzle] = swizzled_data + swizzle_offset;
  35. data_ptrs[!unswizzle] = &unswizzled_data[pixel_index];
  36. std::memcpy(data_ptrs[0], data_ptrs[1], bytes_per_pixel);
  37. }
  38. }
  39. }
  40. u32 BytesPerPixel(TextureFormat format) {
  41. switch (format) {
  42. case TextureFormat::DXT1:
  43. case TextureFormat::DXN1:
  44. // In this case a 'pixel' actually refers to a 4x4 tile.
  45. return 8;
  46. case TextureFormat::DXT23:
  47. case TextureFormat::DXT45:
  48. case TextureFormat::BC7U:
  49. // In this case a 'pixel' actually refers to a 4x4 tile.
  50. return 16;
  51. case TextureFormat::ASTC_2D_4X4:
  52. case TextureFormat::A8R8G8B8:
  53. case TextureFormat::A2B10G10R10:
  54. case TextureFormat::BF10GF11RF11:
  55. case TextureFormat::R32:
  56. case TextureFormat::R16_G16:
  57. return 4;
  58. case TextureFormat::A1B5G5R5:
  59. case TextureFormat::B5G6R5:
  60. case TextureFormat::G8R8:
  61. case TextureFormat::R16:
  62. return 2;
  63. case TextureFormat::R8:
  64. return 1;
  65. case TextureFormat::R16_G16_B16_A16:
  66. return 8;
  67. case TextureFormat::R32_G32_B32_A32:
  68. return 16;
  69. case TextureFormat::R32_G32:
  70. return 8;
  71. default:
  72. UNIMPLEMENTED_MSG("Format not implemented");
  73. break;
  74. }
  75. }
  76. static u32 DepthBytesPerPixel(DepthFormat format) {
  77. switch (format) {
  78. case DepthFormat::Z16_UNORM:
  79. return 2;
  80. case DepthFormat::S8_Z24_UNORM:
  81. case DepthFormat::Z24_S8_UNORM:
  82. case DepthFormat::Z32_FLOAT:
  83. return 4;
  84. case DepthFormat::Z32_S8_X24_FLOAT:
  85. return 8;
  86. default:
  87. UNIMPLEMENTED_MSG("Format not implemented");
  88. break;
  89. }
  90. }
  91. std::vector<u8> UnswizzleTexture(VAddr address, TextureFormat format, u32 width, u32 height,
  92. u32 block_height) {
  93. u8* data = Memory::GetPointer(address);
  94. u32 bytes_per_pixel = BytesPerPixel(format);
  95. std::vector<u8> unswizzled_data(width * height * bytes_per_pixel);
  96. switch (format) {
  97. case TextureFormat::DXT1:
  98. case TextureFormat::DXT23:
  99. case TextureFormat::DXT45:
  100. case TextureFormat::DXN1:
  101. case TextureFormat::BC7U:
  102. // In the DXT and DXN formats, each 4x4 tile is swizzled instead of just individual pixel
  103. // values.
  104. CopySwizzledData(width / 4, height / 4, bytes_per_pixel, bytes_per_pixel, data,
  105. unswizzled_data.data(), true, block_height);
  106. break;
  107. case TextureFormat::A8R8G8B8:
  108. case TextureFormat::A2B10G10R10:
  109. case TextureFormat::A1B5G5R5:
  110. case TextureFormat::B5G6R5:
  111. case TextureFormat::R8:
  112. case TextureFormat::G8R8:
  113. case TextureFormat::R16_G16_B16_A16:
  114. case TextureFormat::R32_G32_B32_A32:
  115. case TextureFormat::R32_G32:
  116. case TextureFormat::R32:
  117. case TextureFormat::R16:
  118. case TextureFormat::R16_G16:
  119. case TextureFormat::BF10GF11RF11:
  120. case TextureFormat::ASTC_2D_4X4:
  121. CopySwizzledData(width, height, bytes_per_pixel, bytes_per_pixel, data,
  122. unswizzled_data.data(), true, block_height);
  123. break;
  124. default:
  125. UNIMPLEMENTED_MSG("Format not implemented");
  126. break;
  127. }
  128. return unswizzled_data;
  129. }
  130. std::vector<u8> UnswizzleDepthTexture(VAddr address, DepthFormat format, u32 width, u32 height,
  131. u32 block_height) {
  132. u8* data = Memory::GetPointer(address);
  133. u32 bytes_per_pixel = DepthBytesPerPixel(format);
  134. std::vector<u8> unswizzled_data(width * height * bytes_per_pixel);
  135. switch (format) {
  136. case DepthFormat::Z16_UNORM:
  137. case DepthFormat::S8_Z24_UNORM:
  138. case DepthFormat::Z24_S8_UNORM:
  139. case DepthFormat::Z32_FLOAT:
  140. case DepthFormat::Z32_S8_X24_FLOAT:
  141. CopySwizzledData(width, height, bytes_per_pixel, bytes_per_pixel, data,
  142. unswizzled_data.data(), true, block_height);
  143. break;
  144. default:
  145. UNIMPLEMENTED_MSG("Format not implemented");
  146. break;
  147. }
  148. return unswizzled_data;
  149. }
  150. std::vector<u8> DecodeTexture(const std::vector<u8>& texture_data, TextureFormat format, u32 width,
  151. u32 height) {
  152. std::vector<u8> rgba_data;
  153. // TODO(Subv): Implement.
  154. switch (format) {
  155. case TextureFormat::DXT1:
  156. case TextureFormat::DXT23:
  157. case TextureFormat::DXT45:
  158. case TextureFormat::DXN1:
  159. case TextureFormat::BC7U:
  160. case TextureFormat::ASTC_2D_4X4:
  161. case TextureFormat::A8R8G8B8:
  162. case TextureFormat::A2B10G10R10:
  163. case TextureFormat::A1B5G5R5:
  164. case TextureFormat::B5G6R5:
  165. case TextureFormat::R8:
  166. case TextureFormat::G8R8:
  167. case TextureFormat::BF10GF11RF11:
  168. case TextureFormat::R32_G32_B32_A32:
  169. case TextureFormat::R32_G32:
  170. case TextureFormat::R32:
  171. case TextureFormat::R16:
  172. case TextureFormat::R16_G16:
  173. // TODO(Subv): For the time being just forward the same data without any decoding.
  174. rgba_data = texture_data;
  175. break;
  176. default:
  177. UNIMPLEMENTED_MSG("Format not implemented");
  178. break;
  179. }
  180. return rgba_data;
  181. }
  182. } // namespace Tegra::Texture