From: Steinar H. Gunderson Date: Tue, 11 Apr 2017 19:53:00 +0000 (+0200) Subject: Make sure our uploaded RGBA textures can deal with being asked for linear gamma. X-Git-Tag: 1.6.0~58 X-Git-Url: https://git.sesse.net/?p=nageru;a=commitdiff_plain;h=e7042ad94ffec1505feaf7f8c5a265b2165957a0 Make sure our uploaded RGBA textures can deal with being asked for linear gamma. They still are not used for anything, though. --- diff --git a/flags.h b/flags.h index caeaf2b..7f39fdd 100644 --- a/flags.h +++ b/flags.h @@ -58,6 +58,7 @@ struct Flags { bool ten_bit_output = false; // Implies x264_video_to_disk == true and x264_bit_depth == 10. int x264_bit_depth = 8; // Not user-settable. bool use_zerocopy = false; // Not user-settable. + bool can_disable_srgb_decoder = false; // Not user-settable. }; extern Flags global_flags; diff --git a/mixer.cpp b/mixer.cpp index 317c762..385ca23 100644 --- a/mixer.cpp +++ b/mixer.cpp @@ -124,7 +124,11 @@ void ensure_texture_resolution(PBOFrameAllocator::Userdata *userdata, unsigned f case bmusb::PixelFormat_8BitRGBA: glBindTexture(GL_TEXTURE_2D, userdata->tex_rgba[field]); check_error(); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); + if (global_flags.can_disable_srgb_decoder) { // See the comments in tweaked_inputs.h. + glTexImage2D(GL_TEXTURE_2D, 0, GL_SRGB8_ALPHA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); + } else { + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); + } check_error(); break; } @@ -206,6 +210,9 @@ Mixer::Mixer(const QSurfaceFormat &format, unsigned num_cards) CHECK(init_movit(MOVIT_SHADER_DIR, MOVIT_DEBUG_OFF)); check_error(); + // This nearly always should be true. + global_flags.can_disable_srgb_decoder = epoxy_has_gl_extension("GL_EXT_texture_sRGB_decode"); + // Since we allow non-bouncing 4:2:2 YCbCrInputs, effective subpixel precision // will be halved when sampling them, and we need to compensate here. movit_texel_subpixel_precision /= 2.0; diff --git a/pbo_frame_allocator.cpp b/pbo_frame_allocator.cpp index e27aa69..ed1ddb5 100644 --- a/pbo_frame_allocator.cpp +++ b/pbo_frame_allocator.cpp @@ -7,6 +7,7 @@ #include #include +#include "flags.h" #include "v210_converter.h" using namespace std; @@ -143,7 +144,11 @@ PBOFrameAllocator::PBOFrameAllocator(bmusb::PixelFormat pixel_format, size_t fra glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); check_error(); if (field == 0) { - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + if (global_flags.can_disable_srgb_decoder) { // See the comments in tweaked_inputs.h. + glTexImage2D(GL_TEXTURE_2D, 0, GL_SRGB8_ALPHA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + } else { + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + } check_error(); } break; diff --git a/theme.cpp b/theme.cpp index b6a19ac..f92143e 100644 --- a/theme.cpp +++ b/theme.cpp @@ -630,7 +630,11 @@ LiveInputWrapper::LiveInputWrapper(Theme *theme, EffectChain *chain, bmusb::Pixe if (pixel_format == bmusb::PixelFormat_8BitRGBA) { for (unsigned i = 0; i < num_inputs; ++i) { - rgba_inputs.push_back(new FlatInput(inout_format, FORMAT_RGBA_POSTMULTIPLIED_ALPHA, GL_UNSIGNED_BYTE, global_flags.width, global_flags.height)); + if (global_flags.can_disable_srgb_decoder) { + rgba_inputs.push_back(new sRGBSwitchingFlatInput(inout_format, FORMAT_RGBA_POSTMULTIPLIED_ALPHA, GL_UNSIGNED_BYTE, global_flags.width, global_flags.height)); + } else { + rgba_inputs.push_back(new NonsRGBCapableFlatInput(inout_format, FORMAT_RGBA_POSTMULTIPLIED_ALPHA, GL_UNSIGNED_BYTE, global_flags.width, global_flags.height)); + } chain->add_input(rgba_inputs.back()); } diff --git a/tweaked_inputs.h b/tweaked_inputs.h index 5478dde..37c6782 100644 --- a/tweaked_inputs.h +++ b/tweaked_inputs.h @@ -21,4 +21,57 @@ public: bool override_disable_bounce() const override { return true; } }; +// We use FlatInput with RGBA inputs a few places where we can't tell when +// uploading the texture whether it needs to be converted from sRGB to linear +// or not. (FlatInput deals with this if you give it pixels, but we give it +// already uploaded textures.) +// +// If we have GL_EXT_texture_sRGB_decode (very common, as far as I can tell), +// we can just always upload with the sRGB flag turned on, and then turn it off +// if not requested; that's sRGBSwitchingFlatInput. If not, we just need to +// turn off the functionality altogether, which is NonsRGBCapableFlatInput. +// +// If you're using NonsRGBCapableFlatInput, upload with GL_RGBA8. +// If using sRGBSwitchingFlatInput, upload with GL_SRGB8_ALPHA8. + +class NonsRGBCapableFlatInput : public movit::FlatInput { +public: + NonsRGBCapableFlatInput(movit::ImageFormat format, movit::MovitPixelFormat pixel_format, GLenum type, unsigned width, unsigned height) + : movit::FlatInput(format, pixel_format, type, width, height) {} + + bool can_output_linear_gamma() const override { return false; } +}; + +class sRGBSwitchingFlatInput : public movit::FlatInput { +public: + sRGBSwitchingFlatInput(movit::ImageFormat format, movit::MovitPixelFormat pixel_format, GLenum type, unsigned width, unsigned height) + : movit::FlatInput(format, pixel_format, type, width, height) {} + + void set_gl_state(GLuint glsl_program_num, const std::string &prefix, unsigned *sampler_num) override + { + movit::FlatInput::set_gl_state(glsl_program_num, prefix, sampler_num); + + // This flag is ignored for non-sRGB-uploaded textures, so we can set it + // without checking can_output_linear_gamma(). + glActiveTexture(GL_TEXTURE0 + *sampler_num - 1); + if (output_linear_gamma) { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SRGB_DECODE_EXT, GL_DECODE_EXT); + } else { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SRGB_DECODE_EXT, GL_SKIP_DECODE_EXT); + } + } + + bool set_int(const std::string &key, int value) override + { + if (key == "output_linear_gamma") { + output_linear_gamma = value; + } + return movit::FlatInput::set_int(key, value); + } + +private: + int output_linear_gamma = false; +}; + + #endif // !defined(_TWEAKED_INPUTS_H)