decoders.cpp 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  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 "video_core/textures/decoders.h"
  7. #include "video_core/textures/texture.h"
  8. namespace Tegra {
  9. namespace Texture {
  10. /**
  11. * Calculates the offset of an (x, y) position within a swizzled texture.
  12. * Taken from the Tegra X1 TRM.
  13. */
  14. static u32 GetSwizzleOffset(u32 x, u32 y, u32 image_width, u32 bytes_per_pixel, u32 block_height) {
  15. u32 image_width_in_gobs = image_width * bytes_per_pixel / 64;
  16. u32 GOB_address = 0 + (y / (8 * block_height)) * 512 * block_height * image_width_in_gobs +
  17. (x * bytes_per_pixel / 64) * 512 * block_height +
  18. (y % (8 * block_height) / 8) * 512;
  19. x *= bytes_per_pixel;
  20. u32 address = GOB_address + ((x % 64) / 32) * 256 + ((y % 8) / 2) * 64 + ((x % 32) / 16) * 32 +
  21. (y % 2) * 16 + (x % 16);
  22. return address;
  23. }
  24. static void CopySwizzledData(u32 width, u32 height, u32 bytes_per_pixel, u32 out_bytes_per_pixel,
  25. u8* swizzled_data, u8* unswizzled_data, bool unswizzle,
  26. u32 block_height) {
  27. u8* data_ptrs[2];
  28. for (unsigned y = 0; y < height; ++y) {
  29. for (unsigned x = 0; x < width; ++x) {
  30. u32 swizzle_offset = GetSwizzleOffset(x, y, width, bytes_per_pixel, block_height);
  31. u32 pixel_index = (x + y * width) * out_bytes_per_pixel;
  32. data_ptrs[unswizzle] = swizzled_data + swizzle_offset;
  33. data_ptrs[!unswizzle] = &unswizzled_data[pixel_index];
  34. std::memcpy(data_ptrs[0], data_ptrs[1], bytes_per_pixel);
  35. }
  36. }
  37. }
  38. u32 BytesPerPixel(TextureFormat format) {
  39. switch (format) {
  40. case TextureFormat::DXT1:
  41. // In this case a 'pixel' actually refers to a 4x4 tile.
  42. return 8;
  43. case TextureFormat::A8R8G8B8:
  44. return 4;
  45. default:
  46. UNIMPLEMENTED_MSG("Format not implemented");
  47. break;
  48. }
  49. }
  50. std::vector<u8> UnswizzleTexture(VAddr address, TextureFormat format, u32 width, u32 height,
  51. u32 block_height) {
  52. u8* data = Memory::GetPointer(address);
  53. u32 bytes_per_pixel = BytesPerPixel(format);
  54. std::vector<u8> unswizzled_data(width * height * bytes_per_pixel);
  55. switch (format) {
  56. case TextureFormat::DXT1:
  57. // In the DXT1 format, each 4x4 tile is swizzled instead of just individual pixel values.
  58. CopySwizzledData(width / 4, height / 4, bytes_per_pixel, bytes_per_pixel, data,
  59. unswizzled_data.data(), true, block_height);
  60. break;
  61. case TextureFormat::A8R8G8B8:
  62. CopySwizzledData(width, height, bytes_per_pixel, bytes_per_pixel, data,
  63. unswizzled_data.data(), true, block_height);
  64. break;
  65. default:
  66. UNIMPLEMENTED_MSG("Format not implemented");
  67. break;
  68. }
  69. return unswizzled_data;
  70. }
  71. std::vector<u8> DecodeTexture(const std::vector<u8>& texture_data, TextureFormat format, u32 width,
  72. u32 height) {
  73. std::vector<u8> rgba_data;
  74. // TODO(Subv): Implement.
  75. switch (format) {
  76. case TextureFormat::DXT1:
  77. case TextureFormat::A8R8G8B8:
  78. // TODO(Subv): For the time being just forward the same data without any decoding.
  79. rgba_data = texture_data;
  80. break;
  81. default:
  82. UNIMPLEMENTED_MSG("Format not implemented");
  83. break;
  84. }
  85. return rgba_data;
  86. }
  87. } // namespace Texture
  88. } // namespace Tegra