From: Steinar H. Gunderson Date: Fri, 21 Apr 2017 22:55:17 +0000 (+0200) Subject: Fix an issue where RGBA videos would flicker. X-Git-Tag: 1.6.0~45 X-Git-Url: https://git.sesse.net/?p=nageru;a=commitdiff_plain;h=142184354968cd1b1918f35772bb6f9f0b1351d6 Fix an issue where RGBA videos would flicker. The issue would be that the preview chains and the live chain would often have different sRGB texture needs, and they'd run at the same time and thus have a race condition. Solve this by using a sampler object instead, which overrides the texture state. --- diff --git a/Makefile b/Makefile index 9dc5526..1a041fe 100644 --- a/Makefile +++ b/Makefile @@ -22,7 +22,7 @@ OBJS += midi_mapper.o midi_mapping.pb.o # Mixer objects AUDIO_MIXER_OBJS = audio_mixer.o alsa_input.o alsa_pool.o ebu_r128_proc.o stereocompressor.o resampling_queue.o flags.o correlation_measurer.o filter.o input_mapping.o state.pb.o -OBJS += chroma_subsampler.o v210_converter.o mixer.o pbo_frame_allocator.o context.o ref_counted_frame.o theme.o httpd.o flags.o image_input.o alsa_output.o disk_space_estimator.o print_latency.o timecode_renderer.o $(AUDIO_MIXER_OBJS) +OBJS += chroma_subsampler.o v210_converter.o mixer.o pbo_frame_allocator.o context.o ref_counted_frame.o theme.o httpd.o flags.o image_input.o alsa_output.o disk_space_estimator.o print_latency.o timecode_renderer.o tweaked_inputs.o $(AUDIO_MIXER_OBJS) # Streaming and encoding objects OBJS += quicksync_encoder.o x264_encoder.o x264_dynamic.o x264_speed_control.o video_encoder.o metacube2.o mux.o audio_encoder.o ffmpeg_raii.o ffmpeg_util.o diff --git a/mixer.cpp b/mixer.cpp index 3a14a75..c21ac95 100644 --- a/mixer.cpp +++ b/mixer.cpp @@ -212,7 +212,9 @@ Mixer::Mixer(const QSurfaceFormat &format, unsigned num_cards) check_error(); // This nearly always should be true. - global_flags.can_disable_srgb_decoder = epoxy_has_gl_extension("GL_EXT_texture_sRGB_decode"); + global_flags.can_disable_srgb_decoder = + epoxy_has_gl_extension("GL_EXT_texture_sRGB_decode") && + epoxy_has_gl_extension("GL_ARB_sampler_objects"); // Since we allow non-bouncing 4:2:2 YCbCrInputs, effective subpixel precision // will be halved when sampling them, and we need to compensate here. diff --git a/tweaked_inputs.cpp b/tweaked_inputs.cpp new file mode 100644 index 0000000..304c3b4 --- /dev/null +++ b/tweaked_inputs.cpp @@ -0,0 +1,48 @@ +#include +#include +#include + +#include "tweaked_inputs.h" + +sRGBSwitchingFlatInput::~sRGBSwitchingFlatInput() +{ + if (sampler_obj != 0) { + glDeleteSamplers(1, &sampler_obj); + } +} + +void sRGBSwitchingFlatInput::set_gl_state(GLuint glsl_program_num, const std::string &prefix, unsigned *sampler_num) +{ + movit::FlatInput::set_gl_state(glsl_program_num, prefix, sampler_num); + texture_unit = *sampler_num - 1; + + if (sampler_obj == 0) { + glGenSamplers(1, &sampler_obj); + check_error(); + glSamplerParameteri(sampler_obj, GL_TEXTURE_MIN_FILTER, needs_mipmaps ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR); + check_error(); + glSamplerParameteri(sampler_obj, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + check_error(); + glSamplerParameteri(sampler_obj, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + check_error() + // This needs to be done on a sampler and not a texture parameter, + // because the texture could be used from multiple different + // contexts at the same time. This flag is ignored for non-sRGB-uploaded + // textures, so we can set it without checking can_output_linear_gamma(). + if (output_linear_gamma) { + glSamplerParameteri(sampler_obj, GL_TEXTURE_SRGB_DECODE_EXT, GL_DECODE_EXT); + } else { + glSamplerParameteri(sampler_obj, GL_TEXTURE_SRGB_DECODE_EXT, GL_SKIP_DECODE_EXT); + } + check_error(); + } + + glBindSampler(texture_unit, sampler_obj); + check_error(); +} + +void sRGBSwitchingFlatInput::clear_gl_state() +{ + glBindSampler(texture_unit, 0); + check_error(); +} diff --git a/tweaked_inputs.h b/tweaked_inputs.h index 37c6782..0ca13ce 100644 --- a/tweaked_inputs.h +++ b/tweaked_inputs.h @@ -47,30 +47,26 @@ 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); - } - } + ~sRGBSwitchingFlatInput(); + void set_gl_state(GLuint glsl_program_num, const std::string &prefix, unsigned *sampler_num) override; + void clear_gl_state() override; bool set_int(const std::string &key, int value) override { if (key == "output_linear_gamma") { output_linear_gamma = value; } + if (key == "needs_mipmaps") { + needs_mipmaps = value; + } return movit::FlatInput::set_int(key, value); } private: - int output_linear_gamma = false; + bool output_linear_gamma = false; + bool needs_mipmaps = false; + GLuint sampler_obj = 0; + GLuint texture_unit; };