summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar bunnei2018-04-18 14:46:10 -0400
committerGravatar GitHub2018-04-18 14:46:10 -0400
commitd3f9ea90e78dce585f23c71c969990439937b427 (patch)
tree618163c00bf621be9b7a44535493ceeaabd6257f /src
parentMerge pull request #346 from bunnei/misc-gpu-improvements (diff)
parentGPU: Pitch textures are now supported, don't assert when encountering them. (diff)
downloadyuzu-d3f9ea90e78dce585f23c71c969990439937b427.tar.gz
yuzu-d3f9ea90e78dce585f23c71c969990439937b427.tar.xz
yuzu-d3f9ea90e78dce585f23c71c969990439937b427.zip
Merge pull request #349 from Subv/texturing
GPU: Support non-tiled textures and configurable block height.
Diffstat (limited to '')
-rw-r--r--src/video_core/engines/maxwell_3d.cpp5
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp3
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer_cache.cpp93
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer_cache.h13
-rw-r--r--src/video_core/textures/decoders.cpp9
-rw-r--r--src/video_core/textures/decoders.h3
-rw-r--r--src/video_core/textures/texture.h24
7 files changed, 97 insertions, 53 deletions
diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp
index a2f162602..2a3ff234a 100644
--- a/src/video_core/engines/maxwell_3d.cpp
+++ b/src/video_core/engines/maxwell_3d.cpp
@@ -218,8 +218,9 @@ Texture::TICEntry Maxwell3D::GetTICEntry(u32 tic_index) const {
218 Texture::TICEntry tic_entry; 218 Texture::TICEntry tic_entry;
219 Memory::ReadBlock(tic_address_cpu, &tic_entry, sizeof(Texture::TICEntry)); 219 Memory::ReadBlock(tic_address_cpu, &tic_entry, sizeof(Texture::TICEntry));
220 220
221 ASSERT_MSG(tic_entry.header_version == Texture::TICHeaderVersion::BlockLinear, 221 ASSERT_MSG(tic_entry.header_version == Texture::TICHeaderVersion::BlockLinear ||
222 "TIC versions other than BlockLinear are unimplemented"); 222 tic_entry.header_version == Texture::TICHeaderVersion::Pitch,
223 "TIC versions other than BlockLinear or Pitch are unimplemented");
223 224
224 ASSERT_MSG((tic_entry.texture_type == Texture::TextureType::Texture2D) || 225 ASSERT_MSG((tic_entry.texture_type == Texture::TextureType::Texture2D) ||
225 (tic_entry.texture_type == Texture::TextureType::Texture2DNoMipmap), 226 (tic_entry.texture_type == Texture::TextureType::Texture2DNoMipmap),
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index 7b6240e65..9522a35ea 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -523,7 +523,8 @@ bool RasterizerOpenGL::AccelerateDisplay(const Tegra::FramebufferConfig& framebu
523 src_params.width = std::min(framebuffer.width, pixel_stride); 523 src_params.width = std::min(framebuffer.width, pixel_stride);
524 src_params.height = framebuffer.height; 524 src_params.height = framebuffer.height;
525 src_params.stride = pixel_stride; 525 src_params.stride = pixel_stride;
526 src_params.is_tiled = false; 526 src_params.is_tiled = true;
527 src_params.block_height = Tegra::Texture::TICEntry::DefaultBlockHeight;
527 src_params.pixel_format = 528 src_params.pixel_format =
528 SurfaceParams::PixelFormatFromGPUPixelFormat(framebuffer.pixel_format); 529 SurfaceParams::PixelFormatFromGPUPixelFormat(framebuffer.pixel_format);
529 src_params.UpdateParams(); 530 src_params.UpdateParams();
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
index 213b20a21..a92773f11 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
@@ -102,39 +102,36 @@ static void MortonCopyTile(u32 stride, u8* tile_buffer, u8* gl_buffer) {
102} 102}
103 103
104template <bool morton_to_gl, PixelFormat format> 104template <bool morton_to_gl, PixelFormat format>
105void MortonCopy(u32 stride, u32 height, u8* gl_buffer, VAddr base, VAddr start, VAddr end) { 105void MortonCopy(u32 stride, u32 block_height, u32 height, u8* gl_buffer, VAddr base, VAddr start,
106 VAddr end) {
106 constexpr u32 bytes_per_pixel = SurfaceParams::GetFormatBpp(format) / 8; 107 constexpr u32 bytes_per_pixel = SurfaceParams::GetFormatBpp(format) / 8;
107 constexpr u32 gl_bytes_per_pixel = CachedSurface::GetGLBytesPerPixel(format); 108 constexpr u32 gl_bytes_per_pixel = CachedSurface::GetGLBytesPerPixel(format);
108 109
109 // TODO(bunnei): Assumes the default rendering GOB size of 16 (128 lines). We should check the 110 if (morton_to_gl) {
110 // configuration for this and perform more generic un/swizzle 111 auto data = Tegra::Texture::UnswizzleTexture(
111 LOG_WARNING(Render_OpenGL, "need to use correct swizzle/GOB parameters!"); 112 base, SurfaceParams::TextureFormatFromPixelFormat(format), stride, height,
112 VideoCore::MortonCopyPixels128(stride, height, bytes_per_pixel, gl_bytes_per_pixel, 113 block_height);
113 Memory::GetPointer(base), gl_buffer, morton_to_gl); 114 std::memcpy(gl_buffer, data.data(), data.size());
114} 115 } else {
115 116 // TODO(bunnei): Assumes the default rendering GOB size of 16 (128 lines). We should check
116template <> 117 // the configuration for this and perform more generic un/swizzle
117void MortonCopy<true, PixelFormat::DXT1>(u32 stride, u32 height, u8* gl_buffer, VAddr base, 118 LOG_WARNING(Render_OpenGL, "need to use correct swizzle/GOB parameters!");
118 VAddr start, VAddr end) { 119 VideoCore::MortonCopyPixels128(stride, height, bytes_per_pixel, gl_bytes_per_pixel,
119 constexpr u32 bytes_per_pixel = SurfaceParams::GetFormatBpp(PixelFormat::DXT1) / 8; 120 Memory::GetPointer(base), gl_buffer, morton_to_gl);
120 constexpr u32 gl_bytes_per_pixel = CachedSurface::GetGLBytesPerPixel(PixelFormat::DXT1); 121 }
121
122 // TODO(bunnei): Assumes the default rendering GOB size of 16 (128 lines). We should check the
123 // configuration for this and perform more generic un/swizzle
124 LOG_WARNING(Render_OpenGL, "need to use correct swizzle/GOB parameters!");
125 auto data =
126 Tegra::Texture::UnswizzleTexture(base, Tegra::Texture::TextureFormat::DXT1, stride, height);
127 std::memcpy(gl_buffer, data.data(), data.size());
128} 122}
129 123
130static constexpr std::array<void (*)(u32, u32, u8*, VAddr, VAddr, VAddr), 2> morton_to_gl_fns = { 124static constexpr std::array<void (*)(u32, u32, u32, u8*, VAddr, VAddr, VAddr), 2> morton_to_gl_fns =
131 MortonCopy<true, PixelFormat::RGBA8>, 125 {
132 MortonCopy<true, PixelFormat::DXT1>, 126 MortonCopy<true, PixelFormat::RGBA8>,
127 MortonCopy<true, PixelFormat::DXT1>,
133}; 128};
134 129
135static constexpr std::array<void (*)(u32, u32, u8*, VAddr, VAddr, VAddr), 2> gl_to_morton_fns = { 130static constexpr std::array<void (*)(u32, u32, u32, u8*, VAddr, VAddr, VAddr), 2> gl_to_morton_fns =
136 MortonCopy<false, PixelFormat::RGBA8>, 131 {
137 MortonCopy<false, PixelFormat::DXT1>, 132 MortonCopy<false, PixelFormat::RGBA8>,
133 // TODO(Subv): Swizzling the DXT1 format is not yet supported
134 nullptr,
138}; 135};
139 136
140// Allocate an uninitialized texture of appropriate size and format for the surface 137// Allocate an uninitialized texture of appropriate size and format for the surface
@@ -311,15 +308,16 @@ MathUtil::Rectangle<u32> SurfaceParams::GetScaledSubRect(const SurfaceParams& su
311 308
312bool SurfaceParams::ExactMatch(const SurfaceParams& other_surface) const { 309bool SurfaceParams::ExactMatch(const SurfaceParams& other_surface) const {
313 return std::tie(other_surface.addr, other_surface.width, other_surface.height, 310 return std::tie(other_surface.addr, other_surface.width, other_surface.height,
314 other_surface.stride, other_surface.pixel_format, other_surface.is_tiled) == 311 other_surface.stride, other_surface.block_height, other_surface.pixel_format,
315 std::tie(addr, width, height, stride, pixel_format, is_tiled) && 312 other_surface.is_tiled) ==
313 std::tie(addr, width, height, stride, block_height, pixel_format, is_tiled) &&
316 pixel_format != PixelFormat::Invalid; 314 pixel_format != PixelFormat::Invalid;
317} 315}
318 316
319bool SurfaceParams::CanSubRect(const SurfaceParams& sub_surface) const { 317bool SurfaceParams::CanSubRect(const SurfaceParams& sub_surface) const {
320 return sub_surface.addr >= addr && sub_surface.end <= end && 318 return sub_surface.addr >= addr && sub_surface.end <= end &&
321 sub_surface.pixel_format == pixel_format && pixel_format != PixelFormat::Invalid && 319 sub_surface.pixel_format == pixel_format && pixel_format != PixelFormat::Invalid &&
322 sub_surface.is_tiled == is_tiled && 320 sub_surface.is_tiled == is_tiled && sub_surface.block_height == block_height &&
323 (sub_surface.addr - addr) % BytesInPixels(is_tiled ? 64 : 1) == 0 && 321 (sub_surface.addr - addr) % BytesInPixels(is_tiled ? 64 : 1) == 0 &&
324 (sub_surface.stride == stride || sub_surface.height <= (is_tiled ? 8u : 1u)) && 322 (sub_surface.stride == stride || sub_surface.height <= (is_tiled ? 8u : 1u)) &&
325 GetSubRect(sub_surface).left + sub_surface.width <= stride; 323 GetSubRect(sub_surface).left + sub_surface.width <= stride;
@@ -328,7 +326,8 @@ bool SurfaceParams::CanSubRect(const SurfaceParams& sub_surface) const {
328bool SurfaceParams::CanExpand(const SurfaceParams& expanded_surface) const { 326bool SurfaceParams::CanExpand(const SurfaceParams& expanded_surface) const {
329 return pixel_format != PixelFormat::Invalid && pixel_format == expanded_surface.pixel_format && 327 return pixel_format != PixelFormat::Invalid && pixel_format == expanded_surface.pixel_format &&
330 addr <= expanded_surface.end && expanded_surface.addr <= end && 328 addr <= expanded_surface.end && expanded_surface.addr <= end &&
331 is_tiled == expanded_surface.is_tiled && stride == expanded_surface.stride && 329 is_tiled == expanded_surface.is_tiled && block_height == expanded_surface.block_height &&
330 stride == expanded_surface.stride &&
332 (std::max(expanded_surface.addr, addr) - std::min(expanded_surface.addr, addr)) % 331 (std::max(expanded_surface.addr, addr) - std::min(expanded_surface.addr, addr)) %
333 BytesInPixels(stride * (is_tiled ? 8 : 1)) == 332 BytesInPixels(stride * (is_tiled ? 8 : 1)) ==
334 0; 333 0;
@@ -339,6 +338,9 @@ bool SurfaceParams::CanTexCopy(const SurfaceParams& texcopy_params) const {
339 end < texcopy_params.end) { 338 end < texcopy_params.end) {
340 return false; 339 return false;
341 } 340 }
341 if (texcopy_params.block_height != block_height)
342 return false;
343
342 if (texcopy_params.width != texcopy_params.stride) { 344 if (texcopy_params.width != texcopy_params.stride) {
343 const u32 tile_stride = static_cast<u32>(BytesInPixels(stride * (is_tiled ? 8 : 1))); 345 const u32 tile_stride = static_cast<u32>(BytesInPixels(stride * (is_tiled ? 8 : 1)));
344 return (texcopy_params.addr - addr) % BytesInPixels(is_tiled ? 64 : 1) == 0 && 346 return (texcopy_params.addr - addr) % BytesInPixels(is_tiled ? 64 : 1) == 0 &&
@@ -481,18 +483,13 @@ void CachedSurface::LoadGLBuffer(VAddr load_start, VAddr load_end) {
481 const u64 start_offset = load_start - addr; 483 const u64 start_offset = load_start - addr;
482 484
483 if (!is_tiled) { 485 if (!is_tiled) {
484 ASSERT(type == SurfaceType::Color);
485 const u32 bytes_per_pixel{GetFormatBpp() >> 3}; 486 const u32 bytes_per_pixel{GetFormatBpp() >> 3};
486 487
487 // TODO(bunnei): Assumes the default rendering GOB size of 16 (128 lines). We should check 488 std::memcpy(&gl_buffer[start_offset], texture_src_data + start_offset,
488 // the configuration for this and perform more generic un/swizzle 489 bytes_per_pixel * width * height);
489 LOG_WARNING(Render_OpenGL, "need to use correct swizzle/GOB parameters!");
490 VideoCore::MortonCopyPixels128(width, height, bytes_per_pixel, 4,
491 texture_src_data + start_offset, &gl_buffer[start_offset],
492 true);
493 } else { 490 } else {
494 morton_to_gl_fns[static_cast<size_t>(pixel_format)](stride, height, &gl_buffer[0], addr, 491 morton_to_gl_fns[static_cast<size_t>(pixel_format)](
495 load_start, load_end); 492 stride, block_height, height, &gl_buffer[0], addr, load_start, load_end);
496 } 493 }
497} 494}
498 495
@@ -533,11 +530,10 @@ void CachedSurface::FlushGLBuffer(VAddr flush_start, VAddr flush_end) {
533 if (backup_bytes) 530 if (backup_bytes)
534 std::memcpy(&dst_buffer[coarse_start_offset], &backup_data[0], backup_bytes); 531 std::memcpy(&dst_buffer[coarse_start_offset], &backup_data[0], backup_bytes);
535 } else if (!is_tiled) { 532 } else if (!is_tiled) {
536 ASSERT(type == SurfaceType::Color);
537 std::memcpy(dst_buffer + start_offset, &gl_buffer[start_offset], flush_end - flush_start); 533 std::memcpy(dst_buffer + start_offset, &gl_buffer[start_offset], flush_end - flush_start);
538 } else { 534 } else {
539 gl_to_morton_fns[static_cast<size_t>(pixel_format)](stride, height, &gl_buffer[0], addr, 535 gl_to_morton_fns[static_cast<size_t>(pixel_format)](
540 flush_start, flush_end); 536 stride, block_height, height, &gl_buffer[0], addr, flush_start, flush_end);
541 } 537 }
542} 538}
543 539
@@ -1041,9 +1037,18 @@ Surface RasterizerCacheOpenGL::GetTextureSurface(const Tegra::Texture::FullTextu
1041 params.height = config.tic.Height(); 1037 params.height = config.tic.Height();
1042 params.is_tiled = config.tic.IsTiled(); 1038 params.is_tiled = config.tic.IsTiled();
1043 params.pixel_format = SurfaceParams::PixelFormatFromTextureFormat(config.tic.format); 1039 params.pixel_format = SurfaceParams::PixelFormatFromTextureFormat(config.tic.format);
1040
1041 if (config.tic.IsTiled()) {
1042 params.block_height = config.tic.BlockHeight();
1043 } else {
1044 // Use the texture-provided stride value if the texture isn't tiled.
1045 params.stride = params.PixelsInBytes(config.tic.Pitch());
1046 }
1047
1044 params.UpdateParams(); 1048 params.UpdateParams();
1045 1049
1046 if (config.tic.Width() % 8 != 0 || config.tic.Height() % 8 != 0) { 1050 if (config.tic.Width() % 8 != 0 || config.tic.Height() % 8 != 0 ||
1051 params.stride != params.width) {
1047 Surface src_surface; 1052 Surface src_surface;
1048 MathUtil::Rectangle<u32> rect; 1053 MathUtil::Rectangle<u32> rect;
1049 std::tie(src_surface, rect) = GetSurfaceSubRect(params, ScaleMatch::Ignore, true); 1054 std::tie(src_surface, rect) = GetSurfaceSubRect(params, ScaleMatch::Ignore, true);
@@ -1094,6 +1099,8 @@ SurfaceSurfaceRect_Tuple RasterizerCacheOpenGL::GetFramebufferSurfaces(
1094 color_params.res_scale = resolution_scale_factor; 1099 color_params.res_scale = resolution_scale_factor;
1095 color_params.width = config.width; 1100 color_params.width = config.width;
1096 color_params.height = config.height; 1101 color_params.height = config.height;
1102 // TODO(Subv): Can framebuffers use a different block height?
1103 color_params.block_height = Tegra::Texture::TICEntry::DefaultBlockHeight;
1097 SurfaceParams depth_params = color_params; 1104 SurfaceParams depth_params = color_params;
1098 1105
1099 color_params.addr = memory_manager->PhysicalToVirtualAddress(config.Address()); 1106 color_params.addr = memory_manager->PhysicalToVirtualAddress(config.Address());
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.h b/src/video_core/renderer_opengl/gl_rasterizer_cache.h
index 3293905d6..26d6c3061 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer_cache.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.h
@@ -115,6 +115,18 @@ struct SurfaceParams {
115 } 115 }
116 } 116 }
117 117
118 static Tegra::Texture::TextureFormat TextureFormatFromPixelFormat(PixelFormat format) {
119 // TODO(Subv): Properly implement this
120 switch (format) {
121 case PixelFormat::RGBA8:
122 return Tegra::Texture::TextureFormat::A8R8G8B8;
123 case PixelFormat::DXT1:
124 return Tegra::Texture::TextureFormat::DXT1;
125 default:
126 UNREACHABLE();
127 }
128 }
129
118 static bool CheckFormatsBlittable(PixelFormat pixel_format_a, PixelFormat pixel_format_b) { 130 static bool CheckFormatsBlittable(PixelFormat pixel_format_a, PixelFormat pixel_format_b) {
119 SurfaceType a_type = GetFormatType(pixel_format_a); 131 SurfaceType a_type = GetFormatType(pixel_format_a);
120 SurfaceType b_type = GetFormatType(pixel_format_b); 132 SurfaceType b_type = GetFormatType(pixel_format_b);
@@ -213,6 +225,7 @@ struct SurfaceParams {
213 u32 width = 0; 225 u32 width = 0;
214 u32 height = 0; 226 u32 height = 0;
215 u32 stride = 0; 227 u32 stride = 0;
228 u32 block_height = 0;
216 u16 res_scale = 1; 229 u16 res_scale = 1;
217 230
218 bool is_tiled = false; 231 bool is_tiled = false;
diff --git a/src/video_core/textures/decoders.cpp b/src/video_core/textures/decoders.cpp
index 2e87281eb..9c2a10d2e 100644
--- a/src/video_core/textures/decoders.cpp
+++ b/src/video_core/textures/decoders.cpp
@@ -56,23 +56,22 @@ u32 BytesPerPixel(TextureFormat format) {
56 } 56 }
57} 57}
58 58
59std::vector<u8> UnswizzleTexture(VAddr address, TextureFormat format, u32 width, u32 height) { 59std::vector<u8> UnswizzleTexture(VAddr address, TextureFormat format, u32 width, u32 height,
60 u32 block_height) {
60 u8* data = Memory::GetPointer(address); 61 u8* data = Memory::GetPointer(address);
61 u32 bytes_per_pixel = BytesPerPixel(format); 62 u32 bytes_per_pixel = BytesPerPixel(format);
62 63
63 static constexpr u32 DefaultBlockHeight = 16;
64
65 std::vector<u8> unswizzled_data(width * height * bytes_per_pixel); 64 std::vector<u8> unswizzled_data(width * height * bytes_per_pixel);
66 65
67 switch (format) { 66 switch (format) {
68 case TextureFormat::DXT1: 67 case TextureFormat::DXT1:
69 // In the DXT1 format, each 4x4 tile is swizzled instead of just individual pixel values. 68 // 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, 69 CopySwizzledData(width / 4, height / 4, bytes_per_pixel, bytes_per_pixel, data,
71 unswizzled_data.data(), true, DefaultBlockHeight); 70 unswizzled_data.data(), true, block_height);
72 break; 71 break;
73 case TextureFormat::A8R8G8B8: 72 case TextureFormat::A8R8G8B8:
74 CopySwizzledData(width, height, bytes_per_pixel, bytes_per_pixel, data, 73 CopySwizzledData(width, height, bytes_per_pixel, bytes_per_pixel, data,
75 unswizzled_data.data(), true, DefaultBlockHeight); 74 unswizzled_data.data(), true, block_height);
76 break; 75 break;
77 default: 76 default:
78 UNIMPLEMENTED_MSG("Format not implemented"); 77 UNIMPLEMENTED_MSG("Format not implemented");
diff --git a/src/video_core/textures/decoders.h b/src/video_core/textures/decoders.h
index 0c21694ff..a700911cf 100644
--- a/src/video_core/textures/decoders.h
+++ b/src/video_core/textures/decoders.h
@@ -14,7 +14,8 @@ namespace Texture {
14/** 14/**
15 * Unswizzles a swizzled texture without changing its format. 15 * Unswizzles a swizzled texture without changing its format.
16 */ 16 */
17std::vector<u8> UnswizzleTexture(VAddr address, TextureFormat format, u32 width, u32 height); 17std::vector<u8> UnswizzleTexture(VAddr address, TextureFormat format, u32 width, u32 height,
18 u32 block_height = TICEntry::DefaultBlockHeight);
18 19
19/** 20/**
20 * Decodes an unswizzled texture into a A8R8G8B8 texture. 21 * Decodes an unswizzled texture into a A8R8G8B8 texture.
diff --git a/src/video_core/textures/texture.h b/src/video_core/textures/texture.h
index 9d443ea90..09d2317e0 100644
--- a/src/video_core/textures/texture.h
+++ b/src/video_core/textures/texture.h
@@ -4,6 +4,7 @@
4 4
5#pragma once 5#pragma once
6 6
7#include "common/assert.h"
7#include "common/bit_field.h" 8#include "common/bit_field.h"
8#include "common/common_funcs.h" 9#include "common/common_funcs.h"
9#include "common/common_types.h" 10#include "common/common_types.h"
@@ -57,6 +58,8 @@ union TextureHandle {
57static_assert(sizeof(TextureHandle) == 4, "TextureHandle has wrong size"); 58static_assert(sizeof(TextureHandle) == 4, "TextureHandle has wrong size");
58 59
59struct TICEntry { 60struct TICEntry {
61 static constexpr u32 DefaultBlockHeight = 16;
62
60 union { 63 union {
61 u32 raw; 64 u32 raw;
62 BitField<0, 7, TextureFormat> format; 65 BitField<0, 7, TextureFormat> format;
@@ -70,7 +73,12 @@ struct TICEntry {
70 BitField<0, 16, u32> address_high; 73 BitField<0, 16, u32> address_high;
71 BitField<21, 3, TICHeaderVersion> header_version; 74 BitField<21, 3, TICHeaderVersion> header_version;
72 }; 75 };
73 INSERT_PADDING_BYTES(4); 76 union {
77 BitField<3, 3, u32> block_height;
78
79 // High 16 bits of the pitch value
80 BitField<0, 16, u32> pitch_high;
81 };
74 union { 82 union {
75 BitField<0, 16, u32> width_minus_1; 83 BitField<0, 16, u32> width_minus_1;
76 BitField<23, 4, TextureType> texture_type; 84 BitField<23, 4, TextureType> texture_type;
@@ -82,6 +90,13 @@ struct TICEntry {
82 return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) | address_low); 90 return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) | address_low);
83 } 91 }
84 92
93 u32 Pitch() const {
94 ASSERT(header_version == TICHeaderVersion::Pitch ||
95 header_version == TICHeaderVersion::PitchColorKey);
96 // The pitch value is 21 bits, and is 32B aligned.
97 return pitch_high << 5;
98 }
99
85 u32 Width() const { 100 u32 Width() const {
86 return width_minus_1 + 1; 101 return width_minus_1 + 1;
87 } 102 }
@@ -90,6 +105,13 @@ struct TICEntry {
90 return height_minus_1 + 1; 105 return height_minus_1 + 1;
91 } 106 }
92 107
108 u32 BlockHeight() const {
109 ASSERT(header_version == TICHeaderVersion::BlockLinear ||
110 header_version == TICHeaderVersion::BlockLinearColorKey);
111 // The block height is stored in log2 format.
112 return 1 << block_height;
113 }
114
93 bool IsTiled() const { 115 bool IsTiled() const {
94 return header_version == TICHeaderVersion::BlockLinear || 116 return header_version == TICHeaderVersion::BlockLinear ||
95 header_version == TICHeaderVersion::BlockLinearColorKey; 117 header_version == TICHeaderVersion::BlockLinearColorKey;