decoders.cpp 5.7 KB

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