summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/video_core/engines/maxwell_3d.cpp5
-rw-r--r--src/video_core/engines/maxwell_3d.h11
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp5
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer_cache.cpp166
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer_cache.h117
-rw-r--r--src/video_core/renderer_opengl/gl_shader_gen.cpp10
-rw-r--r--src/video_core/renderer_opengl/gl_shader_manager.cpp8
-rw-r--r--src/video_core/renderer_opengl/gl_shader_manager.h5
-rw-r--r--src/video_core/textures/decoders.cpp23
-rw-r--r--src/video_core/textures/decoders.h3
-rw-r--r--src/video_core/textures/texture.h25
11 files changed, 260 insertions, 118 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/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h
index b379d8057..d4fcedace 100644
--- a/src/video_core/engines/maxwell_3d.h
+++ b/src/video_core/engines/maxwell_3d.h
@@ -319,7 +319,15 @@ public:
319 } 319 }
320 } rt[NumRenderTargets]; 320 } rt[NumRenderTargets];
321 321
322 INSERT_PADDING_WORDS(0x80); 322 struct {
323 f32 scale_x;
324 f32 scale_y;
325 f32 scale_z;
326 u32 translate_x;
327 u32 translate_y;
328 u32 translate_z;
329 INSERT_PADDING_WORDS(2);
330 } viewport_transform[NumViewports];
323 331
324 struct { 332 struct {
325 union { 333 union {
@@ -649,6 +657,7 @@ private:
649 "Field " #field_name " has invalid position") 657 "Field " #field_name " has invalid position")
650 658
651ASSERT_REG_POSITION(rt, 0x200); 659ASSERT_REG_POSITION(rt, 0x200);
660ASSERT_REG_POSITION(viewport_transform[0], 0x280);
652ASSERT_REG_POSITION(viewport, 0x300); 661ASSERT_REG_POSITION(viewport, 0x300);
653ASSERT_REG_POSITION(vertex_buffer, 0x35D); 662ASSERT_REG_POSITION(vertex_buffer, 0x35D);
654ASSERT_REG_POSITION(zeta, 0x3F8); 663ASSERT_REG_POSITION(zeta, 0x3F8);
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index 7b6240e65..13e2a77ce 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -523,9 +523,12 @@ 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);
530 src_params.component_type =
531 SurfaceParams::ComponentTypeFromGPUPixelFormat(framebuffer.pixel_format);
529 src_params.UpdateParams(); 532 src_params.UpdateParams();
530 533
531 MathUtil::Rectangle<u32> src_rect; 534 MathUtil::Rectangle<u32> src_rect;
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
index 213b20a21..561c6913d 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
@@ -36,6 +36,7 @@
36 36
37using SurfaceType = SurfaceParams::SurfaceType; 37using SurfaceType = SurfaceParams::SurfaceType;
38using PixelFormat = SurfaceParams::PixelFormat; 38using PixelFormat = SurfaceParams::PixelFormat;
39using ComponentType = SurfaceParams::ComponentType;
39 40
40struct FormatTuple { 41struct FormatTuple {
41 GLint internal_format; 42 GLint internal_format;
@@ -47,26 +48,24 @@ struct FormatTuple {
47 u32 compression_factor; 48 u32 compression_factor;
48}; 49};
49 50
50static constexpr std::array<FormatTuple, 1> fb_format_tuples = {{ 51static constexpr std::array<FormatTuple, SurfaceParams::MaxPixelFormat> tex_format_tuples = {{
51 {GL_RGBA8, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, false, 1}, // RGBA8 52 {GL_RGBA8, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, false, 1}, // ABGR8
53 {GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5_REV, false, 1}, // B5G6R5
54 {GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_RGB, GL_UNSIGNED_INT_8_8_8_8, true, 16}, // DXT1
55 {GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, true, 16}, // DXT23
56 {GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, true, 16}, // DXT45
52}}; 57}};
53 58
54static constexpr std::array<FormatTuple, 2> tex_format_tuples = {{ 59static const FormatTuple& GetFormatTuple(PixelFormat pixel_format, ComponentType component_type) {
55 {GL_RGBA8, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, false, 1}, // RGBA8
56 {GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_RGB, GL_UNSIGNED_INT_8_8_8_8, true, 16}, // DXT1
57}};
58
59static const FormatTuple& GetFormatTuple(PixelFormat pixel_format) {
60 const SurfaceType type = SurfaceParams::GetFormatType(pixel_format); 60 const SurfaceType type = SurfaceParams::GetFormatType(pixel_format);
61 if (type == SurfaceType::Color) { 61 if (type == SurfaceType::ColorTexture) {
62 ASSERT(static_cast<size_t>(pixel_format) < fb_format_tuples.size()); 62 ASSERT(static_cast<size_t>(pixel_format) < tex_format_tuples.size());
63 return fb_format_tuples[static_cast<unsigned int>(pixel_format)]; 63 // For now only UNORM components are supported
64 ASSERT(component_type == ComponentType::UNorm);
65 return tex_format_tuples[static_cast<unsigned int>(pixel_format)];
64 } else if (type == SurfaceType::Depth || type == SurfaceType::DepthStencil) { 66 } else if (type == SurfaceType::Depth || type == SurfaceType::DepthStencil) {
65 // TODO(Subv): Implement depth formats 67 // TODO(Subv): Implement depth formats
66 ASSERT_MSG(false, "Unimplemented"); 68 ASSERT_MSG(false, "Unimplemented");
67 } else if (type == SurfaceType::Texture) {
68 ASSERT(static_cast<size_t>(pixel_format) < tex_format_tuples.size());
69 return tex_format_tuples[static_cast<unsigned int>(pixel_format)];
70 } 69 }
71 70
72 UNREACHABLE(); 71 UNREACHABLE();
@@ -85,56 +84,42 @@ static u16 GetResolutionScaleFactor() {
85} 84}
86 85
87template <bool morton_to_gl, PixelFormat format> 86template <bool morton_to_gl, PixelFormat format>
88static void MortonCopyTile(u32 stride, u8* tile_buffer, u8* gl_buffer) { 87void MortonCopy(u32 stride, u32 block_height, u32 height, u8* gl_buffer, VAddr base, VAddr start,
88 VAddr end) {
89 constexpr u32 bytes_per_pixel = SurfaceParams::GetFormatBpp(format) / 8; 89 constexpr u32 bytes_per_pixel = SurfaceParams::GetFormatBpp(format) / 8;
90 constexpr u32 gl_bytes_per_pixel = CachedSurface::GetGLBytesPerPixel(format); 90 constexpr u32 gl_bytes_per_pixel = CachedSurface::GetGLBytesPerPixel(format);
91 for (u32 y = 0; y < 8; ++y) {
92 for (u32 x = 0; x < 8; ++x) {
93 u8* tile_ptr = tile_buffer + VideoCore::MortonInterleave(x, y) * bytes_per_pixel;
94 u8* gl_ptr = gl_buffer + ((7 - y) * stride + x) * gl_bytes_per_pixel;
95 if (morton_to_gl) {
96 std::memcpy(gl_ptr, tile_ptr, bytes_per_pixel);
97 } else {
98 std::memcpy(tile_ptr, gl_ptr, bytes_per_pixel);
99 }
100 }
101 }
102}
103
104template <bool morton_to_gl, PixelFormat format>
105void MortonCopy(u32 stride, u32 height, u8* gl_buffer, VAddr base, VAddr start, VAddr end) {
106 constexpr u32 bytes_per_pixel = SurfaceParams::GetFormatBpp(format) / 8;
107 constexpr u32 gl_bytes_per_pixel = CachedSurface::GetGLBytesPerPixel(format);
108
109 // TODO(bunnei): Assumes the default rendering GOB size of 16 (128 lines). We should check the
110 // configuration for this and perform more generic un/swizzle
111 LOG_WARNING(Render_OpenGL, "need to use correct swizzle/GOB parameters!");
112 VideoCore::MortonCopyPixels128(stride, height, bytes_per_pixel, gl_bytes_per_pixel,
113 Memory::GetPointer(base), gl_buffer, morton_to_gl);
114}
115 91
116template <> 92 if (morton_to_gl) {
117void MortonCopy<true, PixelFormat::DXT1>(u32 stride, u32 height, u8* gl_buffer, VAddr base, 93 auto data = Tegra::Texture::UnswizzleTexture(
118 VAddr start, VAddr end) { 94 base, SurfaceParams::TextureFormatFromPixelFormat(format), stride, height,
119 constexpr u32 bytes_per_pixel = SurfaceParams::GetFormatBpp(PixelFormat::DXT1) / 8; 95 block_height);
120 constexpr u32 gl_bytes_per_pixel = CachedSurface::GetGLBytesPerPixel(PixelFormat::DXT1); 96 std::memcpy(gl_buffer, data.data(), data.size());
121 97 } else {
122 // TODO(bunnei): Assumes the default rendering GOB size of 16 (128 lines). We should check the 98 // TODO(bunnei): Assumes the default rendering GOB size of 16 (128 lines). We should check
123 // configuration for this and perform more generic un/swizzle 99 // the configuration for this and perform more generic un/swizzle
124 LOG_WARNING(Render_OpenGL, "need to use correct swizzle/GOB parameters!"); 100 LOG_WARNING(Render_OpenGL, "need to use correct swizzle/GOB parameters!");
125 auto data = 101 VideoCore::MortonCopyPixels128(stride, height, bytes_per_pixel, gl_bytes_per_pixel,
126 Tegra::Texture::UnswizzleTexture(base, Tegra::Texture::TextureFormat::DXT1, stride, height); 102 Memory::GetPointer(base), gl_buffer, morton_to_gl);
127 std::memcpy(gl_buffer, data.data(), data.size()); 103 }
128} 104}
129 105
130static constexpr std::array<void (*)(u32, u32, u8*, VAddr, VAddr, VAddr), 2> morton_to_gl_fns = { 106static constexpr std::array<void (*)(u32, u32, u32, u8*, VAddr, VAddr, VAddr),
131 MortonCopy<true, PixelFormat::RGBA8>, 107 SurfaceParams::MaxPixelFormat>
132 MortonCopy<true, PixelFormat::DXT1>, 108 morton_to_gl_fns = {
109 MortonCopy<true, PixelFormat::ABGR8>, MortonCopy<true, PixelFormat::B5G6R5>,
110 MortonCopy<true, PixelFormat::DXT1>, MortonCopy<true, PixelFormat::DXT23>,
111 MortonCopy<true, PixelFormat::DXT45>,
133}; 112};
134 113
135static constexpr std::array<void (*)(u32, u32, u8*, VAddr, VAddr, VAddr), 2> gl_to_morton_fns = { 114static constexpr std::array<void (*)(u32, u32, u32, u8*, VAddr, VAddr, VAddr),
136 MortonCopy<false, PixelFormat::RGBA8>, 115 SurfaceParams::MaxPixelFormat>
137 MortonCopy<false, PixelFormat::DXT1>, 116 gl_to_morton_fns = {
117 MortonCopy<false, PixelFormat::ABGR8>,
118 MortonCopy<false, PixelFormat::B5G6R5>,
119 // TODO(Subv): Swizzling the DXT1/DXT23/DXT45 formats is not yet supported
120 nullptr,
121 nullptr,
122 nullptr,
138}; 123};
139 124
140// Allocate an uninitialized texture of appropriate size and format for the surface 125// Allocate an uninitialized texture of appropriate size and format for the surface
@@ -183,7 +168,7 @@ static bool BlitTextures(GLuint src_tex, const MathUtil::Rectangle<u32>& src_rec
183 168
184 u32 buffers = 0; 169 u32 buffers = 0;
185 170
186 if (type == SurfaceType::Color || type == SurfaceType::Texture) { 171 if (type == SurfaceType::ColorTexture) {
187 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, src_tex, 172 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, src_tex,
188 0); 173 0);
189 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 174 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0,
@@ -311,15 +296,18 @@ MathUtil::Rectangle<u32> SurfaceParams::GetScaledSubRect(const SurfaceParams& su
311 296
312bool SurfaceParams::ExactMatch(const SurfaceParams& other_surface) const { 297bool SurfaceParams::ExactMatch(const SurfaceParams& other_surface) const {
313 return std::tie(other_surface.addr, other_surface.width, other_surface.height, 298 return std::tie(other_surface.addr, other_surface.width, other_surface.height,
314 other_surface.stride, other_surface.pixel_format, other_surface.is_tiled) == 299 other_surface.stride, other_surface.block_height, other_surface.pixel_format,
315 std::tie(addr, width, height, stride, pixel_format, is_tiled) && 300 other_surface.component_type,
301 other_surface.is_tiled) == std::tie(addr, width, height, stride, block_height,
302 pixel_format, component_type, is_tiled) &&
316 pixel_format != PixelFormat::Invalid; 303 pixel_format != PixelFormat::Invalid;
317} 304}
318 305
319bool SurfaceParams::CanSubRect(const SurfaceParams& sub_surface) const { 306bool SurfaceParams::CanSubRect(const SurfaceParams& sub_surface) const {
320 return sub_surface.addr >= addr && sub_surface.end <= end && 307 return sub_surface.addr >= addr && sub_surface.end <= end &&
321 sub_surface.pixel_format == pixel_format && pixel_format != PixelFormat::Invalid && 308 sub_surface.pixel_format == pixel_format && pixel_format != PixelFormat::Invalid &&
322 sub_surface.is_tiled == is_tiled && 309 sub_surface.is_tiled == is_tiled && sub_surface.block_height == block_height &&
310 sub_surface.component_type == component_type &&
323 (sub_surface.addr - addr) % BytesInPixels(is_tiled ? 64 : 1) == 0 && 311 (sub_surface.addr - addr) % BytesInPixels(is_tiled ? 64 : 1) == 0 &&
324 (sub_surface.stride == stride || sub_surface.height <= (is_tiled ? 8u : 1u)) && 312 (sub_surface.stride == stride || sub_surface.height <= (is_tiled ? 8u : 1u)) &&
325 GetSubRect(sub_surface).left + sub_surface.width <= stride; 313 GetSubRect(sub_surface).left + sub_surface.width <= stride;
@@ -328,7 +316,8 @@ bool SurfaceParams::CanSubRect(const SurfaceParams& sub_surface) const {
328bool SurfaceParams::CanExpand(const SurfaceParams& expanded_surface) const { 316bool SurfaceParams::CanExpand(const SurfaceParams& expanded_surface) const {
329 return pixel_format != PixelFormat::Invalid && pixel_format == expanded_surface.pixel_format && 317 return pixel_format != PixelFormat::Invalid && pixel_format == expanded_surface.pixel_format &&
330 addr <= expanded_surface.end && expanded_surface.addr <= end && 318 addr <= expanded_surface.end && expanded_surface.addr <= end &&
331 is_tiled == expanded_surface.is_tiled && stride == expanded_surface.stride && 319 is_tiled == expanded_surface.is_tiled && block_height == expanded_surface.block_height &&
320 component_type == expanded_surface.component_type && stride == expanded_surface.stride &&
332 (std::max(expanded_surface.addr, addr) - std::min(expanded_surface.addr, addr)) % 321 (std::max(expanded_surface.addr, addr) - std::min(expanded_surface.addr, addr)) %
333 BytesInPixels(stride * (is_tiled ? 8 : 1)) == 322 BytesInPixels(stride * (is_tiled ? 8 : 1)) ==
334 0; 323 0;
@@ -339,6 +328,10 @@ bool SurfaceParams::CanTexCopy(const SurfaceParams& texcopy_params) const {
339 end < texcopy_params.end) { 328 end < texcopy_params.end) {
340 return false; 329 return false;
341 } 330 }
331 if (texcopy_params.block_height != block_height ||
332 texcopy_params.component_type != component_type)
333 return false;
334
342 if (texcopy_params.width != texcopy_params.stride) { 335 if (texcopy_params.width != texcopy_params.stride) {
343 const u32 tile_stride = static_cast<u32>(BytesInPixels(stride * (is_tiled ? 8 : 1))); 336 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 && 337 return (texcopy_params.addr - addr) % BytesInPixels(is_tiled ? 64 : 1) == 0 &&
@@ -481,18 +474,13 @@ void CachedSurface::LoadGLBuffer(VAddr load_start, VAddr load_end) {
481 const u64 start_offset = load_start - addr; 474 const u64 start_offset = load_start - addr;
482 475
483 if (!is_tiled) { 476 if (!is_tiled) {
484 ASSERT(type == SurfaceType::Color);
485 const u32 bytes_per_pixel{GetFormatBpp() >> 3}; 477 const u32 bytes_per_pixel{GetFormatBpp() >> 3};
486 478
487 // TODO(bunnei): Assumes the default rendering GOB size of 16 (128 lines). We should check 479 std::memcpy(&gl_buffer[start_offset], texture_src_data + start_offset,
488 // the configuration for this and perform more generic un/swizzle 480 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 { 481 } else {
494 morton_to_gl_fns[static_cast<size_t>(pixel_format)](stride, height, &gl_buffer[0], addr, 482 morton_to_gl_fns[static_cast<size_t>(pixel_format)](
495 load_start, load_end); 483 stride, block_height, height, &gl_buffer[0], addr, load_start, load_end);
496 } 484 }
497} 485}
498 486
@@ -533,11 +521,10 @@ void CachedSurface::FlushGLBuffer(VAddr flush_start, VAddr flush_end) {
533 if (backup_bytes) 521 if (backup_bytes)
534 std::memcpy(&dst_buffer[coarse_start_offset], &backup_data[0], backup_bytes); 522 std::memcpy(&dst_buffer[coarse_start_offset], &backup_data[0], backup_bytes);
535 } else if (!is_tiled) { 523 } else if (!is_tiled) {
536 ASSERT(type == SurfaceType::Color);
537 std::memcpy(dst_buffer + start_offset, &gl_buffer[start_offset], flush_end - flush_start); 524 std::memcpy(dst_buffer + start_offset, &gl_buffer[start_offset], flush_end - flush_start);
538 } else { 525 } else {
539 gl_to_morton_fns[static_cast<size_t>(pixel_format)](stride, height, &gl_buffer[0], addr, 526 gl_to_morton_fns[static_cast<size_t>(pixel_format)](
540 flush_start, flush_end); 527 stride, block_height, height, &gl_buffer[0], addr, flush_start, flush_end);
541 } 528 }
542} 529}
543 530
@@ -556,7 +543,7 @@ void CachedSurface::UploadGLTexture(const MathUtil::Rectangle<u32>& rect, GLuint
556 GLint y0 = static_cast<GLint>(rect.bottom); 543 GLint y0 = static_cast<GLint>(rect.bottom);
557 size_t buffer_offset = (y0 * stride + x0) * GetGLBytesPerPixel(pixel_format); 544 size_t buffer_offset = (y0 * stride + x0) * GetGLBytesPerPixel(pixel_format);
558 545
559 const FormatTuple& tuple = GetFormatTuple(pixel_format); 546 const FormatTuple& tuple = GetFormatTuple(pixel_format, component_type);
560 GLuint target_tex = texture.handle; 547 GLuint target_tex = texture.handle;
561 548
562 // If not 1x scale, create 1x texture that we will blit from to replace texture subrect in 549 // If not 1x scale, create 1x texture that we will blit from to replace texture subrect in
@@ -629,7 +616,7 @@ void CachedSurface::DownloadGLTexture(const MathUtil::Rectangle<u32>& rect, GLui
629 OpenGLState prev_state = state; 616 OpenGLState prev_state = state;
630 SCOPE_EXIT({ prev_state.Apply(); }); 617 SCOPE_EXIT({ prev_state.Apply(); });
631 618
632 const FormatTuple& tuple = GetFormatTuple(pixel_format); 619 const FormatTuple& tuple = GetFormatTuple(pixel_format, component_type);
633 620
634 // Ensure no bad interactions with GL_PACK_ALIGNMENT 621 // Ensure no bad interactions with GL_PACK_ALIGNMENT
635 ASSERT(stride * GetGLBytesPerPixel(pixel_format) % 4 == 0); 622 ASSERT(stride * GetGLBytesPerPixel(pixel_format) % 4 == 0);
@@ -662,7 +649,7 @@ void CachedSurface::DownloadGLTexture(const MathUtil::Rectangle<u32>& rect, GLui
662 state.draw.read_framebuffer = read_fb_handle; 649 state.draw.read_framebuffer = read_fb_handle;
663 state.Apply(); 650 state.Apply();
664 651
665 if (type == SurfaceType::Color || type == SurfaceType::Texture) { 652 if (type == SurfaceType::ColorTexture) {
666 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 653 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
667 texture.handle, 0); 654 texture.handle, 0);
668 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 655 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D,
@@ -1041,9 +1028,25 @@ Surface RasterizerCacheOpenGL::GetTextureSurface(const Tegra::Texture::FullTextu
1041 params.height = config.tic.Height(); 1028 params.height = config.tic.Height();
1042 params.is_tiled = config.tic.IsTiled(); 1029 params.is_tiled = config.tic.IsTiled();
1043 params.pixel_format = SurfaceParams::PixelFormatFromTextureFormat(config.tic.format); 1030 params.pixel_format = SurfaceParams::PixelFormatFromTextureFormat(config.tic.format);
1031
1032 // TODO(Subv): Different types per component are not supported.
1033 ASSERT(config.tic.r_type.Value() == config.tic.g_type.Value() &&
1034 config.tic.r_type.Value() == config.tic.b_type.Value() &&
1035 config.tic.r_type.Value() == config.tic.a_type.Value());
1036
1037 params.component_type = SurfaceParams::ComponentTypeFromTexture(config.tic.r_type.Value());
1038
1039 if (config.tic.IsTiled()) {
1040 params.block_height = config.tic.BlockHeight();
1041 } else {
1042 // Use the texture-provided stride value if the texture isn't tiled.
1043 params.stride = params.PixelsInBytes(config.tic.Pitch());
1044 }
1045
1044 params.UpdateParams(); 1046 params.UpdateParams();
1045 1047
1046 if (config.tic.Width() % 8 != 0 || config.tic.Height() % 8 != 0) { 1048 if (config.tic.Width() % 8 != 0 || config.tic.Height() % 8 != 0 ||
1049 params.stride != params.width) {
1047 Surface src_surface; 1050 Surface src_surface;
1048 MathUtil::Rectangle<u32> rect; 1051 MathUtil::Rectangle<u32> rect;
1049 std::tie(src_surface, rect) = GetSurfaceSubRect(params, ScaleMatch::Ignore, true); 1052 std::tie(src_surface, rect) = GetSurfaceSubRect(params, ScaleMatch::Ignore, true);
@@ -1094,10 +1097,13 @@ SurfaceSurfaceRect_Tuple RasterizerCacheOpenGL::GetFramebufferSurfaces(
1094 color_params.res_scale = resolution_scale_factor; 1097 color_params.res_scale = resolution_scale_factor;
1095 color_params.width = config.width; 1098 color_params.width = config.width;
1096 color_params.height = config.height; 1099 color_params.height = config.height;
1100 // TODO(Subv): Can framebuffers use a different block height?
1101 color_params.block_height = Tegra::Texture::TICEntry::DefaultBlockHeight;
1097 SurfaceParams depth_params = color_params; 1102 SurfaceParams depth_params = color_params;
1098 1103
1099 color_params.addr = memory_manager->PhysicalToVirtualAddress(config.Address()); 1104 color_params.addr = memory_manager->PhysicalToVirtualAddress(config.Address());
1100 color_params.pixel_format = SurfaceParams::PixelFormatFromRenderTargetFormat(config.format); 1105 color_params.pixel_format = SurfaceParams::PixelFormatFromRenderTargetFormat(config.format);
1106 color_params.component_type = SurfaceParams::ComponentTypeFromRenderTarget(config.format);
1101 color_params.UpdateParams(); 1107 color_params.UpdateParams();
1102 1108
1103 ASSERT_MSG(!using_depth_fb, "depth buffer is unimplemented"); 1109 ASSERT_MSG(!using_depth_fb, "depth buffer is unimplemented");
@@ -1293,7 +1299,6 @@ void RasterizerCacheOpenGL::InvalidateRegion(VAddr addr, u64 size, const Surface
1293 const SurfaceInterval invalid_interval(addr, addr + size); 1299 const SurfaceInterval invalid_interval(addr, addr + size);
1294 1300
1295 if (region_owner != nullptr) { 1301 if (region_owner != nullptr) {
1296 ASSERT(region_owner->type != SurfaceType::Texture);
1297 ASSERT(addr >= region_owner->addr && addr + size <= region_owner->end); 1302 ASSERT(addr >= region_owner->addr && addr + size <= region_owner->end);
1298 // Surfaces can't have a gap 1303 // Surfaces can't have a gap
1299 ASSERT(region_owner->width == region_owner->stride); 1304 ASSERT(region_owner->width == region_owner->stride);
@@ -1355,7 +1360,8 @@ Surface RasterizerCacheOpenGL::CreateSurface(const SurfaceParams& params) {
1355 1360
1356 surface->gl_buffer_size = 0; 1361 surface->gl_buffer_size = 0;
1357 surface->invalid_regions.insert(surface->GetInterval()); 1362 surface->invalid_regions.insert(surface->GetInterval());
1358 AllocateSurfaceTexture(surface->texture.handle, GetFormatTuple(surface->pixel_format), 1363 AllocateSurfaceTexture(surface->texture.handle,
1364 GetFormatTuple(surface->pixel_format, surface->component_type),
1359 surface->GetScaledWidth(), surface->GetScaledHeight()); 1365 surface->GetScaledWidth(), surface->GetScaledHeight());
1360 1366
1361 return surface; 1367 return surface;
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.h b/src/video_core/renderer_opengl/gl_rasterizer_cache.h
index 3293905d6..6861efe16 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer_cache.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.h
@@ -52,27 +52,45 @@ enum class ScaleMatch {
52 52
53struct SurfaceParams { 53struct SurfaceParams {
54 enum class PixelFormat { 54 enum class PixelFormat {
55 RGBA8 = 0, 55 ABGR8 = 0,
56 DXT1 = 1, 56 B5G6R5 = 1,
57 DXT1 = 2,
58 DXT23 = 3,
59 DXT45 = 4,
60
61 Max,
57 Invalid = 255, 62 Invalid = 255,
58 }; 63 };
59 64
65 static constexpr size_t MaxPixelFormat = static_cast<size_t>(PixelFormat::Max);
66
67 enum class ComponentType {
68 Invalid = 0,
69 SNorm = 1,
70 UNorm = 2,
71 SInt = 3,
72 UInt = 4,
73 Float = 5,
74 };
75
60 enum class SurfaceType { 76 enum class SurfaceType {
61 Color = 0, 77 ColorTexture = 0,
62 Texture = 1, 78 Depth = 1,
63 Depth = 2, 79 DepthStencil = 2,
64 DepthStencil = 3, 80 Fill = 3,
65 Fill = 4, 81 Invalid = 4,
66 Invalid = 5
67 }; 82 };
68 83
69 static constexpr unsigned int GetFormatBpp(PixelFormat format) { 84 static constexpr unsigned int GetFormatBpp(PixelFormat format) {
70 if (format == PixelFormat::Invalid) 85 if (format == PixelFormat::Invalid)
71 return 0; 86 return 0;
72 87
73 constexpr std::array<unsigned int, 2> bpp_table = { 88 constexpr std::array<unsigned int, MaxPixelFormat> bpp_table = {
74 32, // RGBA8 89 32, // ABGR8
75 64, // DXT1 90 16, // B5G6R5
91 64, // DXT1
92 128, // DXT23
93 128, // DXT45
76 }; 94 };
77 95
78 ASSERT(static_cast<size_t>(format) < bpp_table.size()); 96 ASSERT(static_cast<size_t>(format) < bpp_table.size());
@@ -85,7 +103,7 @@ struct SurfaceParams {
85 static PixelFormat PixelFormatFromRenderTargetFormat(Tegra::RenderTargetFormat format) { 103 static PixelFormat PixelFormatFromRenderTargetFormat(Tegra::RenderTargetFormat format) {
86 switch (format) { 104 switch (format) {
87 case Tegra::RenderTargetFormat::RGBA8_UNORM: 105 case Tegra::RenderTargetFormat::RGBA8_UNORM:
88 return PixelFormat::RGBA8; 106 return PixelFormat::ABGR8;
89 default: 107 default:
90 NGLOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast<u32>(format)); 108 NGLOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast<u32>(format));
91 UNREACHABLE(); 109 UNREACHABLE();
@@ -95,7 +113,7 @@ struct SurfaceParams {
95 static PixelFormat PixelFormatFromGPUPixelFormat(Tegra::FramebufferConfig::PixelFormat format) { 113 static PixelFormat PixelFormatFromGPUPixelFormat(Tegra::FramebufferConfig::PixelFormat format) {
96 switch (format) { 114 switch (format) {
97 case Tegra::FramebufferConfig::PixelFormat::ABGR8: 115 case Tegra::FramebufferConfig::PixelFormat::ABGR8:
98 return PixelFormat::RGBA8; 116 return PixelFormat::ABGR8;
99 default: 117 default:
100 NGLOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast<u32>(format)); 118 NGLOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast<u32>(format));
101 UNREACHABLE(); 119 UNREACHABLE();
@@ -106,9 +124,67 @@ struct SurfaceParams {
106 // TODO(Subv): Properly implement this 124 // TODO(Subv): Properly implement this
107 switch (format) { 125 switch (format) {
108 case Tegra::Texture::TextureFormat::A8R8G8B8: 126 case Tegra::Texture::TextureFormat::A8R8G8B8:
109 return PixelFormat::RGBA8; 127 return PixelFormat::ABGR8;
128 case Tegra::Texture::TextureFormat::B5G6R5:
129 return PixelFormat::B5G6R5;
110 case Tegra::Texture::TextureFormat::DXT1: 130 case Tegra::Texture::TextureFormat::DXT1:
111 return PixelFormat::DXT1; 131 return PixelFormat::DXT1;
132 case Tegra::Texture::TextureFormat::DXT23:
133 return PixelFormat::DXT23;
134 case Tegra::Texture::TextureFormat::DXT45:
135 return PixelFormat::DXT45;
136 default:
137 NGLOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast<u32>(format));
138 UNREACHABLE();
139 }
140 }
141
142 static Tegra::Texture::TextureFormat TextureFormatFromPixelFormat(PixelFormat format) {
143 // TODO(Subv): Properly implement this
144 switch (format) {
145 case PixelFormat::ABGR8:
146 return Tegra::Texture::TextureFormat::A8R8G8B8;
147 case PixelFormat::B5G6R5:
148 return Tegra::Texture::TextureFormat::B5G6R5;
149 case PixelFormat::DXT1:
150 return Tegra::Texture::TextureFormat::DXT1;
151 case PixelFormat::DXT23:
152 return Tegra::Texture::TextureFormat::DXT23;
153 case PixelFormat::DXT45:
154 return Tegra::Texture::TextureFormat::DXT45;
155 default:
156 UNREACHABLE();
157 }
158 }
159
160 static ComponentType ComponentTypeFromTexture(Tegra::Texture::ComponentType type) {
161 // TODO(Subv): Implement more component types
162 switch (type) {
163 case Tegra::Texture::ComponentType::UNORM:
164 return ComponentType::UNorm;
165 default:
166 NGLOG_CRITICAL(HW_GPU, "Unimplemented component type={}", static_cast<u32>(type));
167 UNREACHABLE();
168 }
169 }
170
171 static ComponentType ComponentTypeFromRenderTarget(Tegra::RenderTargetFormat format) {
172 // TODO(Subv): Implement more render targets
173 switch (format) {
174 case Tegra::RenderTargetFormat::RGBA8_UNORM:
175 case Tegra::RenderTargetFormat::RGB10_A2_UNORM:
176 return ComponentType::UNorm;
177 default:
178 NGLOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast<u32>(format));
179 UNREACHABLE();
180 }
181 }
182
183 static ComponentType ComponentTypeFromGPUPixelFormat(
184 Tegra::FramebufferConfig::PixelFormat format) {
185 switch (format) {
186 case Tegra::FramebufferConfig::PixelFormat::ABGR8:
187 return ComponentType::UNorm;
112 default: 188 default:
113 NGLOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast<u32>(format)); 189 NGLOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast<u32>(format));
114 UNREACHABLE(); 190 UNREACHABLE();
@@ -119,8 +195,7 @@ struct SurfaceParams {
119 SurfaceType a_type = GetFormatType(pixel_format_a); 195 SurfaceType a_type = GetFormatType(pixel_format_a);
120 SurfaceType b_type = GetFormatType(pixel_format_b); 196 SurfaceType b_type = GetFormatType(pixel_format_b);
121 197
122 if ((a_type == SurfaceType::Color || a_type == SurfaceType::Texture) && 198 if (a_type == SurfaceType::ColorTexture && b_type == SurfaceType::ColorTexture) {
123 (b_type == SurfaceType::Color || b_type == SurfaceType::Texture)) {
124 return true; 199 return true;
125 } 200 }
126 201
@@ -136,12 +211,8 @@ struct SurfaceParams {
136 } 211 }
137 212
138 static SurfaceType GetFormatType(PixelFormat pixel_format) { 213 static SurfaceType GetFormatType(PixelFormat pixel_format) {
139 if ((unsigned int)pixel_format <= static_cast<unsigned int>(PixelFormat::RGBA8)) { 214 if (static_cast<size_t>(pixel_format) < MaxPixelFormat) {
140 return SurfaceType::Color; 215 return SurfaceType::ColorTexture;
141 }
142
143 if ((unsigned int)pixel_format <= static_cast<unsigned int>(PixelFormat::DXT1)) {
144 return SurfaceType::Texture;
145 } 216 }
146 217
147 // TODO(Subv): Implement the other formats 218 // TODO(Subv): Implement the other formats
@@ -213,11 +284,13 @@ struct SurfaceParams {
213 u32 width = 0; 284 u32 width = 0;
214 u32 height = 0; 285 u32 height = 0;
215 u32 stride = 0; 286 u32 stride = 0;
287 u32 block_height = 0;
216 u16 res_scale = 1; 288 u16 res_scale = 1;
217 289
218 bool is_tiled = false; 290 bool is_tiled = false;
219 PixelFormat pixel_format = PixelFormat::Invalid; 291 PixelFormat pixel_format = PixelFormat::Invalid;
220 SurfaceType type = SurfaceType::Invalid; 292 SurfaceType type = SurfaceType::Invalid;
293 ComponentType component_type = ComponentType::Invalid;
221}; 294};
222 295
223struct CachedSurface : SurfaceParams { 296struct CachedSurface : SurfaceParams {
diff --git a/src/video_core/renderer_opengl/gl_shader_gen.cpp b/src/video_core/renderer_opengl/gl_shader_gen.cpp
index 8b7f17601..254f6e2c3 100644
--- a/src/video_core/renderer_opengl/gl_shader_gen.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_gen.cpp
@@ -29,9 +29,15 @@ out gl_PerVertex {
29 29
30out vec4 position; 30out vec4 position;
31 31
32layout (std140) uniform vs_config {
33 vec4 viewport_flip;
34};
35
32void main() { 36void main() {
33 exec_shader(); 37 exec_shader();
34 38
39 // Viewport can be flipped, which is unsupported by glViewport
40 position.xy *= viewport_flip.xy;
35 gl_Position = position; 41 gl_Position = position;
36} 42}
37)"; 43)";
@@ -52,6 +58,10 @@ ProgramResult GenerateFragmentShader(const ShaderSetup& setup, const MaxwellFSCo
52in vec4 position; 58in vec4 position;
53out vec4 color; 59out vec4 color;
54 60
61layout (std140) uniform fs_config {
62 vec4 viewport_flip;
63};
64
55uniform sampler2D tex[32]; 65uniform sampler2D tex[32];
56 66
57void main() { 67void main() {
diff --git a/src/video_core/renderer_opengl/gl_shader_manager.cpp b/src/video_core/renderer_opengl/gl_shader_manager.cpp
index 85b838faa..17b3925a0 100644
--- a/src/video_core/renderer_opengl/gl_shader_manager.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_manager.cpp
@@ -53,6 +53,12 @@ void SetShaderSamplerBindings(GLuint shader) {
53 53
54} // namespace Impl 54} // namespace Impl
55 55
56void MaxwellUniformData::SetFromRegs(const Maxwell3D::State::ShaderStageInfo& shader_stage) {} 56void MaxwellUniformData::SetFromRegs(const Maxwell3D::State::ShaderStageInfo& shader_stage) {
57 const auto& regs = Core::System().GetInstance().GPU().Maxwell3D().regs;
58
59 // TODO(bunnei): Support more than one viewport
60 viewport_flip[0] = regs.viewport_transform[0].scale_x < 0.0 ? -1.0 : 1.0;
61 viewport_flip[1] = regs.viewport_transform[0].scale_y < 0.0 ? -1.0 : 1.0;
62}
57 63
58} // namespace GLShader 64} // namespace GLShader
diff --git a/src/video_core/renderer_opengl/gl_shader_manager.h b/src/video_core/renderer_opengl/gl_shader_manager.h
index be63320e0..e963b4b7e 100644
--- a/src/video_core/renderer_opengl/gl_shader_manager.h
+++ b/src/video_core/renderer_opengl/gl_shader_manager.h
@@ -30,10 +30,9 @@ void SetShaderSamplerBindings(GLuint shader);
30// Not following that rule will cause problems on some AMD drivers. 30// Not following that rule will cause problems on some AMD drivers.
31struct MaxwellUniformData { 31struct MaxwellUniformData {
32 void SetFromRegs(const Maxwell3D::State::ShaderStageInfo& shader_stage); 32 void SetFromRegs(const Maxwell3D::State::ShaderStageInfo& shader_stage);
33 // TODO(Subv): Use this for something. 33 alignas(16) GLvec4 viewport_flip;
34}; 34};
35// static_assert(sizeof(MaxwellUniformData) == 1024, "MaxwellUniformData structure size is 35static_assert(sizeof(MaxwellUniformData) == 16, "MaxwellUniformData structure size is incorrect");
36// incorrect");
37static_assert(sizeof(MaxwellUniformData) < 16384, 36static_assert(sizeof(MaxwellUniformData) < 16384,
38 "MaxwellUniformData structure must be less than 16kb as per the OpenGL spec"); 37 "MaxwellUniformData structure must be less than 16kb as per the OpenGL spec");
39 38
diff --git a/src/video_core/textures/decoders.cpp b/src/video_core/textures/decoders.cpp
index 2e87281eb..4df687786 100644
--- a/src/video_core/textures/decoders.cpp
+++ b/src/video_core/textures/decoders.cpp
@@ -48,31 +48,39 @@ u32 BytesPerPixel(TextureFormat format) {
48 case TextureFormat::DXT1: 48 case TextureFormat::DXT1:
49 // In this case a 'pixel' actually refers to a 4x4 tile. 49 // In this case a 'pixel' actually refers to a 4x4 tile.
50 return 8; 50 return 8;
51 case TextureFormat::DXT23:
52 case TextureFormat::DXT45:
53 // In this case a 'pixel' actually refers to a 4x4 tile.
54 return 16;
51 case TextureFormat::A8R8G8B8: 55 case TextureFormat::A8R8G8B8:
52 return 4; 56 return 4;
57 case TextureFormat::B5G6R5:
58 return 2;
53 default: 59 default:
54 UNIMPLEMENTED_MSG("Format not implemented"); 60 UNIMPLEMENTED_MSG("Format not implemented");
55 break; 61 break;
56 } 62 }
57} 63}
58 64
59std::vector<u8> UnswizzleTexture(VAddr address, TextureFormat format, u32 width, u32 height) { 65std::vector<u8> UnswizzleTexture(VAddr address, TextureFormat format, u32 width, u32 height,
66 u32 block_height) {
60 u8* data = Memory::GetPointer(address); 67 u8* data = Memory::GetPointer(address);
61 u32 bytes_per_pixel = BytesPerPixel(format); 68 u32 bytes_per_pixel = BytesPerPixel(format);
62 69
63 static constexpr u32 DefaultBlockHeight = 16;
64
65 std::vector<u8> unswizzled_data(width * height * bytes_per_pixel); 70 std::vector<u8> unswizzled_data(width * height * bytes_per_pixel);
66 71
67 switch (format) { 72 switch (format) {
68 case TextureFormat::DXT1: 73 case TextureFormat::DXT1:
69 // In the DXT1 format, each 4x4 tile is swizzled instead of just individual pixel values. 74 case TextureFormat::DXT23:
75 case TextureFormat::DXT45:
76 // In the DXT formats, each 4x4 tile is swizzled instead of just individual pixel values.
70 CopySwizzledData(width / 4, height / 4, bytes_per_pixel, bytes_per_pixel, data, 77 CopySwizzledData(width / 4, height / 4, bytes_per_pixel, bytes_per_pixel, data,
71 unswizzled_data.data(), true, DefaultBlockHeight); 78 unswizzled_data.data(), true, block_height);
72 break; 79 break;
73 case TextureFormat::A8R8G8B8: 80 case TextureFormat::A8R8G8B8:
81 case TextureFormat::B5G6R5:
74 CopySwizzledData(width, height, bytes_per_pixel, bytes_per_pixel, data, 82 CopySwizzledData(width, height, bytes_per_pixel, bytes_per_pixel, data,
75 unswizzled_data.data(), true, DefaultBlockHeight); 83 unswizzled_data.data(), true, block_height);
76 break; 84 break;
77 default: 85 default:
78 UNIMPLEMENTED_MSG("Format not implemented"); 86 UNIMPLEMENTED_MSG("Format not implemented");
@@ -89,7 +97,10 @@ std::vector<u8> DecodeTexture(const std::vector<u8>& texture_data, TextureFormat
89 // TODO(Subv): Implement. 97 // TODO(Subv): Implement.
90 switch (format) { 98 switch (format) {
91 case TextureFormat::DXT1: 99 case TextureFormat::DXT1:
100 case TextureFormat::DXT23:
101 case TextureFormat::DXT45:
92 case TextureFormat::A8R8G8B8: 102 case TextureFormat::A8R8G8B8:
103 case TextureFormat::B5G6R5:
93 // TODO(Subv): For the time being just forward the same data without any decoding. 104 // TODO(Subv): For the time being just forward the same data without any decoding.
94 rgba_data = texture_data; 105 rgba_data = texture_data;
95 break; 106 break;
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..86e45aa88 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"
@@ -14,6 +15,7 @@ namespace Texture {
14 15
15enum class TextureFormat : u32 { 16enum class TextureFormat : u32 {
16 A8R8G8B8 = 0x8, 17 A8R8G8B8 = 0x8,
18 B5G6R5 = 0x15,
17 DXT1 = 0x24, 19 DXT1 = 0x24,
18 DXT23 = 0x25, 20 DXT23 = 0x25,
19 DXT45 = 0x26, 21 DXT45 = 0x26,
@@ -57,6 +59,8 @@ union TextureHandle {
57static_assert(sizeof(TextureHandle) == 4, "TextureHandle has wrong size"); 59static_assert(sizeof(TextureHandle) == 4, "TextureHandle has wrong size");
58 60
59struct TICEntry { 61struct TICEntry {
62 static constexpr u32 DefaultBlockHeight = 16;
63
60 union { 64 union {
61 u32 raw; 65 u32 raw;
62 BitField<0, 7, TextureFormat> format; 66 BitField<0, 7, TextureFormat> format;
@@ -70,7 +74,12 @@ struct TICEntry {
70 BitField<0, 16, u32> address_high; 74 BitField<0, 16, u32> address_high;
71 BitField<21, 3, TICHeaderVersion> header_version; 75 BitField<21, 3, TICHeaderVersion> header_version;
72 }; 76 };
73 INSERT_PADDING_BYTES(4); 77 union {
78 BitField<3, 3, u32> block_height;
79
80 // High 16 bits of the pitch value
81 BitField<0, 16, u32> pitch_high;
82 };
74 union { 83 union {
75 BitField<0, 16, u32> width_minus_1; 84 BitField<0, 16, u32> width_minus_1;
76 BitField<23, 4, TextureType> texture_type; 85 BitField<23, 4, TextureType> texture_type;
@@ -82,6 +91,13 @@ struct TICEntry {
82 return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) | address_low); 91 return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) | address_low);
83 } 92 }
84 93
94 u32 Pitch() const {
95 ASSERT(header_version == TICHeaderVersion::Pitch ||
96 header_version == TICHeaderVersion::PitchColorKey);
97 // The pitch value is 21 bits, and is 32B aligned.
98 return pitch_high << 5;
99 }
100
85 u32 Width() const { 101 u32 Width() const {
86 return width_minus_1 + 1; 102 return width_minus_1 + 1;
87 } 103 }
@@ -90,6 +106,13 @@ struct TICEntry {
90 return height_minus_1 + 1; 106 return height_minus_1 + 1;
91 } 107 }
92 108
109 u32 BlockHeight() const {
110 ASSERT(header_version == TICHeaderVersion::BlockLinear ||
111 header_version == TICHeaderVersion::BlockLinearColorKey);
112 // The block height is stored in log2 format.
113 return 1 << block_height;
114 }
115
93 bool IsTiled() const { 116 bool IsTiled() const {
94 return header_version == TICHeaderVersion::BlockLinear || 117 return header_version == TICHeaderVersion::BlockLinear ||
95 header_version == TICHeaderVersion::BlockLinearColorKey; 118 header_version == TICHeaderVersion::BlockLinearColorKey;