decoders.cpp 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  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::DXN2:
  49. case TextureFormat::BC7U:
  50. case TextureFormat::BC6H_UF16:
  51. case TextureFormat::BC6H_SF16:
  52. // In this case a 'pixel' actually refers to a 4x4 tile.
  53. return 16;
  54. case TextureFormat::R32_G32_B32:
  55. return 12;
  56. case TextureFormat::ASTC_2D_4X4:
  57. case TextureFormat::A8R8G8B8:
  58. case TextureFormat::A2B10G10R10:
  59. case TextureFormat::BF10GF11RF11:
  60. case TextureFormat::R32:
  61. case TextureFormat::R16_G16:
  62. return 4;
  63. case TextureFormat::A1B5G5R5:
  64. case TextureFormat::B5G6R5:
  65. case TextureFormat::G8R8:
  66. case TextureFormat::R16:
  67. return 2;
  68. case TextureFormat::R8:
  69. return 1;
  70. case TextureFormat::R16_G16_B16_A16:
  71. return 8;
  72. case TextureFormat::R32_G32_B32_A32:
  73. return 16;
  74. case TextureFormat::R32_G32:
  75. return 8;
  76. default:
  77. UNIMPLEMENTED_MSG("Format not implemented");
  78. break;
  79. }
  80. }
  81. std::vector<u8> UnswizzleTexture(VAddr address, u32 tile_size, u32 bytes_per_pixel, u32 width,
  82. u32 height, u32 block_height) {
  83. std::vector<u8> unswizzled_data(width * height * bytes_per_pixel);
  84. CopySwizzledData(width / tile_size, height / tile_size, bytes_per_pixel, bytes_per_pixel,
  85. Memory::GetPointer(address), unswizzled_data.data(), true, block_height);
  86. return unswizzled_data;
  87. }
  88. std::vector<u8> DecodeTexture(const std::vector<u8>& texture_data, TextureFormat format, u32 width,
  89. u32 height) {
  90. std::vector<u8> rgba_data;
  91. // TODO(Subv): Implement.
  92. switch (format) {
  93. case TextureFormat::DXT1:
  94. case TextureFormat::DXT23:
  95. case TextureFormat::DXT45:
  96. case TextureFormat::DXN1:
  97. case TextureFormat::DXN2:
  98. case TextureFormat::BC7U:
  99. case TextureFormat::BC6H_UF16:
  100. case TextureFormat::BC6H_SF16:
  101. case TextureFormat::ASTC_2D_4X4:
  102. case TextureFormat::A8R8G8B8:
  103. case TextureFormat::A2B10G10R10:
  104. case TextureFormat::A1B5G5R5:
  105. case TextureFormat::B5G6R5:
  106. case TextureFormat::R8:
  107. case TextureFormat::G8R8:
  108. case TextureFormat::BF10GF11RF11:
  109. case TextureFormat::R32_G32_B32_A32:
  110. case TextureFormat::R32_G32:
  111. case TextureFormat::R32:
  112. case TextureFormat::R16:
  113. case TextureFormat::R16_G16:
  114. case TextureFormat::R32_G32_B32:
  115. // TODO(Subv): For the time being just forward the same data without any decoding.
  116. rgba_data = texture_data;
  117. break;
  118. default:
  119. UNIMPLEMENTED_MSG("Format not implemented");
  120. break;
  121. }
  122. return rgba_data;
  123. }
  124. } // namespace Tegra::Texture