summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Subv2018-03-22 15:17:10 -0500
committerGravatar Subv2018-03-24 11:30:56 -0500
commit1b8d798835c2d39c2867f53d8dcacdc7d0ba0d15 (patch)
treedc74d1d4ef4ce25613f2b399ad286911d871457e /src
parentGPU: Preliminary work for texture decoding. (diff)
downloadyuzu-1b8d798835c2d39c2867f53d8dcacdc7d0ba0d15.tar.gz
yuzu-1b8d798835c2d39c2867f53d8dcacdc7d0ba0d15.tar.xz
yuzu-1b8d798835c2d39c2867f53d8dcacdc7d0ba0d15.zip
GPU: Added a method to unswizzle a texture without decoding it.
Allow unswizzling of DXT1 textures.
Diffstat (limited to 'src')
-rw-r--r--src/video_core/engines/maxwell_3d.cpp2
-rw-r--r--src/video_core/textures/decoders.cpp84
-rw-r--r--src/video_core/textures/decoders.h10
-rw-r--r--src/video_core/textures/texture.h4
4 files changed, 95 insertions, 5 deletions
diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp
index ca1b150a7..d1edfe09a 100644
--- a/src/video_core/engines/maxwell_3d.cpp
+++ b/src/video_core/engines/maxwell_3d.cpp
@@ -196,7 +196,7 @@ void Maxwell3D::DrawArrays() {
196 196
197 auto format = tic_entry.format.Value(); 197 auto format = tic_entry.format.Value();
198 198
199 auto texture = Texture::DecodeTexture( 199 auto texture = Texture::UnswizzleTexture(
200 memory_manager.PhysicalToVirtualAddress(tic_entry.Address()), 200 memory_manager.PhysicalToVirtualAddress(tic_entry.Address()),
201 tic_entry.format.Value(), tic_entry.Width(), tic_entry.Height()); 201 tic_entry.format.Value(), tic_entry.Width(), tic_entry.Height());
202 202
diff --git a/src/video_core/textures/decoders.cpp b/src/video_core/textures/decoders.cpp
index 705e2e066..300267209 100644
--- a/src/video_core/textures/decoders.cpp
+++ b/src/video_core/textures/decoders.cpp
@@ -2,13 +2,93 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <cstring>
6#include "common/assert.h"
5#include "video_core/textures/decoders.h" 7#include "video_core/textures/decoders.h"
8#include "video_core/textures/texture.h"
6 9
7namespace Tegra { 10namespace Tegra {
8namespace Texture { 11namespace Texture {
9 12
10std::vector<u8> DecodeTexture(VAddr address, TextureFormat format, u32 width, u32 height) { 13/**
11 return {}; 14 * Calculates the offset of an (x, y) position within a swizzled texture.
15 * Taken from the Tegra X1 TRM.
16 */
17static u32 GetSwizzleOffset(u32 x, u32 y, u32 image_width, u32 bytes_per_pixel, u32 block_height) {
18 u32 image_width_in_gobs = image_width * bytes_per_pixel / 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
26 return address;
12} 27}
28
29static void CopySwizzledData(u32 width, u32 height, u32 bytes_per_pixel, u32 out_bytes_per_pixel,
30 u8* swizzled_data, u8* unswizzled_data, bool unswizzle,
31 u32 block_height) {
32 u8* data_ptrs[2];
33 for (unsigned y = 0; y < height; ++y) {
34 for (unsigned x = 0; x < width; ++x) {
35 u32 swizzle_offset = GetSwizzleOffset(x, y, width, bytes_per_pixel, block_height);
36 u32 pixel_index = (x + y * width) * out_bytes_per_pixel;
37
38 data_ptrs[unswizzle] = swizzled_data + swizzle_offset;
39 data_ptrs[!unswizzle] = &unswizzled_data[pixel_index];
40
41 std::memcpy(data_ptrs[0], data_ptrs[1], bytes_per_pixel);
42 }
43 }
13} 44}
45
46u32 BytesPerPixel(TextureFormat format) {
47 switch (format) {
48 case TextureFormat::DXT1:
49 // In this case a 'pixel' actually refers to a 4x4 tile.
50 return 8;
51 default:
52 UNIMPLEMENTED_MSG("Format not implemented");
53 break;
54 }
55}
56
57std::vector<u8> UnswizzleTexture(VAddr address, TextureFormat format, u32 width, u32 height) {
58 u8* data = Memory::GetPointer(address);
59 u32 bytes_per_pixel = BytesPerPixel(format);
60
61 static constexpr u32 DefaultBlockHeight = 16;
62
63 std::vector<u8> unswizzled_data(width * height * bytes_per_pixel);
64
65 switch (format) {
66 case TextureFormat::DXT1:
67 // In the DXT1 format, each 4x4 tile is swizzled instead of just individual pixel values.
68 CopySwizzledData(width / 4, height / 4, bytes_per_pixel, bytes_per_pixel, data,
69 unswizzled_data.data(), true, DefaultBlockHeight);
70 break;
71 default:
72 UNIMPLEMENTED_MSG("Format not implemented");
73 break;
74 }
75
76 return unswizzled_data;
77}
78
79std::vector<u8> DecodeTexture(const std::vector<u8>& texture_data, TextureFormat format, u32 width,
80 u32 height) {
81 std::vector<u8> rgba_data;
82
83 // TODO(Subv): Implement.
84 switch (format) {
85 default:
86 UNIMPLEMENTED_MSG("Format not implemented");
87 break;
88 }
89
90 return rgba_data;
91}
92
93} // namespace Texture
14} // namespace Tegra 94} // namespace Tegra
diff --git a/src/video_core/textures/decoders.h b/src/video_core/textures/decoders.h
index e0d55600e..0c21694ff 100644
--- a/src/video_core/textures/decoders.h
+++ b/src/video_core/textures/decoders.h
@@ -12,9 +12,15 @@ namespace Tegra {
12namespace Texture { 12namespace Texture {
13 13
14/** 14/**
15 * Decodes a swizzled texture into a RGBA8888 texture. 15 * Unswizzles a swizzled texture without changing its format.
16 */ 16 */
17std::vector<u8> DecodeTexture(VAddr address, TextureFormat format, u32 width, u32 height); 17std::vector<u8> UnswizzleTexture(VAddr address, TextureFormat format, u32 width, u32 height);
18
19/**
20 * Decodes an unswizzled texture into a A8R8G8B8 texture.
21 */
22std::vector<u8> DecodeTexture(const std::vector<u8>& texture_data, TextureFormat format, u32 width,
23 u32 height);
18 24
19} // namespace Texture 25} // namespace Texture
20} // namespace Tegra 26} // namespace Tegra
diff --git a/src/video_core/textures/texture.h b/src/video_core/textures/texture.h
index 3306d2ab2..d969bcdd9 100644
--- a/src/video_core/textures/texture.h
+++ b/src/video_core/textures/texture.h
@@ -13,6 +13,7 @@ namespace Tegra {
13namespace Texture { 13namespace Texture {
14 14
15enum class TextureFormat : u32 { 15enum class TextureFormat : u32 {
16 A8R8G8B8 = 8,
16 DXT1 = 0x24, 17 DXT1 = 0x24,
17}; 18};
18 19
@@ -53,5 +54,8 @@ struct TICEntry {
53}; 54};
54static_assert(sizeof(TICEntry) == 0x20, "TICEntry has wrong size"); 55static_assert(sizeof(TICEntry) == 0x20, "TICEntry has wrong size");
55 56
57/// Returns the number of bytes per pixel of the input texture format.
58u32 BytesPerPixel(TextureFormat format);
59
56} // namespace Texture 60} // namespace Texture
57} // namespace Tegra 61} // namespace Tegra