diff options
| -rw-r--r-- | src/video_core/engines/maxwell_3d.h | 7 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.cpp | 13 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer_cache.cpp | 91 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer_cache.h | 80 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_state.cpp | 13 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_state.h | 14 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/renderer_opengl.cpp | 14 | ||||
| -rw-r--r-- | src/video_core/textures/texture.h | 5 | 
8 files changed, 197 insertions, 40 deletions
| diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h index d6978162a..443affc36 100644 --- a/src/video_core/engines/maxwell_3d.h +++ b/src/video_core/engines/maxwell_3d.h @@ -723,7 +723,11 @@ public:                  StencilOp stencil_back_op_zpass;                  ComparisonOp stencil_back_func_func; -                INSERT_PADDING_WORDS(0x17); +                INSERT_PADDING_WORDS(0x4); + +                u32 framebuffer_srgb; + +                INSERT_PADDING_WORDS(0x12);                  union {                      BitField<2, 1, u32> coord_origin; @@ -1086,6 +1090,7 @@ ASSERT_REG_POSITION(stencil_back_op_fail, 0x566);  ASSERT_REG_POSITION(stencil_back_op_zfail, 0x567);  ASSERT_REG_POSITION(stencil_back_op_zpass, 0x568);  ASSERT_REG_POSITION(stencil_back_func_func, 0x569); +ASSERT_REG_POSITION(framebuffer_srgb, 0x56E);  ASSERT_REG_POSITION(point_coord_replace, 0x581);  ASSERT_REG_POSITION(code_address, 0x582);  ASSERT_REG_POSITION(draw, 0x585); diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index cd4216c4e..cb180b93c 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp @@ -418,6 +418,7 @@ void RasterizerOpenGL::ConfigureFramebuffers(bool using_color_fb, bool using_dep      // Bind the framebuffer surfaces      state.draw.draw_framebuffer = framebuffer.handle;      state.Apply(); +    state.framebuffer_srgb.enabled = regs.framebuffer_srgb != 0;      if (using_color_fb) {          if (single_color_target) { @@ -429,6 +430,9 @@ void RasterizerOpenGL::ConfigureFramebuffers(bool using_color_fb, bool using_dep                  // Assume that a surface will be written to if it is used as a framebuffer, even if                  // the shader doesn't actually write to it.                  color_surface->MarkAsModified(true, res_cache); +                // Workaround for and issue in nvidia drivers +                // https://devtalk.nvidia.com/default/topic/776591/opengl/gl_framebuffer_srgb-functions-incorrectly/ +                state.framebuffer_srgb.enabled |= color_surface->GetSurfaceParams().srgb_conversion;              }              glFramebufferTexture2D( @@ -446,6 +450,11 @@ void RasterizerOpenGL::ConfigureFramebuffers(bool using_color_fb, bool using_dep                      // Assume that a surface will be written to if it is used as a framebuffer, even                      // if the shader doesn't actually write to it.                      color_surface->MarkAsModified(true, res_cache); +                    // Enable sRGB only for supported formats +                    // Workaround for and issue in nvidia drivers +                    // https://devtalk.nvidia.com/default/topic/776591/opengl/gl_framebuffer_srgb-functions-incorrectly/ +                    state.framebuffer_srgb.enabled |= +                        color_surface->GetSurfaceParams().srgb_conversion;                  }                  buffers[index] = GL_COLOR_ATTACHMENT0 + regs.rt_control.GetMap(index); @@ -537,7 +546,9 @@ void RasterizerOpenGL::Clear() {      ConfigureFramebuffers(use_color, use_depth || use_stencil, false,                            regs.clear_buffers.RT.Value()); - +    // Copy the sRGB setting to the clear state to avoid problem with +    // specific driver implementations +    clear_state.framebuffer_srgb.enabled = state.framebuffer_srgb.enabled;      clear_state.Apply();      if (use_color) { diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp index 04a024137..b057e2efa 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp @@ -40,6 +40,10 @@ static bool IsPixelFormatASTC(PixelFormat format) {      case PixelFormat::ASTC_2D_5X4:      case PixelFormat::ASTC_2D_8X8:      case PixelFormat::ASTC_2D_8X5: +    case PixelFormat::ASTC_2D_4X4_SRGB: +    case PixelFormat::ASTC_2D_5X4_SRGB: +    case PixelFormat::ASTC_2D_8X8_SRGB: +    case PixelFormat::ASTC_2D_8X5_SRGB:          return true;      default:          return false; @@ -56,6 +60,14 @@ static std::pair<u32, u32> GetASTCBlockSize(PixelFormat format) {          return {8, 8};      case PixelFormat::ASTC_2D_8X5:          return {8, 5}; +    case PixelFormat::ASTC_2D_4X4_SRGB: +        return {4, 4}; +    case PixelFormat::ASTC_2D_5X4_SRGB: +        return {5, 4}; +    case PixelFormat::ASTC_2D_8X8_SRGB: +        return {8, 8}; +    case PixelFormat::ASTC_2D_8X5_SRGB: +        return {8, 5};      default:          LOG_CRITICAL(HW_GPU, "Unhandled format: {}", static_cast<u32>(format));          UNREACHABLE(); @@ -108,8 +120,9 @@ std::size_t SurfaceParams::InnerMemorySize(bool layer_only) const {      params.block_width = params.is_tiled ? config.tic.BlockWidth() : 0,      params.block_height = params.is_tiled ? config.tic.BlockHeight() : 0,      params.block_depth = params.is_tiled ? config.tic.BlockDepth() : 0, -    params.pixel_format = -        PixelFormatFromTextureFormat(config.tic.format, config.tic.r_type.Value()); +    params.srgb_conversion = config.tic.IsSrgbConversionEnabled(); +    params.pixel_format = PixelFormatFromTextureFormat(config.tic.format, config.tic.r_type.Value(), +                                                       params.srgb_conversion);      params.component_type = ComponentTypeFromTexture(config.tic.r_type.Value());      params.type = GetFormatType(params.pixel_format);      params.width = Common::AlignUp(config.tic.Width(), GetCompressionFactor(params.pixel_format)); @@ -166,6 +179,8 @@ std::size_t SurfaceParams::InnerMemorySize(bool layer_only) const {      params.block_height = 1 << config.memory_layout.block_height;      params.block_depth = 1 << config.memory_layout.block_depth;      params.pixel_format = PixelFormatFromRenderTargetFormat(config.format); +    params.srgb_conversion = config.format == Tegra::RenderTargetFormat::BGRA8_SRGB || +                             config.format == Tegra::RenderTargetFormat::RGBA8_SRGB;      params.component_type = ComponentTypeFromRenderTarget(config.format);      params.type = GetFormatType(params.pixel_format);      params.width = config.width; @@ -201,6 +216,7 @@ std::size_t SurfaceParams::InnerMemorySize(bool layer_only) const {      params.pixel_format = PixelFormatFromDepthFormat(format);      params.component_type = ComponentTypeFromDepthFormat(format);      params.type = GetFormatType(params.pixel_format); +    params.srgb_conversion = false;      params.width = zeta_width;      params.height = zeta_height;      params.unaligned_height = zeta_height; @@ -224,6 +240,8 @@ std::size_t SurfaceParams::InnerMemorySize(bool layer_only) const {      params.block_height = params.is_tiled ? std::min(config.BlockHeight(), 32U) : 0,      params.block_depth = params.is_tiled ? std::min(config.BlockDepth(), 32U) : 0,      params.pixel_format = PixelFormatFromRenderTargetFormat(config.format); +    params.srgb_conversion = config.format == Tegra::RenderTargetFormat::BGRA8_SRGB || +                             config.format == Tegra::RenderTargetFormat::RGBA8_SRGB;      params.component_type = ComponentTypeFromRenderTarget(config.format);      params.type = GetFormatType(params.pixel_format);      params.width = config.width; @@ -289,14 +307,29 @@ static constexpr std::array<FormatTuple, SurfaceParams::MaxPixelFormat> tex_form      {GL_RG16I, GL_RG_INTEGER, GL_SHORT, ComponentType::SInt, false},           // RG16I      {GL_RG16_SNORM, GL_RG, GL_SHORT, ComponentType::SNorm, false},             // RG16S      {GL_RGB32F, GL_RGB, GL_FLOAT, ComponentType::Float, false},                // RGB32F -    {GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, ComponentType::UNorm, false}, // SRGBA8 -    {GL_RG8, GL_RG, GL_UNSIGNED_BYTE, ComponentType::UNorm, false},                       // RG8U -    {GL_RG8, GL_RG, GL_BYTE, ComponentType::SNorm, false},                                // RG8S -    {GL_RG32UI, GL_RG_INTEGER, GL_UNSIGNED_INT, ComponentType::UInt, false},              // RG32UI -    {GL_R32UI, GL_RED_INTEGER, GL_UNSIGNED_INT, ComponentType::UInt, false},              // R32UI -    {GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_8X8 -    {GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_8X5 -    {GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_5X4 +    {GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, ComponentType::UNorm, +     false},                                                                   // RGBA8_SRGB +    {GL_RG8, GL_RG, GL_UNSIGNED_BYTE, ComponentType::UNorm, false},            // RG8U +    {GL_RG8, GL_RG, GL_BYTE, ComponentType::SNorm, false},                     // RG8S +    {GL_RG32UI, GL_RG_INTEGER, GL_UNSIGNED_INT, ComponentType::UInt, false},   // RG32UI +    {GL_R32UI, GL_RED_INTEGER, GL_UNSIGNED_INT, ComponentType::UInt, false},   // R32UI +    {GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false},        // ASTC_2D_8X8 +    {GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false},        // ASTC_2D_8X5 +    {GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false},        // ASTC_2D_5X4 +    {GL_SRGB8_ALPHA8, GL_BGRA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // BGRA8 +    // Compressed sRGB formats +    {GL_COMPRESSED_SRGB_S3TC_DXT1_EXT, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, ComponentType::UNorm, +     true}, // DXT1_SRGB +    {GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, ComponentType::UNorm, +     true}, // DXT23_SRGB +    {GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, ComponentType::UNorm, +     true}, // DXT45_SRGB +    {GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, +     ComponentType::UNorm, true},                                              // BC7U_SRGB +    {GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_4X4_SRGB +    {GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_8X8_SRGB +    {GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_8X5_SRGB +    {GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_5X4_SRGB      // Depth formats      {GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT, ComponentType::Float, false}, // Z32F @@ -361,6 +394,10 @@ static bool IsFormatBCn(PixelFormat format) {      case PixelFormat::BC7U:      case PixelFormat::BC6H_UF16:      case PixelFormat::BC6H_SF16: +    case PixelFormat::DXT1_SRGB: +    case PixelFormat::DXT23_SRGB: +    case PixelFormat::DXT45_SRGB: +    case PixelFormat::BC7U_SRGB:          return true;      }      return false; @@ -432,7 +469,7 @@ static constexpr GLConversionArray morton_to_gl_fns = {          MortonCopy<true, PixelFormat::RG16I>,          MortonCopy<true, PixelFormat::RG16S>,          MortonCopy<true, PixelFormat::RGB32F>, -        MortonCopy<true, PixelFormat::SRGBA8>, +        MortonCopy<true, PixelFormat::RGBA8_SRGB>,          MortonCopy<true, PixelFormat::RG8U>,          MortonCopy<true, PixelFormat::RG8S>,          MortonCopy<true, PixelFormat::RG32UI>, @@ -440,6 +477,15 @@ static constexpr GLConversionArray morton_to_gl_fns = {          MortonCopy<true, PixelFormat::ASTC_2D_8X8>,          MortonCopy<true, PixelFormat::ASTC_2D_8X5>,          MortonCopy<true, PixelFormat::ASTC_2D_5X4>, +        MortonCopy<true, PixelFormat::BGRA8_SRGB>, +        MortonCopy<true, PixelFormat::DXT1_SRGB>, +        MortonCopy<true, PixelFormat::DXT23_SRGB>, +        MortonCopy<true, PixelFormat::DXT45_SRGB>, +        MortonCopy<true, PixelFormat::BC7U_SRGB>, +        MortonCopy<true, PixelFormat::ASTC_2D_4X4_SRGB>, +        MortonCopy<true, PixelFormat::ASTC_2D_8X8_SRGB>, +        MortonCopy<true, PixelFormat::ASTC_2D_8X5_SRGB>, +        MortonCopy<true, PixelFormat::ASTC_2D_5X4_SRGB>,          MortonCopy<true, PixelFormat::Z32F>,          MortonCopy<true, PixelFormat::Z16>,          MortonCopy<true, PixelFormat::Z24S8>, @@ -491,7 +537,7 @@ static constexpr GLConversionArray gl_to_morton_fns = {          MortonCopy<false, PixelFormat::RG16I>,          MortonCopy<false, PixelFormat::RG16S>,          MortonCopy<false, PixelFormat::RGB32F>, -        MortonCopy<false, PixelFormat::SRGBA8>, +        MortonCopy<false, PixelFormat::RGBA8_SRGB>,          MortonCopy<false, PixelFormat::RG8U>,          MortonCopy<false, PixelFormat::RG8S>,          MortonCopy<false, PixelFormat::RG32UI>, @@ -499,6 +545,15 @@ static constexpr GLConversionArray gl_to_morton_fns = {          nullptr,          nullptr,          nullptr, +        MortonCopy<false, PixelFormat::BGRA8_SRGB>, +        MortonCopy<false, PixelFormat::DXT1_SRGB>, +        MortonCopy<false, PixelFormat::DXT23_SRGB>, +        MortonCopy<false, PixelFormat::DXT45_SRGB>, +        MortonCopy<false, PixelFormat::BC7U_SRGB>, +        nullptr, +        nullptr, +        nullptr, +        nullptr,          MortonCopy<false, PixelFormat::Z32F>,          MortonCopy<false, PixelFormat::Z16>,          MortonCopy<false, PixelFormat::Z24S8>, @@ -546,6 +601,8 @@ static bool BlitSurface(const Surface& src_surface, const Surface& dst_surface,      OpenGLState state;      state.draw.read_framebuffer = read_fb_handle;      state.draw.draw_framebuffer = draw_fb_handle; +    // Set sRGB enabled if the destination surfaces need it +    state.framebuffer_srgb.enabled = dst_params.srgb_conversion;      state.Apply();      u32 buffers{}; @@ -881,7 +938,11 @@ static void ConvertFormatAsNeeded_LoadGLBuffer(std::vector<u8>& data, PixelForma      case PixelFormat::ASTC_2D_4X4:      case PixelFormat::ASTC_2D_8X8:      case PixelFormat::ASTC_2D_8X5: -    case PixelFormat::ASTC_2D_5X4: { +    case PixelFormat::ASTC_2D_5X4: +    case PixelFormat::ASTC_2D_4X4_SRGB: +    case PixelFormat::ASTC_2D_8X8_SRGB: +    case PixelFormat::ASTC_2D_8X5_SRGB: +    case PixelFormat::ASTC_2D_5X4_SRGB: {          // Convert ASTC pixel formats to RGBA8, as most desktop GPUs do not support ASTC.          u32 block_width{};          u32 block_height{}; @@ -913,7 +974,9 @@ static void ConvertFormatAsNeeded_FlushGLBuffer(std::vector<u8>& data, PixelForm      case PixelFormat::G8R8U:      case PixelFormat::G8R8S:      case PixelFormat::ASTC_2D_4X4: -    case PixelFormat::ASTC_2D_8X8: { +    case PixelFormat::ASTC_2D_8X8: +    case PixelFormat::ASTC_2D_4X4_SRGB: +    case PixelFormat::ASTC_2D_8X8_SRGB: {          LOG_CRITICAL(HW_GPU, "Conversion of format {} after texture flushing is not implemented",                       static_cast<u32>(pixel_format));          UNREACHABLE(); diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.h b/src/video_core/renderer_opengl/gl_rasterizer_cache.h index 181acfc68..b4701a616 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.h +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.h @@ -69,7 +69,7 @@ struct SurfaceParams {          RG16I = 37,          RG16S = 38,          RGB32F = 39, -        SRGBA8 = 40, +        RGBA8_SRGB = 40,          RG8U = 41,          RG8S = 42,          RG32UI = 43, @@ -77,19 +77,28 @@ struct SurfaceParams {          ASTC_2D_8X8 = 45,          ASTC_2D_8X5 = 46,          ASTC_2D_5X4 = 47, +        BGRA8_SRGB = 48, +        DXT1_SRGB = 49, +        DXT23_SRGB = 50, +        DXT45_SRGB = 51, +        BC7U_SRGB = 52, +        ASTC_2D_4X4_SRGB = 53, +        ASTC_2D_8X8_SRGB = 54, +        ASTC_2D_8X5_SRGB = 55, +        ASTC_2D_5X4_SRGB = 56,          MaxColorFormat,          // Depth formats -        Z32F = 48, -        Z16 = 49, +        Z32F = 57, +        Z16 = 58,          MaxDepthFormat,          // DepthStencil formats -        Z24S8 = 50, -        S8Z24 = 51, -        Z32FS8 = 52, +        Z24S8 = 59, +        S8Z24 = 60, +        Z32FS8 = 61,          MaxDepthStencilFormat, @@ -236,7 +245,7 @@ struct SurfaceParams {              1, // RG16I              1, // RG16S              1, // RGB32F -            1, // SRGBA8 +            1, // RGBA8_SRGB              1, // RG8U              1, // RG8S              1, // RG32UI @@ -244,6 +253,15 @@ struct SurfaceParams {              4, // ASTC_2D_8X8              4, // ASTC_2D_8X5              4, // ASTC_2D_5X4 +            1, // BGRA8_SRGB +            4, // DXT1_SRGB +            4, // DXT23_SRGB +            4, // DXT45_SRGB +            4, // BC7U_SRGB +            4, // ASTC_2D_4X4_SRGB +            4, // ASTC_2D_8X8_SRGB +            4, // ASTC_2D_8X5_SRGB +            4, // ASTC_2D_5X4_SRGB              1, // Z32F              1, // Z16              1, // Z24S8 @@ -299,7 +317,7 @@ struct SurfaceParams {              1, // RG16I              1, // RG16S              1, // RGB32F -            1, // SRGBA8 +            1, // RGBA8_SRGB              1, // RG8U              1, // RG8S              1, // RG32UI @@ -307,6 +325,15 @@ struct SurfaceParams {              8, // ASTC_2D_8X8              5, // ASTC_2D_8X5              4, // ASTC_2D_5X4 +            1, // BGRA8_SRGB +            4, // DXT1_SRGB +            4, // DXT23_SRGB +            4, // DXT45_SRGB +            4, // BC7U_SRGB +            4, // ASTC_2D_4X4_SRGB +            8, // ASTC_2D_8X8_SRGB +            5, // ASTC_2D_8X5_SRGB +            4, // ASTC_2D_5X4_SRGB              1, // Z32F              1, // Z16              1, // Z24S8 @@ -362,7 +389,7 @@ struct SurfaceParams {              32,  // RG16I              32,  // RG16S              96,  // RGB32F -            32,  // SRGBA8 +            32,  // RGBA8_SRGB              16,  // RG8U              16,  // RG8S              64,  // RG32UI @@ -370,6 +397,15 @@ struct SurfaceParams {              16,  // ASTC_2D_8X8              32,  // ASTC_2D_8X5              32,  // ASTC_2D_5X4 +            32,  // BGRA8_SRGB +            64,  // DXT1_SRGB +            128, // DXT23_SRGB +            128, // DXT45_SRGB +            128, // BC7U +            32,  // ASTC_2D_4X4_SRGB +            16,  // ASTC_2D_8X8_SRGB +            32,  // ASTC_2D_8X5_SRGB +            32,  // ASTC_2D_5X4_SRGB              32,  // Z32F              16,  // Z16              32,  // Z24S8 @@ -408,6 +444,7 @@ struct SurfaceParams {          // TODO (Hexagon12): Converting SRGBA to RGBA is a hack and doesn't completely correct the          // gamma.          case Tegra::RenderTargetFormat::RGBA8_SRGB: +            return PixelFormat::RGBA8_SRGB;          case Tegra::RenderTargetFormat::RGBA8_UNORM:              return PixelFormat::ABGR8U;          case Tegra::RenderTargetFormat::RGBA8_SNORM: @@ -415,6 +452,7 @@ struct SurfaceParams {          case Tegra::RenderTargetFormat::RGBA8_UINT:              return PixelFormat::ABGR8UI;          case Tegra::RenderTargetFormat::BGRA8_SRGB: +            return PixelFormat::BGRA8_SRGB;          case Tegra::RenderTargetFormat::BGRA8_UNORM:              return PixelFormat::BGRA8;          case Tegra::RenderTargetFormat::RGB10_A2_UNORM: @@ -478,10 +516,14 @@ struct SurfaceParams {      }      static PixelFormat PixelFormatFromTextureFormat(Tegra::Texture::TextureFormat format, -                                                    Tegra::Texture::ComponentType component_type) { +                                                    Tegra::Texture::ComponentType component_type, +                                                    bool is_srgb) {          // TODO(Subv): Properly implement this          switch (format) {          case Tegra::Texture::TextureFormat::A8R8G8B8: +            if (is_srgb) { +                return PixelFormat::RGBA8_SRGB; +            }              switch (component_type) {              case Tegra::Texture::ComponentType::UNORM:                  return PixelFormat::ABGR8U; @@ -616,11 +658,11 @@ struct SurfaceParams {          case Tegra::Texture::TextureFormat::Z24S8:              return PixelFormat::Z24S8;          case Tegra::Texture::TextureFormat::DXT1: -            return PixelFormat::DXT1; +            return is_srgb ? PixelFormat::DXT1_SRGB : PixelFormat::DXT1;          case Tegra::Texture::TextureFormat::DXT23: -            return PixelFormat::DXT23; +            return is_srgb ? PixelFormat::DXT23_SRGB : PixelFormat::DXT23;          case Tegra::Texture::TextureFormat::DXT45: -            return PixelFormat::DXT45; +            return is_srgb ? PixelFormat::DXT45_SRGB : PixelFormat::DXT45;          case Tegra::Texture::TextureFormat::DXN1:              return PixelFormat::DXN1;          case Tegra::Texture::TextureFormat::DXN2: @@ -634,19 +676,19 @@ struct SurfaceParams {                           static_cast<u32>(component_type));              UNREACHABLE();          case Tegra::Texture::TextureFormat::BC7U: -            return PixelFormat::BC7U; +            return is_srgb ? PixelFormat::BC7U_SRGB : PixelFormat::BC7U;          case Tegra::Texture::TextureFormat::BC6H_UF16:              return PixelFormat::BC6H_UF16;          case Tegra::Texture::TextureFormat::BC6H_SF16:              return PixelFormat::BC6H_SF16;          case Tegra::Texture::TextureFormat::ASTC_2D_4X4: -            return PixelFormat::ASTC_2D_4X4; +            return is_srgb ? PixelFormat::ASTC_2D_4X4_SRGB : PixelFormat::ASTC_2D_4X4;          case Tegra::Texture::TextureFormat::ASTC_2D_5X4: -            return PixelFormat::ASTC_2D_5X4; +            return is_srgb ? PixelFormat::ASTC_2D_5X4_SRGB : PixelFormat::ASTC_2D_5X4;          case Tegra::Texture::TextureFormat::ASTC_2D_8X8: -            return PixelFormat::ASTC_2D_8X8; +            return is_srgb ? PixelFormat::ASTC_2D_8X8_SRGB : PixelFormat::ASTC_2D_8X8;          case Tegra::Texture::TextureFormat::ASTC_2D_8X5: -            return PixelFormat::ASTC_2D_8X5; +            return is_srgb ? PixelFormat::ASTC_2D_8X5_SRGB : PixelFormat::ASTC_2D_8X5;          case Tegra::Texture::TextureFormat::R16_G16:              switch (component_type) {              case Tegra::Texture::ComponentType::FLOAT: @@ -881,7 +923,7 @@ struct SurfaceParams {      SurfaceTarget target;      u32 max_mip_level;      bool is_layered; - +    bool srgb_conversion;      // Parameters used for caching      VAddr addr;      Tegra::GPUVAddr gpu_addr; diff --git a/src/video_core/renderer_opengl/gl_state.cpp b/src/video_core/renderer_opengl/gl_state.cpp index f9d41ca24..d8a43cc94 100644 --- a/src/video_core/renderer_opengl/gl_state.cpp +++ b/src/video_core/renderer_opengl/gl_state.cpp @@ -11,9 +11,10 @@  namespace OpenGL {  OpenGLState OpenGLState::cur_state; - +bool OpenGLState::s_rgb_used;  OpenGLState::OpenGLState() {      // These all match default OpenGL values +    framebuffer_srgb.enabled = false;      cull.enabled = false;      cull.mode = GL_BACK;      cull.front_face = GL_CCW; @@ -89,6 +90,16 @@ OpenGLState::OpenGLState() {  }  void OpenGLState::Apply() const { +    // sRGB +    if (framebuffer_srgb.enabled != cur_state.framebuffer_srgb.enabled) { +        if (framebuffer_srgb.enabled) { +            // Track if sRGB is used +            s_rgb_used = true; +            glEnable(GL_FRAMEBUFFER_SRGB); +        } else { +            glDisable(GL_FRAMEBUFFER_SRGB); +        } +    }      // Culling      if (cull.enabled != cur_state.cull.enabled) {          if (cull.enabled) { diff --git a/src/video_core/renderer_opengl/gl_state.h b/src/video_core/renderer_opengl/gl_state.h index 4334b0d35..9e2c573b5 100644 --- a/src/video_core/renderer_opengl/gl_state.h +++ b/src/video_core/renderer_opengl/gl_state.h @@ -36,6 +36,10 @@ constexpr TextureUnit ProcTexDiffLUT{9};  class OpenGLState {  public:      struct { +        bool enabled; // GL_FRAMEBUFFER_SRGB +    } framebuffer_srgb; + +    struct {          bool enabled;      // GL_CULL_FACE          GLenum mode;       // GL_CULL_FACE_MODE          GLenum front_face; // GL_FRONT_FACE @@ -161,7 +165,12 @@ public:      static OpenGLState GetCurState() {          return cur_state;      } - +    static bool GetsRGBUsed() { +        return s_rgb_used; +    } +    static void ClearsRGBUsed() { +        s_rgb_used = false; +    }      /// Apply this state as the current OpenGL state      void Apply() const; @@ -176,6 +185,9 @@ public:  private:      static OpenGLState cur_state; +    // Workaround for sRGB problems caused by +    // QT not supporting srgb output +    static bool s_rgb_used;  };  } // namespace OpenGL diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index 96d916b07..90b68943d 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp @@ -283,7 +283,8 @@ void RendererOpenGL::CreateRasterizer() {      if (rasterizer) {          return;      } - +    // Initialize sRGB Usage +    OpenGLState::ClearsRGBUsed();      rasterizer = std::make_unique<RasterizerOpenGL>(render_window, screen_info);  } @@ -356,13 +357,20 @@ void RendererOpenGL::DrawScreenTriangles(const ScreenInfo& screen_info, float x,      state.texture_units[0].texture = screen_info.display_texture;      state.texture_units[0].swizzle = {GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA}; +    // Workaround brigthness problems in SMO by enabling sRGB in the final output +    // if it has been used in the frame +    // Needed because of this bug in QT +    // QTBUG-50987 +    state.framebuffer_srgb.enabled = OpenGLState::GetsRGBUsed();      state.Apply(); -      glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices.data());      glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - +    // restore default state +    state.framebuffer_srgb.enabled = false;      state.texture_units[0].texture = 0;      state.Apply(); +    // Clear sRGB state for the next frame +    OpenGLState::ClearsRGBUsed();  }  /** diff --git a/src/video_core/textures/texture.h b/src/video_core/textures/texture.h index 5947bd2b9..d12d2ecb8 100644 --- a/src/video_core/textures/texture.h +++ b/src/video_core/textures/texture.h @@ -173,6 +173,7 @@ struct TICEntry {      };      union {          BitField<0, 16, u32> width_minus_1; +        BitField<22, 1, u32> srgb_conversion;          BitField<23, 4, TextureType> texture_type;      };      union { @@ -227,6 +228,10 @@ struct TICEntry {          return header_version == TICHeaderVersion::BlockLinear ||                 header_version == TICHeaderVersion::BlockLinearColorKey;      } + +    bool IsSrgbConversionEnabled() const { +        return srgb_conversion != 0; +    }  };  static_assert(sizeof(TICEntry) == 0x20, "TICEntry has wrong size"); | 
