summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/video_core/engines/maxwell_3d.h7
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp13
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer_cache.cpp91
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer_cache.h80
-rw-r--r--src/video_core/renderer_opengl/gl_state.cpp13
-rw-r--r--src/video_core/renderer_opengl/gl_state.h14
-rw-r--r--src/video_core/renderer_opengl/renderer_opengl.cpp14
-rw-r--r--src/video_core/textures/texture.h5
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:
723 StencilOp stencil_back_op_zpass; 723 StencilOp stencil_back_op_zpass;
724 ComparisonOp stencil_back_func_func; 724 ComparisonOp stencil_back_func_func;
725 725
726 INSERT_PADDING_WORDS(0x17); 726 INSERT_PADDING_WORDS(0x4);
727
728 u32 framebuffer_srgb;
729
730 INSERT_PADDING_WORDS(0x12);
727 731
728 union { 732 union {
729 BitField<2, 1, u32> coord_origin; 733 BitField<2, 1, u32> coord_origin;
@@ -1086,6 +1090,7 @@ ASSERT_REG_POSITION(stencil_back_op_fail, 0x566);
1086ASSERT_REG_POSITION(stencil_back_op_zfail, 0x567); 1090ASSERT_REG_POSITION(stencil_back_op_zfail, 0x567);
1087ASSERT_REG_POSITION(stencil_back_op_zpass, 0x568); 1091ASSERT_REG_POSITION(stencil_back_op_zpass, 0x568);
1088ASSERT_REG_POSITION(stencil_back_func_func, 0x569); 1092ASSERT_REG_POSITION(stencil_back_func_func, 0x569);
1093ASSERT_REG_POSITION(framebuffer_srgb, 0x56E);
1089ASSERT_REG_POSITION(point_coord_replace, 0x581); 1094ASSERT_REG_POSITION(point_coord_replace, 0x581);
1090ASSERT_REG_POSITION(code_address, 0x582); 1095ASSERT_REG_POSITION(code_address, 0x582);
1091ASSERT_REG_POSITION(draw, 0x585); 1096ASSERT_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
418 // Bind the framebuffer surfaces 418 // Bind the framebuffer surfaces
419 state.draw.draw_framebuffer = framebuffer.handle; 419 state.draw.draw_framebuffer = framebuffer.handle;
420 state.Apply(); 420 state.Apply();
421 state.framebuffer_srgb.enabled = regs.framebuffer_srgb != 0;
421 422
422 if (using_color_fb) { 423 if (using_color_fb) {
423 if (single_color_target) { 424 if (single_color_target) {
@@ -429,6 +430,9 @@ void RasterizerOpenGL::ConfigureFramebuffers(bool using_color_fb, bool using_dep
429 // Assume that a surface will be written to if it is used as a framebuffer, even if 430 // Assume that a surface will be written to if it is used as a framebuffer, even if
430 // the shader doesn't actually write to it. 431 // the shader doesn't actually write to it.
431 color_surface->MarkAsModified(true, res_cache); 432 color_surface->MarkAsModified(true, res_cache);
433 // Workaround for and issue in nvidia drivers
434 // https://devtalk.nvidia.com/default/topic/776591/opengl/gl_framebuffer_srgb-functions-incorrectly/
435 state.framebuffer_srgb.enabled |= color_surface->GetSurfaceParams().srgb_conversion;
432 } 436 }
433 437
434 glFramebufferTexture2D( 438 glFramebufferTexture2D(
@@ -446,6 +450,11 @@ void RasterizerOpenGL::ConfigureFramebuffers(bool using_color_fb, bool using_dep
446 // Assume that a surface will be written to if it is used as a framebuffer, even 450 // Assume that a surface will be written to if it is used as a framebuffer, even
447 // if the shader doesn't actually write to it. 451 // if the shader doesn't actually write to it.
448 color_surface->MarkAsModified(true, res_cache); 452 color_surface->MarkAsModified(true, res_cache);
453 // Enable sRGB only for supported formats
454 // Workaround for and issue in nvidia drivers
455 // https://devtalk.nvidia.com/default/topic/776591/opengl/gl_framebuffer_srgb-functions-incorrectly/
456 state.framebuffer_srgb.enabled |=
457 color_surface->GetSurfaceParams().srgb_conversion;
449 } 458 }
450 459
451 buffers[index] = GL_COLOR_ATTACHMENT0 + regs.rt_control.GetMap(index); 460 buffers[index] = GL_COLOR_ATTACHMENT0 + regs.rt_control.GetMap(index);
@@ -537,7 +546,9 @@ void RasterizerOpenGL::Clear() {
537 546
538 ConfigureFramebuffers(use_color, use_depth || use_stencil, false, 547 ConfigureFramebuffers(use_color, use_depth || use_stencil, false,
539 regs.clear_buffers.RT.Value()); 548 regs.clear_buffers.RT.Value());
540 549 // Copy the sRGB setting to the clear state to avoid problem with
550 // specific driver implementations
551 clear_state.framebuffer_srgb.enabled = state.framebuffer_srgb.enabled;
541 clear_state.Apply(); 552 clear_state.Apply();
542 553
543 if (use_color) { 554 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) {
40 case PixelFormat::ASTC_2D_5X4: 40 case PixelFormat::ASTC_2D_5X4:
41 case PixelFormat::ASTC_2D_8X8: 41 case PixelFormat::ASTC_2D_8X8:
42 case PixelFormat::ASTC_2D_8X5: 42 case PixelFormat::ASTC_2D_8X5:
43 case PixelFormat::ASTC_2D_4X4_SRGB:
44 case PixelFormat::ASTC_2D_5X4_SRGB:
45 case PixelFormat::ASTC_2D_8X8_SRGB:
46 case PixelFormat::ASTC_2D_8X5_SRGB:
43 return true; 47 return true;
44 default: 48 default:
45 return false; 49 return false;
@@ -56,6 +60,14 @@ static std::pair<u32, u32> GetASTCBlockSize(PixelFormat format) {
56 return {8, 8}; 60 return {8, 8};
57 case PixelFormat::ASTC_2D_8X5: 61 case PixelFormat::ASTC_2D_8X5:
58 return {8, 5}; 62 return {8, 5};
63 case PixelFormat::ASTC_2D_4X4_SRGB:
64 return {4, 4};
65 case PixelFormat::ASTC_2D_5X4_SRGB:
66 return {5, 4};
67 case PixelFormat::ASTC_2D_8X8_SRGB:
68 return {8, 8};
69 case PixelFormat::ASTC_2D_8X5_SRGB:
70 return {8, 5};
59 default: 71 default:
60 LOG_CRITICAL(HW_GPU, "Unhandled format: {}", static_cast<u32>(format)); 72 LOG_CRITICAL(HW_GPU, "Unhandled format: {}", static_cast<u32>(format));
61 UNREACHABLE(); 73 UNREACHABLE();
@@ -108,8 +120,9 @@ std::size_t SurfaceParams::InnerMemorySize(bool layer_only) const {
108 params.block_width = params.is_tiled ? config.tic.BlockWidth() : 0, 120 params.block_width = params.is_tiled ? config.tic.BlockWidth() : 0,
109 params.block_height = params.is_tiled ? config.tic.BlockHeight() : 0, 121 params.block_height = params.is_tiled ? config.tic.BlockHeight() : 0,
110 params.block_depth = params.is_tiled ? config.tic.BlockDepth() : 0, 122 params.block_depth = params.is_tiled ? config.tic.BlockDepth() : 0,
111 params.pixel_format = 123 params.srgb_conversion = config.tic.IsSrgbConversionEnabled();
112 PixelFormatFromTextureFormat(config.tic.format, config.tic.r_type.Value()); 124 params.pixel_format = PixelFormatFromTextureFormat(config.tic.format, config.tic.r_type.Value(),
125 params.srgb_conversion);
113 params.component_type = ComponentTypeFromTexture(config.tic.r_type.Value()); 126 params.component_type = ComponentTypeFromTexture(config.tic.r_type.Value());
114 params.type = GetFormatType(params.pixel_format); 127 params.type = GetFormatType(params.pixel_format);
115 params.width = Common::AlignUp(config.tic.Width(), GetCompressionFactor(params.pixel_format)); 128 params.width = Common::AlignUp(config.tic.Width(), GetCompressionFactor(params.pixel_format));
@@ -166,6 +179,8 @@ std::size_t SurfaceParams::InnerMemorySize(bool layer_only) const {
166 params.block_height = 1 << config.memory_layout.block_height; 179 params.block_height = 1 << config.memory_layout.block_height;
167 params.block_depth = 1 << config.memory_layout.block_depth; 180 params.block_depth = 1 << config.memory_layout.block_depth;
168 params.pixel_format = PixelFormatFromRenderTargetFormat(config.format); 181 params.pixel_format = PixelFormatFromRenderTargetFormat(config.format);
182 params.srgb_conversion = config.format == Tegra::RenderTargetFormat::BGRA8_SRGB ||
183 config.format == Tegra::RenderTargetFormat::RGBA8_SRGB;
169 params.component_type = ComponentTypeFromRenderTarget(config.format); 184 params.component_type = ComponentTypeFromRenderTarget(config.format);
170 params.type = GetFormatType(params.pixel_format); 185 params.type = GetFormatType(params.pixel_format);
171 params.width = config.width; 186 params.width = config.width;
@@ -201,6 +216,7 @@ std::size_t SurfaceParams::InnerMemorySize(bool layer_only) const {
201 params.pixel_format = PixelFormatFromDepthFormat(format); 216 params.pixel_format = PixelFormatFromDepthFormat(format);
202 params.component_type = ComponentTypeFromDepthFormat(format); 217 params.component_type = ComponentTypeFromDepthFormat(format);
203 params.type = GetFormatType(params.pixel_format); 218 params.type = GetFormatType(params.pixel_format);
219 params.srgb_conversion = false;
204 params.width = zeta_width; 220 params.width = zeta_width;
205 params.height = zeta_height; 221 params.height = zeta_height;
206 params.unaligned_height = zeta_height; 222 params.unaligned_height = zeta_height;
@@ -224,6 +240,8 @@ std::size_t SurfaceParams::InnerMemorySize(bool layer_only) const {
224 params.block_height = params.is_tiled ? std::min(config.BlockHeight(), 32U) : 0, 240 params.block_height = params.is_tiled ? std::min(config.BlockHeight(), 32U) : 0,
225 params.block_depth = params.is_tiled ? std::min(config.BlockDepth(), 32U) : 0, 241 params.block_depth = params.is_tiled ? std::min(config.BlockDepth(), 32U) : 0,
226 params.pixel_format = PixelFormatFromRenderTargetFormat(config.format); 242 params.pixel_format = PixelFormatFromRenderTargetFormat(config.format);
243 params.srgb_conversion = config.format == Tegra::RenderTargetFormat::BGRA8_SRGB ||
244 config.format == Tegra::RenderTargetFormat::RGBA8_SRGB;
227 params.component_type = ComponentTypeFromRenderTarget(config.format); 245 params.component_type = ComponentTypeFromRenderTarget(config.format);
228 params.type = GetFormatType(params.pixel_format); 246 params.type = GetFormatType(params.pixel_format);
229 params.width = config.width; 247 params.width = config.width;
@@ -289,14 +307,29 @@ static constexpr std::array<FormatTuple, SurfaceParams::MaxPixelFormat> tex_form
289 {GL_RG16I, GL_RG_INTEGER, GL_SHORT, ComponentType::SInt, false}, // RG16I 307 {GL_RG16I, GL_RG_INTEGER, GL_SHORT, ComponentType::SInt, false}, // RG16I
290 {GL_RG16_SNORM, GL_RG, GL_SHORT, ComponentType::SNorm, false}, // RG16S 308 {GL_RG16_SNORM, GL_RG, GL_SHORT, ComponentType::SNorm, false}, // RG16S
291 {GL_RGB32F, GL_RGB, GL_FLOAT, ComponentType::Float, false}, // RGB32F 309 {GL_RGB32F, GL_RGB, GL_FLOAT, ComponentType::Float, false}, // RGB32F
292 {GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, ComponentType::UNorm, false}, // SRGBA8 310 {GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, ComponentType::UNorm,
293 {GL_RG8, GL_RG, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // RG8U 311 false}, // RGBA8_SRGB
294 {GL_RG8, GL_RG, GL_BYTE, ComponentType::SNorm, false}, // RG8S 312 {GL_RG8, GL_RG, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // RG8U
295 {GL_RG32UI, GL_RG_INTEGER, GL_UNSIGNED_INT, ComponentType::UInt, false}, // RG32UI 313 {GL_RG8, GL_RG, GL_BYTE, ComponentType::SNorm, false}, // RG8S
296 {GL_R32UI, GL_RED_INTEGER, GL_UNSIGNED_INT, ComponentType::UInt, false}, // R32UI 314 {GL_RG32UI, GL_RG_INTEGER, GL_UNSIGNED_INT, ComponentType::UInt, false}, // RG32UI
297 {GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_8X8 315 {GL_R32UI, GL_RED_INTEGER, GL_UNSIGNED_INT, ComponentType::UInt, false}, // R32UI
298 {GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_8X5 316 {GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_8X8
299 {GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_5X4 317 {GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_8X5
318 {GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_5X4
319 {GL_SRGB8_ALPHA8, GL_BGRA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // BGRA8
320 // Compressed sRGB formats
321 {GL_COMPRESSED_SRGB_S3TC_DXT1_EXT, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, ComponentType::UNorm,
322 true}, // DXT1_SRGB
323 {GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, ComponentType::UNorm,
324 true}, // DXT23_SRGB
325 {GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, ComponentType::UNorm,
326 true}, // DXT45_SRGB
327 {GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8,
328 ComponentType::UNorm, true}, // BC7U_SRGB
329 {GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_4X4_SRGB
330 {GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_8X8_SRGB
331 {GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_8X5_SRGB
332 {GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, ComponentType::UNorm, false}, // ASTC_2D_5X4_SRGB
300 333
301 // Depth formats 334 // Depth formats
302 {GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT, ComponentType::Float, false}, // Z32F 335 {GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT, ComponentType::Float, false}, // Z32F
@@ -361,6 +394,10 @@ static bool IsFormatBCn(PixelFormat format) {
361 case PixelFormat::BC7U: 394 case PixelFormat::BC7U:
362 case PixelFormat::BC6H_UF16: 395 case PixelFormat::BC6H_UF16:
363 case PixelFormat::BC6H_SF16: 396 case PixelFormat::BC6H_SF16:
397 case PixelFormat::DXT1_SRGB:
398 case PixelFormat::DXT23_SRGB:
399 case PixelFormat::DXT45_SRGB:
400 case PixelFormat::BC7U_SRGB:
364 return true; 401 return true;
365 } 402 }
366 return false; 403 return false;
@@ -432,7 +469,7 @@ static constexpr GLConversionArray morton_to_gl_fns = {
432 MortonCopy<true, PixelFormat::RG16I>, 469 MortonCopy<true, PixelFormat::RG16I>,
433 MortonCopy<true, PixelFormat::RG16S>, 470 MortonCopy<true, PixelFormat::RG16S>,
434 MortonCopy<true, PixelFormat::RGB32F>, 471 MortonCopy<true, PixelFormat::RGB32F>,
435 MortonCopy<true, PixelFormat::SRGBA8>, 472 MortonCopy<true, PixelFormat::RGBA8_SRGB>,
436 MortonCopy<true, PixelFormat::RG8U>, 473 MortonCopy<true, PixelFormat::RG8U>,
437 MortonCopy<true, PixelFormat::RG8S>, 474 MortonCopy<true, PixelFormat::RG8S>,
438 MortonCopy<true, PixelFormat::RG32UI>, 475 MortonCopy<true, PixelFormat::RG32UI>,
@@ -440,6 +477,15 @@ static constexpr GLConversionArray morton_to_gl_fns = {
440 MortonCopy<true, PixelFormat::ASTC_2D_8X8>, 477 MortonCopy<true, PixelFormat::ASTC_2D_8X8>,
441 MortonCopy<true, PixelFormat::ASTC_2D_8X5>, 478 MortonCopy<true, PixelFormat::ASTC_2D_8X5>,
442 MortonCopy<true, PixelFormat::ASTC_2D_5X4>, 479 MortonCopy<true, PixelFormat::ASTC_2D_5X4>,
480 MortonCopy<true, PixelFormat::BGRA8_SRGB>,
481 MortonCopy<true, PixelFormat::DXT1_SRGB>,
482 MortonCopy<true, PixelFormat::DXT23_SRGB>,
483 MortonCopy<true, PixelFormat::DXT45_SRGB>,
484 MortonCopy<true, PixelFormat::BC7U_SRGB>,
485 MortonCopy<true, PixelFormat::ASTC_2D_4X4_SRGB>,
486 MortonCopy<true, PixelFormat::ASTC_2D_8X8_SRGB>,
487 MortonCopy<true, PixelFormat::ASTC_2D_8X5_SRGB>,
488 MortonCopy<true, PixelFormat::ASTC_2D_5X4_SRGB>,
443 MortonCopy<true, PixelFormat::Z32F>, 489 MortonCopy<true, PixelFormat::Z32F>,
444 MortonCopy<true, PixelFormat::Z16>, 490 MortonCopy<true, PixelFormat::Z16>,
445 MortonCopy<true, PixelFormat::Z24S8>, 491 MortonCopy<true, PixelFormat::Z24S8>,
@@ -491,7 +537,7 @@ static constexpr GLConversionArray gl_to_morton_fns = {
491 MortonCopy<false, PixelFormat::RG16I>, 537 MortonCopy<false, PixelFormat::RG16I>,
492 MortonCopy<false, PixelFormat::RG16S>, 538 MortonCopy<false, PixelFormat::RG16S>,
493 MortonCopy<false, PixelFormat::RGB32F>, 539 MortonCopy<false, PixelFormat::RGB32F>,
494 MortonCopy<false, PixelFormat::SRGBA8>, 540 MortonCopy<false, PixelFormat::RGBA8_SRGB>,
495 MortonCopy<false, PixelFormat::RG8U>, 541 MortonCopy<false, PixelFormat::RG8U>,
496 MortonCopy<false, PixelFormat::RG8S>, 542 MortonCopy<false, PixelFormat::RG8S>,
497 MortonCopy<false, PixelFormat::RG32UI>, 543 MortonCopy<false, PixelFormat::RG32UI>,
@@ -499,6 +545,15 @@ static constexpr GLConversionArray gl_to_morton_fns = {
499 nullptr, 545 nullptr,
500 nullptr, 546 nullptr,
501 nullptr, 547 nullptr,
548 MortonCopy<false, PixelFormat::BGRA8_SRGB>,
549 MortonCopy<false, PixelFormat::DXT1_SRGB>,
550 MortonCopy<false, PixelFormat::DXT23_SRGB>,
551 MortonCopy<false, PixelFormat::DXT45_SRGB>,
552 MortonCopy<false, PixelFormat::BC7U_SRGB>,
553 nullptr,
554 nullptr,
555 nullptr,
556 nullptr,
502 MortonCopy<false, PixelFormat::Z32F>, 557 MortonCopy<false, PixelFormat::Z32F>,
503 MortonCopy<false, PixelFormat::Z16>, 558 MortonCopy<false, PixelFormat::Z16>,
504 MortonCopy<false, PixelFormat::Z24S8>, 559 MortonCopy<false, PixelFormat::Z24S8>,
@@ -546,6 +601,8 @@ static bool BlitSurface(const Surface& src_surface, const Surface& dst_surface,
546 OpenGLState state; 601 OpenGLState state;
547 state.draw.read_framebuffer = read_fb_handle; 602 state.draw.read_framebuffer = read_fb_handle;
548 state.draw.draw_framebuffer = draw_fb_handle; 603 state.draw.draw_framebuffer = draw_fb_handle;
604 // Set sRGB enabled if the destination surfaces need it
605 state.framebuffer_srgb.enabled = dst_params.srgb_conversion;
549 state.Apply(); 606 state.Apply();
550 607
551 u32 buffers{}; 608 u32 buffers{};
@@ -881,7 +938,11 @@ static void ConvertFormatAsNeeded_LoadGLBuffer(std::vector<u8>& data, PixelForma
881 case PixelFormat::ASTC_2D_4X4: 938 case PixelFormat::ASTC_2D_4X4:
882 case PixelFormat::ASTC_2D_8X8: 939 case PixelFormat::ASTC_2D_8X8:
883 case PixelFormat::ASTC_2D_8X5: 940 case PixelFormat::ASTC_2D_8X5:
884 case PixelFormat::ASTC_2D_5X4: { 941 case PixelFormat::ASTC_2D_5X4:
942 case PixelFormat::ASTC_2D_4X4_SRGB:
943 case PixelFormat::ASTC_2D_8X8_SRGB:
944 case PixelFormat::ASTC_2D_8X5_SRGB:
945 case PixelFormat::ASTC_2D_5X4_SRGB: {
885 // Convert ASTC pixel formats to RGBA8, as most desktop GPUs do not support ASTC. 946 // Convert ASTC pixel formats to RGBA8, as most desktop GPUs do not support ASTC.
886 u32 block_width{}; 947 u32 block_width{};
887 u32 block_height{}; 948 u32 block_height{};
@@ -913,7 +974,9 @@ static void ConvertFormatAsNeeded_FlushGLBuffer(std::vector<u8>& data, PixelForm
913 case PixelFormat::G8R8U: 974 case PixelFormat::G8R8U:
914 case PixelFormat::G8R8S: 975 case PixelFormat::G8R8S:
915 case PixelFormat::ASTC_2D_4X4: 976 case PixelFormat::ASTC_2D_4X4:
916 case PixelFormat::ASTC_2D_8X8: { 977 case PixelFormat::ASTC_2D_8X8:
978 case PixelFormat::ASTC_2D_4X4_SRGB:
979 case PixelFormat::ASTC_2D_8X8_SRGB: {
917 LOG_CRITICAL(HW_GPU, "Conversion of format {} after texture flushing is not implemented", 980 LOG_CRITICAL(HW_GPU, "Conversion of format {} after texture flushing is not implemented",
918 static_cast<u32>(pixel_format)); 981 static_cast<u32>(pixel_format));
919 UNREACHABLE(); 982 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 {
69 RG16I = 37, 69 RG16I = 37,
70 RG16S = 38, 70 RG16S = 38,
71 RGB32F = 39, 71 RGB32F = 39,
72 SRGBA8 = 40, 72 RGBA8_SRGB = 40,
73 RG8U = 41, 73 RG8U = 41,
74 RG8S = 42, 74 RG8S = 42,
75 RG32UI = 43, 75 RG32UI = 43,
@@ -77,19 +77,28 @@ struct SurfaceParams {
77 ASTC_2D_8X8 = 45, 77 ASTC_2D_8X8 = 45,
78 ASTC_2D_8X5 = 46, 78 ASTC_2D_8X5 = 46,
79 ASTC_2D_5X4 = 47, 79 ASTC_2D_5X4 = 47,
80 BGRA8_SRGB = 48,
81 DXT1_SRGB = 49,
82 DXT23_SRGB = 50,
83 DXT45_SRGB = 51,
84 BC7U_SRGB = 52,
85 ASTC_2D_4X4_SRGB = 53,
86 ASTC_2D_8X8_SRGB = 54,
87 ASTC_2D_8X5_SRGB = 55,
88 ASTC_2D_5X4_SRGB = 56,
80 89
81 MaxColorFormat, 90 MaxColorFormat,
82 91
83 // Depth formats 92 // Depth formats
84 Z32F = 48, 93 Z32F = 57,
85 Z16 = 49, 94 Z16 = 58,
86 95
87 MaxDepthFormat, 96 MaxDepthFormat,
88 97
89 // DepthStencil formats 98 // DepthStencil formats
90 Z24S8 = 50, 99 Z24S8 = 59,
91 S8Z24 = 51, 100 S8Z24 = 60,
92 Z32FS8 = 52, 101 Z32FS8 = 61,
93 102
94 MaxDepthStencilFormat, 103 MaxDepthStencilFormat,
95 104
@@ -236,7 +245,7 @@ struct SurfaceParams {
236 1, // RG16I 245 1, // RG16I
237 1, // RG16S 246 1, // RG16S
238 1, // RGB32F 247 1, // RGB32F
239 1, // SRGBA8 248 1, // RGBA8_SRGB
240 1, // RG8U 249 1, // RG8U
241 1, // RG8S 250 1, // RG8S
242 1, // RG32UI 251 1, // RG32UI
@@ -244,6 +253,15 @@ struct SurfaceParams {
244 4, // ASTC_2D_8X8 253 4, // ASTC_2D_8X8
245 4, // ASTC_2D_8X5 254 4, // ASTC_2D_8X5
246 4, // ASTC_2D_5X4 255 4, // ASTC_2D_5X4
256 1, // BGRA8_SRGB
257 4, // DXT1_SRGB
258 4, // DXT23_SRGB
259 4, // DXT45_SRGB
260 4, // BC7U_SRGB
261 4, // ASTC_2D_4X4_SRGB
262 4, // ASTC_2D_8X8_SRGB
263 4, // ASTC_2D_8X5_SRGB
264 4, // ASTC_2D_5X4_SRGB
247 1, // Z32F 265 1, // Z32F
248 1, // Z16 266 1, // Z16
249 1, // Z24S8 267 1, // Z24S8
@@ -299,7 +317,7 @@ struct SurfaceParams {
299 1, // RG16I 317 1, // RG16I
300 1, // RG16S 318 1, // RG16S
301 1, // RGB32F 319 1, // RGB32F
302 1, // SRGBA8 320 1, // RGBA8_SRGB
303 1, // RG8U 321 1, // RG8U
304 1, // RG8S 322 1, // RG8S
305 1, // RG32UI 323 1, // RG32UI
@@ -307,6 +325,15 @@ struct SurfaceParams {
307 8, // ASTC_2D_8X8 325 8, // ASTC_2D_8X8
308 5, // ASTC_2D_8X5 326 5, // ASTC_2D_8X5
309 4, // ASTC_2D_5X4 327 4, // ASTC_2D_5X4
328 1, // BGRA8_SRGB
329 4, // DXT1_SRGB
330 4, // DXT23_SRGB
331 4, // DXT45_SRGB
332 4, // BC7U_SRGB
333 4, // ASTC_2D_4X4_SRGB
334 8, // ASTC_2D_8X8_SRGB
335 5, // ASTC_2D_8X5_SRGB
336 4, // ASTC_2D_5X4_SRGB
310 1, // Z32F 337 1, // Z32F
311 1, // Z16 338 1, // Z16
312 1, // Z24S8 339 1, // Z24S8
@@ -362,7 +389,7 @@ struct SurfaceParams {
362 32, // RG16I 389 32, // RG16I
363 32, // RG16S 390 32, // RG16S
364 96, // RGB32F 391 96, // RGB32F
365 32, // SRGBA8 392 32, // RGBA8_SRGB
366 16, // RG8U 393 16, // RG8U
367 16, // RG8S 394 16, // RG8S
368 64, // RG32UI 395 64, // RG32UI
@@ -370,6 +397,15 @@ struct SurfaceParams {
370 16, // ASTC_2D_8X8 397 16, // ASTC_2D_8X8
371 32, // ASTC_2D_8X5 398 32, // ASTC_2D_8X5
372 32, // ASTC_2D_5X4 399 32, // ASTC_2D_5X4
400 32, // BGRA8_SRGB
401 64, // DXT1_SRGB
402 128, // DXT23_SRGB
403 128, // DXT45_SRGB
404 128, // BC7U
405 32, // ASTC_2D_4X4_SRGB
406 16, // ASTC_2D_8X8_SRGB
407 32, // ASTC_2D_8X5_SRGB
408 32, // ASTC_2D_5X4_SRGB
373 32, // Z32F 409 32, // Z32F
374 16, // Z16 410 16, // Z16
375 32, // Z24S8 411 32, // Z24S8
@@ -408,6 +444,7 @@ struct SurfaceParams {
408 // TODO (Hexagon12): Converting SRGBA to RGBA is a hack and doesn't completely correct the 444 // TODO (Hexagon12): Converting SRGBA to RGBA is a hack and doesn't completely correct the
409 // gamma. 445 // gamma.
410 case Tegra::RenderTargetFormat::RGBA8_SRGB: 446 case Tegra::RenderTargetFormat::RGBA8_SRGB:
447 return PixelFormat::RGBA8_SRGB;
411 case Tegra::RenderTargetFormat::RGBA8_UNORM: 448 case Tegra::RenderTargetFormat::RGBA8_UNORM:
412 return PixelFormat::ABGR8U; 449 return PixelFormat::ABGR8U;
413 case Tegra::RenderTargetFormat::RGBA8_SNORM: 450 case Tegra::RenderTargetFormat::RGBA8_SNORM:
@@ -415,6 +452,7 @@ struct SurfaceParams {
415 case Tegra::RenderTargetFormat::RGBA8_UINT: 452 case Tegra::RenderTargetFormat::RGBA8_UINT:
416 return PixelFormat::ABGR8UI; 453 return PixelFormat::ABGR8UI;
417 case Tegra::RenderTargetFormat::BGRA8_SRGB: 454 case Tegra::RenderTargetFormat::BGRA8_SRGB:
455 return PixelFormat::BGRA8_SRGB;
418 case Tegra::RenderTargetFormat::BGRA8_UNORM: 456 case Tegra::RenderTargetFormat::BGRA8_UNORM:
419 return PixelFormat::BGRA8; 457 return PixelFormat::BGRA8;
420 case Tegra::RenderTargetFormat::RGB10_A2_UNORM: 458 case Tegra::RenderTargetFormat::RGB10_A2_UNORM:
@@ -478,10 +516,14 @@ struct SurfaceParams {
478 } 516 }
479 517
480 static PixelFormat PixelFormatFromTextureFormat(Tegra::Texture::TextureFormat format, 518 static PixelFormat PixelFormatFromTextureFormat(Tegra::Texture::TextureFormat format,
481 Tegra::Texture::ComponentType component_type) { 519 Tegra::Texture::ComponentType component_type,
520 bool is_srgb) {
482 // TODO(Subv): Properly implement this 521 // TODO(Subv): Properly implement this
483 switch (format) { 522 switch (format) {
484 case Tegra::Texture::TextureFormat::A8R8G8B8: 523 case Tegra::Texture::TextureFormat::A8R8G8B8:
524 if (is_srgb) {
525 return PixelFormat::RGBA8_SRGB;
526 }
485 switch (component_type) { 527 switch (component_type) {
486 case Tegra::Texture::ComponentType::UNORM: 528 case Tegra::Texture::ComponentType::UNORM:
487 return PixelFormat::ABGR8U; 529 return PixelFormat::ABGR8U;
@@ -616,11 +658,11 @@ struct SurfaceParams {
616 case Tegra::Texture::TextureFormat::Z24S8: 658 case Tegra::Texture::TextureFormat::Z24S8:
617 return PixelFormat::Z24S8; 659 return PixelFormat::Z24S8;
618 case Tegra::Texture::TextureFormat::DXT1: 660 case Tegra::Texture::TextureFormat::DXT1:
619 return PixelFormat::DXT1; 661 return is_srgb ? PixelFormat::DXT1_SRGB : PixelFormat::DXT1;
620 case Tegra::Texture::TextureFormat::DXT23: 662 case Tegra::Texture::TextureFormat::DXT23:
621 return PixelFormat::DXT23; 663 return is_srgb ? PixelFormat::DXT23_SRGB : PixelFormat::DXT23;
622 case Tegra::Texture::TextureFormat::DXT45: 664 case Tegra::Texture::TextureFormat::DXT45:
623 return PixelFormat::DXT45; 665 return is_srgb ? PixelFormat::DXT45_SRGB : PixelFormat::DXT45;
624 case Tegra::Texture::TextureFormat::DXN1: 666 case Tegra::Texture::TextureFormat::DXN1:
625 return PixelFormat::DXN1; 667 return PixelFormat::DXN1;
626 case Tegra::Texture::TextureFormat::DXN2: 668 case Tegra::Texture::TextureFormat::DXN2:
@@ -634,19 +676,19 @@ struct SurfaceParams {
634 static_cast<u32>(component_type)); 676 static_cast<u32>(component_type));
635 UNREACHABLE(); 677 UNREACHABLE();
636 case Tegra::Texture::TextureFormat::BC7U: 678 case Tegra::Texture::TextureFormat::BC7U:
637 return PixelFormat::BC7U; 679 return is_srgb ? PixelFormat::BC7U_SRGB : PixelFormat::BC7U;
638 case Tegra::Texture::TextureFormat::BC6H_UF16: 680 case Tegra::Texture::TextureFormat::BC6H_UF16:
639 return PixelFormat::BC6H_UF16; 681 return PixelFormat::BC6H_UF16;
640 case Tegra::Texture::TextureFormat::BC6H_SF16: 682 case Tegra::Texture::TextureFormat::BC6H_SF16:
641 return PixelFormat::BC6H_SF16; 683 return PixelFormat::BC6H_SF16;
642 case Tegra::Texture::TextureFormat::ASTC_2D_4X4: 684 case Tegra::Texture::TextureFormat::ASTC_2D_4X4:
643 return PixelFormat::ASTC_2D_4X4; 685 return is_srgb ? PixelFormat::ASTC_2D_4X4_SRGB : PixelFormat::ASTC_2D_4X4;
644 case Tegra::Texture::TextureFormat::ASTC_2D_5X4: 686 case Tegra::Texture::TextureFormat::ASTC_2D_5X4:
645 return PixelFormat::ASTC_2D_5X4; 687 return is_srgb ? PixelFormat::ASTC_2D_5X4_SRGB : PixelFormat::ASTC_2D_5X4;
646 case Tegra::Texture::TextureFormat::ASTC_2D_8X8: 688 case Tegra::Texture::TextureFormat::ASTC_2D_8X8:
647 return PixelFormat::ASTC_2D_8X8; 689 return is_srgb ? PixelFormat::ASTC_2D_8X8_SRGB : PixelFormat::ASTC_2D_8X8;
648 case Tegra::Texture::TextureFormat::ASTC_2D_8X5: 690 case Tegra::Texture::TextureFormat::ASTC_2D_8X5:
649 return PixelFormat::ASTC_2D_8X5; 691 return is_srgb ? PixelFormat::ASTC_2D_8X5_SRGB : PixelFormat::ASTC_2D_8X5;
650 case Tegra::Texture::TextureFormat::R16_G16: 692 case Tegra::Texture::TextureFormat::R16_G16:
651 switch (component_type) { 693 switch (component_type) {
652 case Tegra::Texture::ComponentType::FLOAT: 694 case Tegra::Texture::ComponentType::FLOAT:
@@ -881,7 +923,7 @@ struct SurfaceParams {
881 SurfaceTarget target; 923 SurfaceTarget target;
882 u32 max_mip_level; 924 u32 max_mip_level;
883 bool is_layered; 925 bool is_layered;
884 926 bool srgb_conversion;
885 // Parameters used for caching 927 // Parameters used for caching
886 VAddr addr; 928 VAddr addr;
887 Tegra::GPUVAddr gpu_addr; 929 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 @@
11namespace OpenGL { 11namespace OpenGL {
12 12
13OpenGLState OpenGLState::cur_state; 13OpenGLState OpenGLState::cur_state;
14 14bool OpenGLState::s_rgb_used;
15OpenGLState::OpenGLState() { 15OpenGLState::OpenGLState() {
16 // These all match default OpenGL values 16 // These all match default OpenGL values
17 framebuffer_srgb.enabled = false;
17 cull.enabled = false; 18 cull.enabled = false;
18 cull.mode = GL_BACK; 19 cull.mode = GL_BACK;
19 cull.front_face = GL_CCW; 20 cull.front_face = GL_CCW;
@@ -89,6 +90,16 @@ OpenGLState::OpenGLState() {
89} 90}
90 91
91void OpenGLState::Apply() const { 92void OpenGLState::Apply() const {
93 // sRGB
94 if (framebuffer_srgb.enabled != cur_state.framebuffer_srgb.enabled) {
95 if (framebuffer_srgb.enabled) {
96 // Track if sRGB is used
97 s_rgb_used = true;
98 glEnable(GL_FRAMEBUFFER_SRGB);
99 } else {
100 glDisable(GL_FRAMEBUFFER_SRGB);
101 }
102 }
92 // Culling 103 // Culling
93 if (cull.enabled != cur_state.cull.enabled) { 104 if (cull.enabled != cur_state.cull.enabled) {
94 if (cull.enabled) { 105 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};
36class OpenGLState { 36class OpenGLState {
37public: 37public:
38 struct { 38 struct {
39 bool enabled; // GL_FRAMEBUFFER_SRGB
40 } framebuffer_srgb;
41
42 struct {
39 bool enabled; // GL_CULL_FACE 43 bool enabled; // GL_CULL_FACE
40 GLenum mode; // GL_CULL_FACE_MODE 44 GLenum mode; // GL_CULL_FACE_MODE
41 GLenum front_face; // GL_FRONT_FACE 45 GLenum front_face; // GL_FRONT_FACE
@@ -161,7 +165,12 @@ public:
161 static OpenGLState GetCurState() { 165 static OpenGLState GetCurState() {
162 return cur_state; 166 return cur_state;
163 } 167 }
164 168 static bool GetsRGBUsed() {
169 return s_rgb_used;
170 }
171 static void ClearsRGBUsed() {
172 s_rgb_used = false;
173 }
165 /// Apply this state as the current OpenGL state 174 /// Apply this state as the current OpenGL state
166 void Apply() const; 175 void Apply() const;
167 176
@@ -176,6 +185,9 @@ public:
176 185
177private: 186private:
178 static OpenGLState cur_state; 187 static OpenGLState cur_state;
188 // Workaround for sRGB problems caused by
189 // QT not supporting srgb output
190 static bool s_rgb_used;
179}; 191};
180 192
181} // namespace OpenGL 193} // 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() {
283 if (rasterizer) { 283 if (rasterizer) {
284 return; 284 return;
285 } 285 }
286 286 // Initialize sRGB Usage
287 OpenGLState::ClearsRGBUsed();
287 rasterizer = std::make_unique<RasterizerOpenGL>(render_window, screen_info); 288 rasterizer = std::make_unique<RasterizerOpenGL>(render_window, screen_info);
288} 289}
289 290
@@ -356,13 +357,20 @@ void RendererOpenGL::DrawScreenTriangles(const ScreenInfo& screen_info, float x,
356 357
357 state.texture_units[0].texture = screen_info.display_texture; 358 state.texture_units[0].texture = screen_info.display_texture;
358 state.texture_units[0].swizzle = {GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA}; 359 state.texture_units[0].swizzle = {GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA};
360 // Workaround brigthness problems in SMO by enabling sRGB in the final output
361 // if it has been used in the frame
362 // Needed because of this bug in QT
363 // QTBUG-50987
364 state.framebuffer_srgb.enabled = OpenGLState::GetsRGBUsed();
359 state.Apply(); 365 state.Apply();
360
361 glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices.data()); 366 glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices.data());
362 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 367 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
363 368 // restore default state
369 state.framebuffer_srgb.enabled = false;
364 state.texture_units[0].texture = 0; 370 state.texture_units[0].texture = 0;
365 state.Apply(); 371 state.Apply();
372 // Clear sRGB state for the next frame
373 OpenGLState::ClearsRGBUsed();
366} 374}
367 375
368/** 376/**
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 {
173 }; 173 };
174 union { 174 union {
175 BitField<0, 16, u32> width_minus_1; 175 BitField<0, 16, u32> width_minus_1;
176 BitField<22, 1, u32> srgb_conversion;
176 BitField<23, 4, TextureType> texture_type; 177 BitField<23, 4, TextureType> texture_type;
177 }; 178 };
178 union { 179 union {
@@ -227,6 +228,10 @@ struct TICEntry {
227 return header_version == TICHeaderVersion::BlockLinear || 228 return header_version == TICHeaderVersion::BlockLinear ||
228 header_version == TICHeaderVersion::BlockLinearColorKey; 229 header_version == TICHeaderVersion::BlockLinearColorKey;
229 } 230 }
231
232 bool IsSrgbConversionEnabled() const {
233 return srgb_conversion != 0;
234 }
230}; 235};
231static_assert(sizeof(TICEntry) == 0x20, "TICEntry has wrong size"); 236static_assert(sizeof(TICEntry) == 0x20, "TICEntry has wrong size");
232 237