summaryrefslogtreecommitdiff
path: root/src/video_core/textures/decoders.cpp
diff options
context:
space:
mode:
authorGravatar bunnei2018-03-25 16:28:24 -0400
committerGravatar GitHub2018-03-25 16:28:24 -0400
commite9315ace9f7f541d251a995ff2d4d3513ddc16c4 (patch)
treeba32de7358ed98e1230c1f522a5c7ba35d7ab19e /src/video_core/textures/decoders.cpp
parentMerge pull request #281 from mailwl/sockets-services (diff)
parentGPU: Make the debug_context variable a member of the frontend instead of a gl... (diff)
downloadyuzu-e9315ace9f7f541d251a995ff2d4d3513ddc16c4.tar.gz
yuzu-e9315ace9f7f541d251a995ff2d4d3513ddc16c4.tar.xz
yuzu-e9315ace9f7f541d251a995ff2d4d3513ddc16c4.zip
Merge pull request #273 from Subv/textures
GPU: Added code to unswizzle textures and ported the surface viewer from citra
Diffstat (limited to 'src/video_core/textures/decoders.cpp')
-rw-r--r--src/video_core/textures/decoders.cpp105
1 files changed, 105 insertions, 0 deletions
diff --git a/src/video_core/textures/decoders.cpp b/src/video_core/textures/decoders.cpp
new file mode 100644
index 000000000..2e87281eb
--- /dev/null
+++ b/src/video_core/textures/decoders.cpp
@@ -0,0 +1,105 @@
1// Copyright 2018 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <cstring>
6#include "common/assert.h"
7#include "video_core/textures/decoders.h"
8#include "video_core/textures/texture.h"
9
10namespace Tegra {
11namespace Texture {
12
13/**
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;
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 }
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 case TextureFormat::A8R8G8B8:
52 return 4;
53 default:
54 UNIMPLEMENTED_MSG("Format not implemented");
55 break;
56 }
57}
58
59std::vector<u8> UnswizzleTexture(VAddr address, TextureFormat format, u32 width, u32 height) {
60 u8* data = Memory::GetPointer(address);
61 u32 bytes_per_pixel = BytesPerPixel(format);
62
63 static constexpr u32 DefaultBlockHeight = 16;
64
65 std::vector<u8> unswizzled_data(width * height * bytes_per_pixel);
66
67 switch (format) {
68 case TextureFormat::DXT1:
69 // In the DXT1 format, each 4x4 tile is swizzled instead of just individual pixel values.
70 CopySwizzledData(width / 4, height / 4, bytes_per_pixel, bytes_per_pixel, data,
71 unswizzled_data.data(), true, DefaultBlockHeight);
72 break;
73 case TextureFormat::A8R8G8B8:
74 CopySwizzledData(width, height, bytes_per_pixel, bytes_per_pixel, data,
75 unswizzled_data.data(), true, DefaultBlockHeight);
76 break;
77 default:
78 UNIMPLEMENTED_MSG("Format not implemented");
79 break;
80 }
81
82 return unswizzled_data;
83}
84
85std::vector<u8> DecodeTexture(const std::vector<u8>& texture_data, TextureFormat format, u32 width,
86 u32 height) {
87 std::vector<u8> rgba_data;
88
89 // TODO(Subv): Implement.
90 switch (format) {
91 case TextureFormat::DXT1:
92 case TextureFormat::A8R8G8B8:
93 // TODO(Subv): For the time being just forward the same data without any decoding.
94 rgba_data = texture_data;
95 break;
96 default:
97 UNIMPLEMENTED_MSG("Format not implemented");
98 break;
99 }
100
101 return rgba_data;
102}
103
104} // namespace Texture
105} // namespace Tegra