From c079cf4eece8ca84c3786c8b5433ae9fca8f585f Mon Sep 17 00:00:00 2001
From: Subv <subv2112@gmail.com>
Date: Sat, 21 Apr 2018 17:32:25 -0500
Subject: [PATCH] GPU: Implement the A2BGR10 texture format.

---
 .../renderer_opengl/gl_rasterizer_cache.cpp          |  8 +++++---
 src/video_core/renderer_opengl/gl_rasterizer_cache.h | 12 +++++++++---
 src/video_core/textures/decoders.cpp                 |  3 +++
 src/video_core/textures/texture.h                    |  1 +
 4 files changed, 18 insertions(+), 6 deletions(-)

diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
index ced2b82479..7410471cc6 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
@@ -49,6 +49,7 @@ struct FormatTuple {
 static constexpr std::array<FormatTuple, SurfaceParams::MaxPixelFormat> tex_format_tuples = {{
     {GL_RGBA8, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, false, 1},                     // ABGR8
     {GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5_REV, false, 1},                        // B5G6R5
+    {GL_RGB10_A2, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, false, 1},               // A2B10G10R10
     {GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_RGB, GL_UNSIGNED_INT_8_8_8_8, true, 16},   // DXT1
     {GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, true, 16}, // DXT23
     {GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, true, 16}, // DXT45
@@ -104,9 +105,9 @@ void MortonCopy(u32 stride, u32 block_height, u32 height, u8* gl_buffer, VAddr b
 static constexpr std::array<void (*)(u32, u32, u32, u8*, VAddr, VAddr, VAddr),
                             SurfaceParams::MaxPixelFormat>
     morton_to_gl_fns = {
-        MortonCopy<true, PixelFormat::ABGR8>, MortonCopy<true, PixelFormat::B5G6R5>,
-        MortonCopy<true, PixelFormat::DXT1>,  MortonCopy<true, PixelFormat::DXT23>,
-        MortonCopy<true, PixelFormat::DXT45>,
+        MortonCopy<true, PixelFormat::ABGR8>,       MortonCopy<true, PixelFormat::B5G6R5>,
+        MortonCopy<true, PixelFormat::A2B10G10R10>, MortonCopy<true, PixelFormat::DXT1>,
+        MortonCopy<true, PixelFormat::DXT23>,       MortonCopy<true, PixelFormat::DXT45>,
 };
 
 static constexpr std::array<void (*)(u32, u32, u32, u8*, VAddr, VAddr, VAddr),
@@ -114,6 +115,7 @@ static constexpr std::array<void (*)(u32, u32, u32, u8*, VAddr, VAddr, VAddr),
     gl_to_morton_fns = {
         MortonCopy<false, PixelFormat::ABGR8>,
         MortonCopy<false, PixelFormat::B5G6R5>,
+        MortonCopy<false, PixelFormat::A2B10G10R10>,
         // TODO(Subv): Swizzling the DXT1/DXT23/DXT45 formats is not yet supported
         nullptr,
         nullptr,
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.h b/src/video_core/renderer_opengl/gl_rasterizer_cache.h
index 6861efe165..e4cb3390fe 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer_cache.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.h
@@ -54,9 +54,10 @@ struct SurfaceParams {
     enum class PixelFormat {
         ABGR8 = 0,
         B5G6R5 = 1,
-        DXT1 = 2,
-        DXT23 = 3,
-        DXT45 = 4,
+        A2B10G10R10 = 2,
+        DXT1 = 3,
+        DXT23 = 4,
+        DXT45 = 5,
 
         Max,
         Invalid = 255,
@@ -88,6 +89,7 @@ struct SurfaceParams {
         constexpr std::array<unsigned int, MaxPixelFormat> bpp_table = {
             32,  // ABGR8
             16,  // B5G6R5
+            32,  // A2B10G10R10
             64,  // DXT1
             128, // DXT23
             128, // DXT45
@@ -127,6 +129,8 @@ struct SurfaceParams {
             return PixelFormat::ABGR8;
         case Tegra::Texture::TextureFormat::B5G6R5:
             return PixelFormat::B5G6R5;
+        case Tegra::Texture::TextureFormat::A2B10G10R10:
+            return PixelFormat::A2B10G10R10;
         case Tegra::Texture::TextureFormat::DXT1:
             return PixelFormat::DXT1;
         case Tegra::Texture::TextureFormat::DXT23:
@@ -146,6 +150,8 @@ struct SurfaceParams {
             return Tegra::Texture::TextureFormat::A8R8G8B8;
         case PixelFormat::B5G6R5:
             return Tegra::Texture::TextureFormat::B5G6R5;
+        case PixelFormat::A2B10G10R10:
+            return Tegra::Texture::TextureFormat::A2B10G10R10;
         case PixelFormat::DXT1:
             return Tegra::Texture::TextureFormat::DXT1;
         case PixelFormat::DXT23:
diff --git a/src/video_core/textures/decoders.cpp b/src/video_core/textures/decoders.cpp
index 4df6877860..e0509f0ce2 100644
--- a/src/video_core/textures/decoders.cpp
+++ b/src/video_core/textures/decoders.cpp
@@ -53,6 +53,7 @@ u32 BytesPerPixel(TextureFormat format) {
         // In this case a 'pixel' actually refers to a 4x4 tile.
         return 16;
     case TextureFormat::A8R8G8B8:
+    case TextureFormat::A2B10G10R10:
         return 4;
     case TextureFormat::B5G6R5:
         return 2;
@@ -78,6 +79,7 @@ std::vector<u8> UnswizzleTexture(VAddr address, TextureFormat format, u32 width,
                          unswizzled_data.data(), true, block_height);
         break;
     case TextureFormat::A8R8G8B8:
+    case TextureFormat::A2B10G10R10:
     case TextureFormat::B5G6R5:
         CopySwizzledData(width, height, bytes_per_pixel, bytes_per_pixel, data,
                          unswizzled_data.data(), true, block_height);
@@ -100,6 +102,7 @@ std::vector<u8> DecodeTexture(const std::vector<u8>& texture_data, TextureFormat
     case TextureFormat::DXT23:
     case TextureFormat::DXT45:
     case TextureFormat::A8R8G8B8:
+    case TextureFormat::A2B10G10R10:
     case TextureFormat::B5G6R5:
         // TODO(Subv): For the time being just forward the same data without any decoding.
         rgba_data = texture_data;
diff --git a/src/video_core/textures/texture.h b/src/video_core/textures/texture.h
index 86e45aa882..dc004d3614 100644
--- a/src/video_core/textures/texture.h
+++ b/src/video_core/textures/texture.h
@@ -15,6 +15,7 @@ namespace Texture {
 
 enum class TextureFormat : u32 {
     A8R8G8B8 = 0x8,
+    A2B10G10R10 = 0x9,
     B5G6R5 = 0x15,
     DXT1 = 0x24,
     DXT23 = 0x25,