Update to 113.0
This commit is contained in:
		
							parent
							
								
									d5f2b2028f
								
							
						
					
					
						commit
						e81ff02c0f
					
				
							
								
								
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @ -571,3 +571,5 @@ firefox-3.6.4.source.tar.bz2 | ||||
| /firefox-112.0.1.source.tar.xz | ||||
| /firefox-langpacks-112.0.2-20230427.tar.xz | ||||
| /firefox-112.0.2.source.tar.xz | ||||
| /firefox-langpacks-113.0-20230509.tar.xz | ||||
| /firefox-113.0.source.tar.xz | ||||
|  | ||||
							
								
								
									
										22
									
								
								D172126.diff
									
									
									
									
									
								
							
							
						
						
									
										22
									
								
								D172126.diff
									
									
									
									
									
								
							| @ -1,22 +0,0 @@ | ||||
| diff --git a/dom/media/webaudio/AudioNodeEngineGeneric.h b/dom/media/webaudio/AudioNodeEngineGeneric.h
 | ||||
| --- a/dom/media/webaudio/AudioNodeEngineGeneric.h
 | ||||
| +++ b/dom/media/webaudio/AudioNodeEngineGeneric.h
 | ||||
| @@ -203,14 +203,14 @@
 | ||||
|      MOZ_ASSERT((aSize % xsimd::batch<float, Arch>::size == 0), | ||||
|                 "requires tail processing"); | ||||
|   | ||||
|      MOZ_UNROLL(2) | ||||
|      for (unsigned i = 0; i < aSize * 2; | ||||
| -         i += 2 * xsimd::batch<std::complex<float>>::size) {
 | ||||
| -      auto in1 = xsimd::batch<std::complex<float>>::load_aligned(
 | ||||
| +         i += 2 * xsimd::batch<std::complex<float>, Arch>::size) {
 | ||||
| +      auto in1 = xsimd::batch<std::complex<float>, Arch>::load_aligned(
 | ||||
|            reinterpret_cast<const std::complex<float>*>(&aInput[i])); | ||||
| -      auto in2 = xsimd::batch<std::complex<float>>::load_aligned(
 | ||||
| +      auto in2 = xsimd::batch<std::complex<float>, Arch>::load_aligned(
 | ||||
|            reinterpret_cast<const std::complex<float>*>(&aScale[i])); | ||||
|        auto out = in1 * in2; | ||||
|        out.store_aligned(reinterpret_cast<std::complex<float>*>(&aOutput[i])); | ||||
|      } | ||||
|    }; | ||||
| 
 | ||||
							
								
								
									
										736
									
								
								D172864.diff
									
									
									
									
									
								
							
							
						
						
									
										736
									
								
								D172864.diff
									
									
									
									
									
								
							| @ -1,736 +0,0 @@ | ||||
| diff --git a/dom/media/webaudio/AudioNodeEngineGeneric.h b/dom/media/webaudio/AudioNodeEngineGeneric.h
 | ||||
| --- a/dom/media/webaudio/AudioNodeEngineGeneric.h
 | ||||
| +++ b/dom/media/webaudio/AudioNodeEngineGeneric.h
 | ||||
| @@ -5,331 +5,54 @@
 | ||||
|   | ||||
|  #ifndef MOZILLA_AUDIONODEENGINEGENERIC_H_ | ||||
|  #define MOZILLA_AUDIONODEENGINEGENERIC_H_ | ||||
|   | ||||
|  #include "AudioNodeEngine.h" | ||||
| -#include "AlignmentUtils.h"
 | ||||
|   | ||||
|  #include "xsimd/xsimd.hpp" | ||||
|   | ||||
| -#if defined(__GNUC__) && __GNUC__ > 7
 | ||||
| -#  define MOZ_PRAGMA(tokens) _Pragma(#tokens)
 | ||||
| -#  define MOZ_UNROLL(factor) MOZ_PRAGMA(GCC unroll factor)
 | ||||
| -#elif defined(__INTEL_COMPILER) || (defined(__clang__) && __clang_major__ > 3)
 | ||||
| -#  define MOZ_PRAGMA(tokens) _Pragma(#tokens)
 | ||||
| -#  define MOZ_UNROLL(factor) MOZ_PRAGMA(unroll factor)
 | ||||
| -#else
 | ||||
| -#  define MOZ_UNROLL(_)
 | ||||
| -#endif
 | ||||
| -
 | ||||
|  namespace mozilla { | ||||
|   | ||||
|  template <class Arch> | ||||
| -static bool is_aligned(const void* ptr) {
 | ||||
| -  return (reinterpret_cast<uintptr_t>(ptr) &
 | ||||
| -          ~(static_cast<uintptr_t>(Arch::alignment()) - 1)) ==
 | ||||
| -         reinterpret_cast<uintptr_t>(ptr);
 | ||||
| -};
 | ||||
| -
 | ||||
| -template <class Arch>
 | ||||
|  struct Engine { | ||||
|    static void AudioBufferAddWithScale(const float* aInput, float aScale, | ||||
| -                                      float* aOutput, uint32_t aSize) {
 | ||||
| -    if constexpr (Arch::requires_alignment()) {
 | ||||
| -      if (aScale == 1.0f) {
 | ||||
| -        while (!is_aligned<Arch>(aInput) || !is_aligned<Arch>(aOutput)) {
 | ||||
| -          if (!aSize) return;
 | ||||
| -          *aOutput += *aInput;
 | ||||
| -          ++aOutput;
 | ||||
| -          ++aInput;
 | ||||
| -          --aSize;
 | ||||
| -        }
 | ||||
| -      } else {
 | ||||
| -        while (!is_aligned<Arch>(aInput) || !is_aligned<Arch>(aOutput)) {
 | ||||
| -          if (!aSize) return;
 | ||||
| -          *aOutput += *aInput * aScale;
 | ||||
| -          ++aOutput;
 | ||||
| -          ++aInput;
 | ||||
| -          --aSize;
 | ||||
| -        }
 | ||||
| -      }
 | ||||
| -    }
 | ||||
| -    MOZ_ASSERT(is_aligned<Arch>(aInput), "aInput is aligned");
 | ||||
| -    MOZ_ASSERT(is_aligned<Arch>(aOutput), "aOutput is aligned");
 | ||||
| -
 | ||||
| -    xsimd::batch<float, Arch> vgain(aScale);
 | ||||
| -
 | ||||
| -    uint32_t aVSize = aSize & ~(xsimd::batch<float, Arch>::size - 1);
 | ||||
| -    MOZ_UNROLL(4)
 | ||||
| -    for (unsigned i = 0; i < aVSize; i += xsimd::batch<float, Arch>::size) {
 | ||||
| -      auto vin1 = xsimd::batch<float, Arch>::load_aligned(&aInput[i]);
 | ||||
| -      auto vin2 = xsimd::batch<float, Arch>::load_aligned(&aOutput[i]);
 | ||||
| -      auto vout = xsimd::fma(vin1, vgain, vin2);
 | ||||
| -      vout.store_aligned(&aOutput[i]);
 | ||||
| -    }
 | ||||
| -
 | ||||
| -    for (unsigned i = aVSize; i < aSize; ++i) {
 | ||||
| -      aOutput[i] += aInput[i] * aScale;
 | ||||
| -    }
 | ||||
| -  };
 | ||||
| +                                      float* aOutput, uint32_t aSize);
 | ||||
|   | ||||
|    static void AudioBlockCopyChannelWithScale(const float* aInput, float aScale, | ||||
| -                                             float* aOutput) {
 | ||||
| -    MOZ_ASSERT(is_aligned<Arch>(aInput), "aInput is aligned");
 | ||||
| -    MOZ_ASSERT(is_aligned<Arch>(aOutput), "aOutput is aligned");
 | ||||
| -
 | ||||
| -    MOZ_ASSERT((WEBAUDIO_BLOCK_SIZE % xsimd::batch<float, Arch>::size == 0),
 | ||||
| -               "requires tail processing");
 | ||||
| -
 | ||||
| -    xsimd::batch<float, Arch> vgain = (aScale);
 | ||||
| -
 | ||||
| -    MOZ_UNROLL(4)
 | ||||
| -    for (unsigned i = 0; i < WEBAUDIO_BLOCK_SIZE;
 | ||||
| -         i += xsimd::batch<float, Arch>::size) {
 | ||||
| -      auto vin = xsimd::batch<float, Arch>::load_aligned(&aInput[i]);
 | ||||
| -      auto vout = vin * vgain;
 | ||||
| -      vout.store_aligned(&aOutput[i]);
 | ||||
| -    }
 | ||||
| -  };
 | ||||
| +                                             float* aOutput);
 | ||||
|   | ||||
|    static void AudioBlockCopyChannelWithScale( | ||||
|        const float aInput[WEBAUDIO_BLOCK_SIZE], | ||||
|        const float aScale[WEBAUDIO_BLOCK_SIZE], | ||||
| -      float aOutput[WEBAUDIO_BLOCK_SIZE]) {
 | ||||
| -    MOZ_ASSERT(is_aligned<Arch>(aInput), "aInput is aligned");
 | ||||
| -    MOZ_ASSERT(is_aligned<Arch>(aOutput), "aOutput is aligned");
 | ||||
| -    MOZ_ASSERT(is_aligned<Arch>(aScale), "aScale is aligned");
 | ||||
| -
 | ||||
| -    MOZ_ASSERT((WEBAUDIO_BLOCK_SIZE % xsimd::batch<float, Arch>::size == 0),
 | ||||
| -               "requires tail processing");
 | ||||
| -
 | ||||
| -    MOZ_UNROLL(4)
 | ||||
| -    for (unsigned i = 0; i < WEBAUDIO_BLOCK_SIZE;
 | ||||
| -         i += xsimd::batch<float, Arch>::size) {
 | ||||
| -      auto vscaled = xsimd::batch<float, Arch>::load_aligned(&aScale[i]);
 | ||||
| -      auto vin = xsimd::batch<float, Arch>::load_aligned(&aInput[i]);
 | ||||
| -      auto vout = vin * vscaled;
 | ||||
| -      vout.store_aligned(&aOutput[i]);
 | ||||
| -    }
 | ||||
| -  };
 | ||||
| +      float aOutput[WEBAUDIO_BLOCK_SIZE]);
 | ||||
|   | ||||
|    static void AudioBufferInPlaceScale(float* aBlock, float aScale, | ||||
| -                                      uint32_t aSize) {
 | ||||
| -    MOZ_ASSERT(is_aligned<Arch>(aBlock), "aBlock is aligned");
 | ||||
| -
 | ||||
| -    xsimd::batch<float, Arch> vgain(aScale);
 | ||||
| -
 | ||||
| -    uint32_t aVSize = aSize & ~(xsimd::batch<float, Arch>::size - 1);
 | ||||
| -    MOZ_UNROLL(4)
 | ||||
| -    for (unsigned i = 0; i < aVSize; i += xsimd::batch<float, Arch>::size) {
 | ||||
| -      auto vin = xsimd::batch<float, Arch>::load_aligned(&aBlock[i]);
 | ||||
| -      auto vout = vin * vgain;
 | ||||
| -      vout.store_aligned(&aBlock[i]);
 | ||||
| -    }
 | ||||
| -    for (unsigned i = aVSize; i < aSize; ++i) aBlock[i] *= aScale;
 | ||||
| -  };
 | ||||
| +                                      uint32_t aSize);
 | ||||
|   | ||||
|    static void AudioBufferInPlaceScale(float* aBlock, float* aScale, | ||||
| -                                      uint32_t aSize) {
 | ||||
| -    MOZ_ASSERT(is_aligned<Arch>(aBlock), "aBlock is aligned");
 | ||||
| -    MOZ_ASSERT(is_aligned<Arch>(aScale), "aScale is aligned");
 | ||||
| -
 | ||||
| -    uint32_t aVSize = aSize & ~(xsimd::batch<float, Arch>::size - 1);
 | ||||
| -    MOZ_UNROLL(4)
 | ||||
| -    for (unsigned i = 0; i < aVSize; i += xsimd::batch<float, Arch>::size) {
 | ||||
| -      auto vin = xsimd::batch<float, Arch>::load_aligned(&aBlock[i]);
 | ||||
| -      auto vgain = xsimd::batch<float, Arch>::load_aligned(&aScale[i]);
 | ||||
| -      auto vout = vin * vgain;
 | ||||
| -      vout.store_aligned(&aBlock[i]);
 | ||||
| -    }
 | ||||
| -    for (uint32_t i = aVSize; i < aSize; ++i) {
 | ||||
| -      *aBlock++ *= *aScale++;
 | ||||
| -    }
 | ||||
| -  };
 | ||||
| +                                      uint32_t aSize);
 | ||||
|   | ||||
|    static void AudioBlockPanStereoToStereo( | ||||
|        const float aInputL[WEBAUDIO_BLOCK_SIZE], | ||||
|        const float aInputR[WEBAUDIO_BLOCK_SIZE], float aGainL, float aGainR, | ||||
|        bool aIsOnTheLeft, float aOutputL[WEBAUDIO_BLOCK_SIZE], | ||||
| -      float aOutputR[WEBAUDIO_BLOCK_SIZE]) {
 | ||||
| -    MOZ_ASSERT(is_aligned<Arch>(aInputL), "aInputL is aligned");
 | ||||
| -    MOZ_ASSERT(is_aligned<Arch>(aInputR), "aInputR is aligned");
 | ||||
| -    MOZ_ASSERT(is_aligned<Arch>(aOutputL), "aOutputL is aligned");
 | ||||
| -    MOZ_ASSERT(is_aligned<Arch>(aOutputR), "aOutputR is aligned");
 | ||||
| -
 | ||||
| -    MOZ_ASSERT((WEBAUDIO_BLOCK_SIZE % xsimd::batch<float, Arch>::size == 0),
 | ||||
| -               "requires tail processing");
 | ||||
| -
 | ||||
| -    xsimd::batch<float, Arch> vgainl(aGainL);
 | ||||
| -    xsimd::batch<float, Arch> vgainr(aGainR);
 | ||||
| -
 | ||||
| -    if (aIsOnTheLeft) {
 | ||||
| -      MOZ_UNROLL(2)
 | ||||
| -      for (unsigned i = 0; i < WEBAUDIO_BLOCK_SIZE;
 | ||||
| -           i += xsimd::batch<float, Arch>::size) {
 | ||||
| -        auto vinl = xsimd::batch<float, Arch>::load_aligned(&aInputL[i]);
 | ||||
| -        auto vinr = xsimd::batch<float, Arch>::load_aligned(&aInputR[i]);
 | ||||
| -
 | ||||
| -        /* left channel : aOutputL  = aInputL + aInputR * gainL */
 | ||||
| -        auto vout = xsimd::fma(vinr, vgainl, vinl);
 | ||||
| -        vout.store_aligned(&aOutputL[i]);
 | ||||
| -
 | ||||
| -        /* right channel : aOutputR = aInputR * gainR */
 | ||||
| -        auto vscaled = vinr * vgainr;
 | ||||
| -        vscaled.store_aligned(&aOutputR[i]);
 | ||||
| -      }
 | ||||
| -    } else {
 | ||||
| -      MOZ_UNROLL(2)
 | ||||
| -      for (unsigned i = 0; i < WEBAUDIO_BLOCK_SIZE;
 | ||||
| -           i += xsimd::batch<float, Arch>::size) {
 | ||||
| -        auto vinl = xsimd::batch<float, Arch>::load_aligned(&aInputL[i]);
 | ||||
| -        auto vinr = xsimd::batch<float, Arch>::load_aligned(&aInputR[i]);
 | ||||
| -
 | ||||
| -        /* left channel : aInputL * gainL */
 | ||||
| -        auto vscaled = vinl * vgainl;
 | ||||
| -        vscaled.store_aligned(&aOutputL[i]);
 | ||||
| -
 | ||||
| -        /* right channel: aOutputR = aInputR + aInputL * gainR */
 | ||||
| -        auto vout = xsimd::fma(vinl, vgainr, vinr);
 | ||||
| -        vout.store_aligned(&aOutputR[i]);
 | ||||
| -      }
 | ||||
| -    }
 | ||||
| -  };
 | ||||
| +      float aOutputR[WEBAUDIO_BLOCK_SIZE]);
 | ||||
|   | ||||
|    static void BufferComplexMultiply(const float* aInput, const float* aScale, | ||||
| -                                    float* aOutput, uint32_t aSize) {
 | ||||
| -    MOZ_ASSERT(is_aligned<Arch>(aInput), "aInput is aligned");
 | ||||
| -    MOZ_ASSERT(is_aligned<Arch>(aOutput), "aOutput is aligned");
 | ||||
| -    MOZ_ASSERT(is_aligned<Arch>(aScale), "aScale is aligned");
 | ||||
| -    MOZ_ASSERT((aSize % xsimd::batch<float, Arch>::size == 0),
 | ||||
| -               "requires tail processing");
 | ||||
| -
 | ||||
| -    MOZ_UNROLL(2)
 | ||||
| -    for (unsigned i = 0; i < aSize * 2;
 | ||||
| -         i += 2 * xsimd::batch<std::complex<float>, Arch>::size) {
 | ||||
| -      auto in1 = xsimd::batch<std::complex<float>, Arch>::load_aligned(
 | ||||
| -          reinterpret_cast<const std::complex<float>*>(&aInput[i]));
 | ||||
| -      auto in2 = xsimd::batch<std::complex<float>, Arch>::load_aligned(
 | ||||
| -          reinterpret_cast<const std::complex<float>*>(&aScale[i]));
 | ||||
| -      auto out = in1 * in2;
 | ||||
| -      out.store_aligned(reinterpret_cast<std::complex<float>*>(&aOutput[i]));
 | ||||
| -    }
 | ||||
| -  };
 | ||||
| -
 | ||||
| -  static float AudioBufferSumOfSquares(const float* aInput, uint32_t aLength) {
 | ||||
| -    float sum = 0.f;
 | ||||
| -
 | ||||
| -    if constexpr (Arch::requires_alignment()) {
 | ||||
| -      while (!is_aligned<Arch>(aInput)) {
 | ||||
| -        if (!aLength) {
 | ||||
| -          return sum;
 | ||||
| -        }
 | ||||
| -        sum += *aInput * *aInput;
 | ||||
| -        ++aInput;
 | ||||
| -        --aLength;
 | ||||
| -      }
 | ||||
| -    }
 | ||||
| -
 | ||||
| -    MOZ_ASSERT(is_aligned<Arch>(aInput), "aInput is aligned");
 | ||||
| -
 | ||||
| -    constexpr uint32_t unroll_factor = 4;
 | ||||
| -    xsimd::batch<float, Arch> accs[unroll_factor] = {0.f, 0.f, 0.f, 0.f};
 | ||||
| -
 | ||||
| -    uint32_t vLength =
 | ||||
| -        aLength & ~(unroll_factor * xsimd::batch<float, Arch>::size - 1);
 | ||||
| +                                    float* aOutput, uint32_t aSize);
 | ||||
|   | ||||
| -    for (uint32_t i = 0; i < vLength;
 | ||||
| -         i += unroll_factor * xsimd::batch<float, Arch>::size) {
 | ||||
| -      MOZ_UNROLL(4)
 | ||||
| -      for (uint32_t j = 0; j < unroll_factor; ++j) {
 | ||||
| -        auto in = xsimd::batch<float, Arch>::load_aligned(
 | ||||
| -            &aInput[i + xsimd::batch<float, Arch>::size * j]);
 | ||||
| -        accs[j] = xsimd::fma(in, in, accs[j]);
 | ||||
| -      }
 | ||||
| -    }
 | ||||
| -
 | ||||
| -    sum += reduce_add((accs[0] + accs[1]) + (accs[2] + accs[3]));
 | ||||
| -    for (uint32_t i = vLength; i < aLength; ++i) sum += aInput[i] * aInput[i];
 | ||||
| -    return sum;
 | ||||
| -  };
 | ||||
| +  static float AudioBufferSumOfSquares(const float* aInput, uint32_t aLength);
 | ||||
|   | ||||
| -  static void NaNToZeroInPlace(float* aSamples, size_t aCount) {
 | ||||
| -    if constexpr (Arch::requires_alignment()) {
 | ||||
| -      while (!is_aligned<Arch>(aSamples)) {
 | ||||
| -        if (!aCount) {
 | ||||
| -          return;
 | ||||
| -        }
 | ||||
| -        if (*aSamples != *aSamples) {
 | ||||
| -          *aSamples = 0.0;
 | ||||
| -        }
 | ||||
| -        ++aSamples;
 | ||||
| -        --aCount;
 | ||||
| -      }
 | ||||
| -    }
 | ||||
| -
 | ||||
| -    MOZ_ASSERT(is_aligned<Arch>(aSamples), "aSamples is aligned");
 | ||||
| -
 | ||||
| -    uint32_t vCount = aCount & ~(xsimd::batch<float, Arch>::size - 1);
 | ||||
| -
 | ||||
| -    MOZ_UNROLL(4)
 | ||||
| -    for (uint32_t i = 0; i < vCount; i += xsimd::batch<float, Arch>::size) {
 | ||||
| -      auto vin = xsimd::batch<float, Arch>::load_aligned(&aSamples[i]);
 | ||||
| -      auto vout =
 | ||||
| -          xsimd::select(xsimd::isnan(vin), xsimd::batch<float, Arch>(0.f), vin);
 | ||||
| -      vout.store_aligned(&aSamples[i]);
 | ||||
| -    }
 | ||||
| -
 | ||||
| -    for (uint32_t i = vCount; i < aCount; i++) {
 | ||||
| -      if (aSamples[i] != aSamples[i]) {
 | ||||
| -        aSamples[i] = 0.0;
 | ||||
| -      }
 | ||||
| -    }
 | ||||
| -  };
 | ||||
| +  static void NaNToZeroInPlace(float* aSamples, size_t aCount);
 | ||||
|   | ||||
|    static void AudioBlockPanStereoToStereo( | ||||
|        const float aInputL[WEBAUDIO_BLOCK_SIZE], | ||||
|        const float aInputR[WEBAUDIO_BLOCK_SIZE], | ||||
|        const float aGainL[WEBAUDIO_BLOCK_SIZE], | ||||
|        const float aGainR[WEBAUDIO_BLOCK_SIZE], | ||||
|        const bool aIsOnTheLeft[WEBAUDIO_BLOCK_SIZE], | ||||
| -      float aOutputL[WEBAUDIO_BLOCK_SIZE],
 | ||||
| -      float aOutputR[WEBAUDIO_BLOCK_SIZE]) {
 | ||||
| -    MOZ_ASSERT(is_aligned<Arch>(aInputL), "aInputL is aligned");
 | ||||
| -    MOZ_ASSERT(is_aligned<Arch>(aInputR), "aInputR is aligned");
 | ||||
| -    MOZ_ASSERT(is_aligned<Arch>(aGainL), "aGainL is aligned");
 | ||||
| -    MOZ_ASSERT(is_aligned<Arch>(aGainR), "aGainR is aligned");
 | ||||
| -    MOZ_ASSERT(is_aligned<Arch>(aIsOnTheLeft), "aIsOnTheLeft is aligned");
 | ||||
| -    MOZ_ASSERT(is_aligned<Arch>(aOutputL), "aOutputL is aligned");
 | ||||
| -    MOZ_ASSERT(is_aligned<Arch>(aOutputR), "aOutputR is aligned");
 | ||||
| -
 | ||||
| -    MOZ_ASSERT((WEBAUDIO_BLOCK_SIZE % xsimd::batch<float, Arch>::size == 0),
 | ||||
| -               "requires tail processing");
 | ||||
| -
 | ||||
| -    MOZ_UNROLL(2)
 | ||||
| -    for (uint32_t i = 0; i < WEBAUDIO_BLOCK_SIZE;
 | ||||
| -         i += xsimd::batch<float, Arch>::size) {
 | ||||
| -      auto mask =
 | ||||
| -          xsimd::batch_bool<float, Arch>::load_aligned(&aIsOnTheLeft[i]);
 | ||||
| -
 | ||||
| -      auto inputL = xsimd::batch<float, Arch>::load_aligned(&aInputL[i]);
 | ||||
| -      auto inputR = xsimd::batch<float, Arch>::load_aligned(&aInputR[i]);
 | ||||
| -      auto gainL = xsimd::batch<float, Arch>::load_aligned(&aGainL[i]);
 | ||||
| -      auto gainR = xsimd::batch<float, Arch>::load_aligned(&aGainR[i]);
 | ||||
| -
 | ||||
| -      auto outL_true = xsimd::fma(inputR, gainL, inputL);
 | ||||
| -      auto outR_true = inputR * gainR;
 | ||||
| -
 | ||||
| -      auto outL_false = inputL * gainL;
 | ||||
| -      auto outR_false = xsimd::fma(inputL, gainR, inputR);
 | ||||
| -
 | ||||
| -      auto outL = xsimd::select(mask, outL_true, outL_false);
 | ||||
| -      auto outR = xsimd::select(mask, outR_true, outR_false);
 | ||||
| -
 | ||||
| -      outL.store_aligned(&aOutputL[i]);
 | ||||
| -      outR.store_aligned(&aOutputR[i]);
 | ||||
| -    }
 | ||||
| -  }
 | ||||
| +      float aOutputL[WEBAUDIO_BLOCK_SIZE], float aOutputR[WEBAUDIO_BLOCK_SIZE]);
 | ||||
|  }; | ||||
|   | ||||
|  }  // namespace mozilla | ||||
|   | ||||
|  #endif | ||||
| diff --git a/dom/media/webaudio/AudioNodeEngineGenericImpl.h b/dom/media/webaudio/AudioNodeEngineGenericImpl.h
 | ||||
| new file mode 100644 | ||||
| --- /dev/null
 | ||||
| +++ b/dom/media/webaudio/AudioNodeEngineGenericImpl.h
 | ||||
| @@ -0,0 +1,341 @@
 | ||||
| +/* -*- mode: c++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 | ||||
| +/* this source code form is subject to the terms of the mozilla public
 | ||||
| + * license, v. 2.0. if a copy of the mpl was not distributed with this file,
 | ||||
| + * You can obtain one at http://mozilla.org/MPL/2.0/. */
 | ||||
| +
 | ||||
| +#ifndef MOZILLA_AUDIONODEENGINEGENERICIMPL_H_
 | ||||
| +#define MOZILLA_AUDIONODEENGINEGENERICIMPL_H_
 | ||||
| +
 | ||||
| +#include "AudioNodeEngineGeneric.h"
 | ||||
| +#include "AlignmentUtils.h"
 | ||||
| +
 | ||||
| +#if defined(__GNUC__) && __GNUC__ > 7
 | ||||
| +#  define MOZ_PRAGMA(tokens) _Pragma(#tokens)
 | ||||
| +#  define MOZ_UNROLL(factor) MOZ_PRAGMA(GCC unroll factor)
 | ||||
| +#elif defined(__INTEL_COMPILER) || (defined(__clang__) && __clang_major__ > 3)
 | ||||
| +#  define MOZ_PRAGMA(tokens) _Pragma(#tokens)
 | ||||
| +#  define MOZ_UNROLL(factor) MOZ_PRAGMA(unroll factor)
 | ||||
| +#else
 | ||||
| +#  define MOZ_UNROLL(_)
 | ||||
| +#endif
 | ||||
| +
 | ||||
| +namespace mozilla {
 | ||||
| +
 | ||||
| +template <class Arch>
 | ||||
| +static bool is_aligned(const void* ptr) {
 | ||||
| +  return (reinterpret_cast<uintptr_t>(ptr) &
 | ||||
| +          ~(static_cast<uintptr_t>(Arch::alignment()) - 1)) ==
 | ||||
| +         reinterpret_cast<uintptr_t>(ptr);
 | ||||
| +};
 | ||||
| +
 | ||||
| +template <class Arch>
 | ||||
| +void Engine<Arch>::AudioBufferAddWithScale(const float* aInput, float aScale,
 | ||||
| +                                           float* aOutput, uint32_t aSize) {
 | ||||
| +  if constexpr (Arch::requires_alignment()) {
 | ||||
| +    if (aScale == 1.0f) {
 | ||||
| +      while (!is_aligned<Arch>(aInput) || !is_aligned<Arch>(aOutput)) {
 | ||||
| +        if (!aSize) return;
 | ||||
| +        *aOutput += *aInput;
 | ||||
| +        ++aOutput;
 | ||||
| +        ++aInput;
 | ||||
| +        --aSize;
 | ||||
| +      }
 | ||||
| +    } else {
 | ||||
| +      while (!is_aligned<Arch>(aInput) || !is_aligned<Arch>(aOutput)) {
 | ||||
| +        if (!aSize) return;
 | ||||
| +        *aOutput += *aInput * aScale;
 | ||||
| +        ++aOutput;
 | ||||
| +        ++aInput;
 | ||||
| +        --aSize;
 | ||||
| +      }
 | ||||
| +    }
 | ||||
| +  }
 | ||||
| +  MOZ_ASSERT(is_aligned<Arch>(aInput), "aInput is aligned");
 | ||||
| +  MOZ_ASSERT(is_aligned<Arch>(aOutput), "aOutput is aligned");
 | ||||
| +
 | ||||
| +  xsimd::batch<float, Arch> vgain(aScale);
 | ||||
| +
 | ||||
| +  uint32_t aVSize = aSize & ~(xsimd::batch<float, Arch>::size - 1);
 | ||||
| +  MOZ_UNROLL(4)
 | ||||
| +  for (unsigned i = 0; i < aVSize; i += xsimd::batch<float, Arch>::size) {
 | ||||
| +    auto vin1 = xsimd::batch<float, Arch>::load_aligned(&aInput[i]);
 | ||||
| +    auto vin2 = xsimd::batch<float, Arch>::load_aligned(&aOutput[i]);
 | ||||
| +    auto vout = xsimd::fma(vin1, vgain, vin2);
 | ||||
| +    vout.store_aligned(&aOutput[i]);
 | ||||
| +  }
 | ||||
| +
 | ||||
| +  for (unsigned i = aVSize; i < aSize; ++i) {
 | ||||
| +    aOutput[i] += aInput[i] * aScale;
 | ||||
| +  }
 | ||||
| +}
 | ||||
| +
 | ||||
| +template <class Arch>
 | ||||
| +void Engine<Arch>::AudioBlockCopyChannelWithScale(const float* aInput,
 | ||||
| +                                                  float aScale,
 | ||||
| +                                                  float* aOutput) {
 | ||||
| +  MOZ_ASSERT(is_aligned<Arch>(aInput), "aInput is aligned");
 | ||||
| +  MOZ_ASSERT(is_aligned<Arch>(aOutput), "aOutput is aligned");
 | ||||
| +
 | ||||
| +  MOZ_ASSERT((WEBAUDIO_BLOCK_SIZE % xsimd::batch<float, Arch>::size == 0),
 | ||||
| +             "requires tail processing");
 | ||||
| +
 | ||||
| +  xsimd::batch<float, Arch> vgain = (aScale);
 | ||||
| +
 | ||||
| +  MOZ_UNROLL(4)
 | ||||
| +  for (unsigned i = 0; i < WEBAUDIO_BLOCK_SIZE;
 | ||||
| +       i += xsimd::batch<float, Arch>::size) {
 | ||||
| +    auto vin = xsimd::batch<float, Arch>::load_aligned(&aInput[i]);
 | ||||
| +    auto vout = vin * vgain;
 | ||||
| +    vout.store_aligned(&aOutput[i]);
 | ||||
| +  }
 | ||||
| +};
 | ||||
| +
 | ||||
| +template <class Arch>
 | ||||
| +void Engine<Arch>::AudioBlockCopyChannelWithScale(
 | ||||
| +    const float aInput[WEBAUDIO_BLOCK_SIZE],
 | ||||
| +    const float aScale[WEBAUDIO_BLOCK_SIZE],
 | ||||
| +    float aOutput[WEBAUDIO_BLOCK_SIZE]) {
 | ||||
| +  MOZ_ASSERT(is_aligned<Arch>(aInput), "aInput is aligned");
 | ||||
| +  MOZ_ASSERT(is_aligned<Arch>(aOutput), "aOutput is aligned");
 | ||||
| +  MOZ_ASSERT(is_aligned<Arch>(aScale), "aScale is aligned");
 | ||||
| +
 | ||||
| +  MOZ_ASSERT((WEBAUDIO_BLOCK_SIZE % xsimd::batch<float, Arch>::size == 0),
 | ||||
| +             "requires tail processing");
 | ||||
| +
 | ||||
| +  MOZ_UNROLL(4)
 | ||||
| +  for (unsigned i = 0; i < WEBAUDIO_BLOCK_SIZE;
 | ||||
| +       i += xsimd::batch<float, Arch>::size) {
 | ||||
| +    auto vscaled = xsimd::batch<float, Arch>::load_aligned(&aScale[i]);
 | ||||
| +    auto vin = xsimd::batch<float, Arch>::load_aligned(&aInput[i]);
 | ||||
| +    auto vout = vin * vscaled;
 | ||||
| +    vout.store_aligned(&aOutput[i]);
 | ||||
| +  }
 | ||||
| +};
 | ||||
| +
 | ||||
| +template <class Arch>
 | ||||
| +void Engine<Arch>::AudioBufferInPlaceScale(float* aBlock, float aScale,
 | ||||
| +                                           uint32_t aSize) {
 | ||||
| +  MOZ_ASSERT(is_aligned<Arch>(aBlock), "aBlock is aligned");
 | ||||
| +
 | ||||
| +  xsimd::batch<float, Arch> vgain(aScale);
 | ||||
| +
 | ||||
| +  uint32_t aVSize = aSize & ~(xsimd::batch<float, Arch>::size - 1);
 | ||||
| +  MOZ_UNROLL(4)
 | ||||
| +  for (unsigned i = 0; i < aVSize; i += xsimd::batch<float, Arch>::size) {
 | ||||
| +    auto vin = xsimd::batch<float, Arch>::load_aligned(&aBlock[i]);
 | ||||
| +    auto vout = vin * vgain;
 | ||||
| +    vout.store_aligned(&aBlock[i]);
 | ||||
| +  }
 | ||||
| +  for (unsigned i = aVSize; i < aSize; ++i) aBlock[i] *= aScale;
 | ||||
| +};
 | ||||
| +
 | ||||
| +template <class Arch>
 | ||||
| +void Engine<Arch>::AudioBufferInPlaceScale(float* aBlock, float* aScale,
 | ||||
| +                                           uint32_t aSize) {
 | ||||
| +  MOZ_ASSERT(is_aligned<Arch>(aBlock), "aBlock is aligned");
 | ||||
| +  MOZ_ASSERT(is_aligned<Arch>(aScale), "aScale is aligned");
 | ||||
| +
 | ||||
| +  uint32_t aVSize = aSize & ~(xsimd::batch<float, Arch>::size - 1);
 | ||||
| +  MOZ_UNROLL(4)
 | ||||
| +  for (unsigned i = 0; i < aVSize; i += xsimd::batch<float, Arch>::size) {
 | ||||
| +    auto vin = xsimd::batch<float, Arch>::load_aligned(&aBlock[i]);
 | ||||
| +    auto vgain = xsimd::batch<float, Arch>::load_aligned(&aScale[i]);
 | ||||
| +    auto vout = vin * vgain;
 | ||||
| +    vout.store_aligned(&aBlock[i]);
 | ||||
| +  }
 | ||||
| +  for (uint32_t i = aVSize; i < aSize; ++i) {
 | ||||
| +    *aBlock++ *= *aScale++;
 | ||||
| +  }
 | ||||
| +};
 | ||||
| +
 | ||||
| +template <class Arch>
 | ||||
| +void Engine<Arch>::AudioBlockPanStereoToStereo(
 | ||||
| +    const float aInputL[WEBAUDIO_BLOCK_SIZE],
 | ||||
| +    const float aInputR[WEBAUDIO_BLOCK_SIZE], float aGainL, float aGainR,
 | ||||
| +    bool aIsOnTheLeft, float aOutputL[WEBAUDIO_BLOCK_SIZE],
 | ||||
| +    float aOutputR[WEBAUDIO_BLOCK_SIZE]) {
 | ||||
| +  MOZ_ASSERT(is_aligned<Arch>(aInputL), "aInputL is aligned");
 | ||||
| +  MOZ_ASSERT(is_aligned<Arch>(aInputR), "aInputR is aligned");
 | ||||
| +  MOZ_ASSERT(is_aligned<Arch>(aOutputL), "aOutputL is aligned");
 | ||||
| +  MOZ_ASSERT(is_aligned<Arch>(aOutputR), "aOutputR is aligned");
 | ||||
| +
 | ||||
| +  MOZ_ASSERT((WEBAUDIO_BLOCK_SIZE % xsimd::batch<float, Arch>::size == 0),
 | ||||
| +             "requires tail processing");
 | ||||
| +
 | ||||
| +  xsimd::batch<float, Arch> vgainl(aGainL);
 | ||||
| +  xsimd::batch<float, Arch> vgainr(aGainR);
 | ||||
| +
 | ||||
| +  if (aIsOnTheLeft) {
 | ||||
| +    MOZ_UNROLL(2)
 | ||||
| +    for (unsigned i = 0; i < WEBAUDIO_BLOCK_SIZE;
 | ||||
| +         i += xsimd::batch<float, Arch>::size) {
 | ||||
| +      auto vinl = xsimd::batch<float, Arch>::load_aligned(&aInputL[i]);
 | ||||
| +      auto vinr = xsimd::batch<float, Arch>::load_aligned(&aInputR[i]);
 | ||||
| +
 | ||||
| +      /* left channel : aOutputL  = aInputL + aInputR * gainL */
 | ||||
| +      auto vout = xsimd::fma(vinr, vgainl, vinl);
 | ||||
| +      vout.store_aligned(&aOutputL[i]);
 | ||||
| +
 | ||||
| +      /* right channel : aOutputR = aInputR * gainR */
 | ||||
| +      auto vscaled = vinr * vgainr;
 | ||||
| +      vscaled.store_aligned(&aOutputR[i]);
 | ||||
| +    }
 | ||||
| +  } else {
 | ||||
| +    MOZ_UNROLL(2)
 | ||||
| +    for (unsigned i = 0; i < WEBAUDIO_BLOCK_SIZE;
 | ||||
| +         i += xsimd::batch<float, Arch>::size) {
 | ||||
| +      auto vinl = xsimd::batch<float, Arch>::load_aligned(&aInputL[i]);
 | ||||
| +      auto vinr = xsimd::batch<float, Arch>::load_aligned(&aInputR[i]);
 | ||||
| +
 | ||||
| +      /* left channel : aInputL * gainL */
 | ||||
| +      auto vscaled = vinl * vgainl;
 | ||||
| +      vscaled.store_aligned(&aOutputL[i]);
 | ||||
| +
 | ||||
| +      /* right channel: aOutputR = aInputR + aInputL * gainR */
 | ||||
| +      auto vout = xsimd::fma(vinl, vgainr, vinr);
 | ||||
| +      vout.store_aligned(&aOutputR[i]);
 | ||||
| +    }
 | ||||
| +  }
 | ||||
| +};
 | ||||
| +
 | ||||
| +template <class Arch>
 | ||||
| +void Engine<Arch>::BufferComplexMultiply(const float* aInput,
 | ||||
| +                                         const float* aScale, float* aOutput,
 | ||||
| +                                         uint32_t aSize) {
 | ||||
| +  MOZ_ASSERT(is_aligned<Arch>(aInput), "aInput is aligned");
 | ||||
| +  MOZ_ASSERT(is_aligned<Arch>(aOutput), "aOutput is aligned");
 | ||||
| +  MOZ_ASSERT(is_aligned<Arch>(aScale), "aScale is aligned");
 | ||||
| +  MOZ_ASSERT((aSize % xsimd::batch<float, Arch>::size == 0),
 | ||||
| +             "requires tail processing");
 | ||||
| +
 | ||||
| +  MOZ_UNROLL(2)
 | ||||
| +  for (unsigned i = 0; i < aSize * 2;
 | ||||
| +       i += 2 * xsimd::batch<std::complex<float>, Arch>::size) {
 | ||||
| +    auto in1 = xsimd::batch<std::complex<float>, Arch>::load_aligned(
 | ||||
| +        reinterpret_cast<const std::complex<float>*>(&aInput[i]));
 | ||||
| +    auto in2 = xsimd::batch<std::complex<float>, Arch>::load_aligned(
 | ||||
| +        reinterpret_cast<const std::complex<float>*>(&aScale[i]));
 | ||||
| +    auto out = in1 * in2;
 | ||||
| +    out.store_aligned(reinterpret_cast<std::complex<float>*>(&aOutput[i]));
 | ||||
| +  }
 | ||||
| +};
 | ||||
| +
 | ||||
| +template <class Arch>
 | ||||
| +float Engine<Arch>::AudioBufferSumOfSquares(const float* aInput,
 | ||||
| +                                            uint32_t aLength) {
 | ||||
| +  float sum = 0.f;
 | ||||
| +
 | ||||
| +  if constexpr (Arch::requires_alignment()) {
 | ||||
| +    while (!is_aligned<Arch>(aInput)) {
 | ||||
| +      if (!aLength) {
 | ||||
| +        return sum;
 | ||||
| +      }
 | ||||
| +      sum += *aInput * *aInput;
 | ||||
| +      ++aInput;
 | ||||
| +      --aLength;
 | ||||
| +    }
 | ||||
| +  }
 | ||||
| +
 | ||||
| +  MOZ_ASSERT(is_aligned<Arch>(aInput), "aInput is aligned");
 | ||||
| +
 | ||||
| +  constexpr uint32_t unroll_factor = 4;
 | ||||
| +  xsimd::batch<float, Arch> accs[unroll_factor] = {0.f, 0.f, 0.f, 0.f};
 | ||||
| +
 | ||||
| +  uint32_t vLength =
 | ||||
| +      aLength & ~(unroll_factor * xsimd::batch<float, Arch>::size - 1);
 | ||||
| +
 | ||||
| +  for (uint32_t i = 0; i < vLength;
 | ||||
| +       i += unroll_factor * xsimd::batch<float, Arch>::size) {
 | ||||
| +    MOZ_UNROLL(4)
 | ||||
| +    for (uint32_t j = 0; j < unroll_factor; ++j) {
 | ||||
| +      auto in = xsimd::batch<float, Arch>::load_aligned(
 | ||||
| +          &aInput[i + xsimd::batch<float, Arch>::size * j]);
 | ||||
| +      accs[j] = xsimd::fma(in, in, accs[j]);
 | ||||
| +    }
 | ||||
| +  }
 | ||||
| +
 | ||||
| +  sum += reduce_add((accs[0] + accs[1]) + (accs[2] + accs[3]));
 | ||||
| +  for (uint32_t i = vLength; i < aLength; ++i) sum += aInput[i] * aInput[i];
 | ||||
| +  return sum;
 | ||||
| +};
 | ||||
| +
 | ||||
| +template <class Arch>
 | ||||
| +void Engine<Arch>::NaNToZeroInPlace(float* aSamples, size_t aCount) {
 | ||||
| +  if constexpr (Arch::requires_alignment()) {
 | ||||
| +    while (!is_aligned<Arch>(aSamples)) {
 | ||||
| +      if (!aCount) {
 | ||||
| +        return;
 | ||||
| +      }
 | ||||
| +      if (*aSamples != *aSamples) {
 | ||||
| +        *aSamples = 0.0;
 | ||||
| +      }
 | ||||
| +      ++aSamples;
 | ||||
| +      --aCount;
 | ||||
| +    }
 | ||||
| +  }
 | ||||
| +
 | ||||
| +  MOZ_ASSERT(is_aligned<Arch>(aSamples), "aSamples is aligned");
 | ||||
| +
 | ||||
| +  uint32_t vCount = aCount & ~(xsimd::batch<float, Arch>::size - 1);
 | ||||
| +
 | ||||
| +  MOZ_UNROLL(4)
 | ||||
| +  for (uint32_t i = 0; i < vCount; i += xsimd::batch<float, Arch>::size) {
 | ||||
| +    auto vin = xsimd::batch<float, Arch>::load_aligned(&aSamples[i]);
 | ||||
| +    auto vout =
 | ||||
| +        xsimd::select(xsimd::isnan(vin), xsimd::batch<float, Arch>(0.f), vin);
 | ||||
| +    vout.store_aligned(&aSamples[i]);
 | ||||
| +  }
 | ||||
| +
 | ||||
| +  for (uint32_t i = vCount; i < aCount; i++) {
 | ||||
| +    if (aSamples[i] != aSamples[i]) {
 | ||||
| +      aSamples[i] = 0.0;
 | ||||
| +    }
 | ||||
| +  }
 | ||||
| +};
 | ||||
| +
 | ||||
| +template <class Arch>
 | ||||
| +void Engine<Arch>::AudioBlockPanStereoToStereo(
 | ||||
| +    const float aInputL[WEBAUDIO_BLOCK_SIZE],
 | ||||
| +    const float aInputR[WEBAUDIO_BLOCK_SIZE],
 | ||||
| +    const float aGainL[WEBAUDIO_BLOCK_SIZE],
 | ||||
| +    const float aGainR[WEBAUDIO_BLOCK_SIZE],
 | ||||
| +    const bool aIsOnTheLeft[WEBAUDIO_BLOCK_SIZE],
 | ||||
| +    float aOutputL[WEBAUDIO_BLOCK_SIZE], float aOutputR[WEBAUDIO_BLOCK_SIZE]) {
 | ||||
| +  MOZ_ASSERT(is_aligned<Arch>(aInputL), "aInputL is aligned");
 | ||||
| +  MOZ_ASSERT(is_aligned<Arch>(aInputR), "aInputR is aligned");
 | ||||
| +  MOZ_ASSERT(is_aligned<Arch>(aGainL), "aGainL is aligned");
 | ||||
| +  MOZ_ASSERT(is_aligned<Arch>(aGainR), "aGainR is aligned");
 | ||||
| +  MOZ_ASSERT(is_aligned<Arch>(aIsOnTheLeft), "aIsOnTheLeft is aligned");
 | ||||
| +  MOZ_ASSERT(is_aligned<Arch>(aOutputL), "aOutputL is aligned");
 | ||||
| +  MOZ_ASSERT(is_aligned<Arch>(aOutputR), "aOutputR is aligned");
 | ||||
| +
 | ||||
| +  MOZ_ASSERT((WEBAUDIO_BLOCK_SIZE % xsimd::batch<float, Arch>::size == 0),
 | ||||
| +             "requires tail processing");
 | ||||
| +
 | ||||
| +  MOZ_UNROLL(2)
 | ||||
| +  for (uint32_t i = 0; i < WEBAUDIO_BLOCK_SIZE;
 | ||||
| +       i += xsimd::batch<float, Arch>::size) {
 | ||||
| +    auto mask = xsimd::batch_bool<float, Arch>::load_aligned(&aIsOnTheLeft[i]);
 | ||||
| +
 | ||||
| +    auto inputL = xsimd::batch<float, Arch>::load_aligned(&aInputL[i]);
 | ||||
| +    auto inputR = xsimd::batch<float, Arch>::load_aligned(&aInputR[i]);
 | ||||
| +    auto gainL = xsimd::batch<float, Arch>::load_aligned(&aGainL[i]);
 | ||||
| +    auto gainR = xsimd::batch<float, Arch>::load_aligned(&aGainR[i]);
 | ||||
| +
 | ||||
| +    auto outL_true = xsimd::fma(inputR, gainL, inputL);
 | ||||
| +    auto outR_true = inputR * gainR;
 | ||||
| +
 | ||||
| +    auto outL_false = inputL * gainL;
 | ||||
| +    auto outR_false = xsimd::fma(inputL, gainR, inputR);
 | ||||
| +
 | ||||
| +    auto outL = xsimd::select(mask, outL_true, outL_false);
 | ||||
| +    auto outR = xsimd::select(mask, outR_true, outR_false);
 | ||||
| +
 | ||||
| +    outL.store_aligned(&aOutputL[i]);
 | ||||
| +    outR.store_aligned(&aOutputR[i]);
 | ||||
| +  }
 | ||||
| +}
 | ||||
| +
 | ||||
| +}  // namespace mozilla
 | ||||
| +
 | ||||
| +#endif
 | ||||
| diff --git a/dom/media/webaudio/AudioNodeEngineNEON.cpp b/dom/media/webaudio/AudioNodeEngineNEON.cpp
 | ||||
| --- a/dom/media/webaudio/AudioNodeEngineNEON.cpp
 | ||||
| +++ b/dom/media/webaudio/AudioNodeEngineNEON.cpp
 | ||||
| @@ -1,9 +1,9 @@
 | ||||
|  /* -*- mode: c++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ | ||||
|  /* this source code form is subject to the terms of the mozilla public | ||||
|   * license, v. 2.0. if a copy of the mpl was not distributed with this file, | ||||
|   * You can obtain one at http://mozilla.org/MPL/2.0/. */ | ||||
|   | ||||
| -#include "AudioNodeEngineGeneric.h"
 | ||||
| +#include "AudioNodeEngineGenericImpl.h"
 | ||||
|  namespace mozilla { | ||||
|  template struct Engine<xsimd::neon>; | ||||
|  }  // namespace mozilla | ||||
| diff --git a/dom/media/webaudio/AudioNodeEngineSSE2.cpp b/dom/media/webaudio/AudioNodeEngineSSE2.cpp
 | ||||
| --- a/dom/media/webaudio/AudioNodeEngineSSE2.cpp
 | ||||
| +++ b/dom/media/webaudio/AudioNodeEngineSSE2.cpp
 | ||||
| @@ -1,10 +1,10 @@
 | ||||
|  /* -*- mode: c++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ | ||||
|  /* this source code form is subject to the terms of the mozilla public | ||||
|   * license, v. 2.0. if a copy of the mpl was not distributed with this file, | ||||
|   * You can obtain one at http://mozilla.org/MPL/2.0/. */ | ||||
|   | ||||
| -#include "AudioNodeEngineGeneric.h"
 | ||||
| +#include "AudioNodeEngineGenericImpl.h"
 | ||||
|   | ||||
|  namespace mozilla { | ||||
|  template struct Engine<xsimd::sse2>; | ||||
|  }  // namespace mozilla | ||||
| diff --git a/dom/media/webaudio/AudioNodeEngineSSE4_2_FMA3.cpp b/dom/media/webaudio/AudioNodeEngineSSE4_2_FMA3.cpp
 | ||||
| --- a/dom/media/webaudio/AudioNodeEngineSSE4_2_FMA3.cpp
 | ||||
| +++ b/dom/media/webaudio/AudioNodeEngineSSE4_2_FMA3.cpp
 | ||||
| @@ -1,10 +1,10 @@
 | ||||
|  /* -*- mode: c++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ | ||||
|  /* this source code form is subject to the terms of the mozilla public | ||||
|   * license, v. 2.0. if a copy of the mpl was not distributed with this file, | ||||
|   * You can obtain one at http://mozilla.org/MPL/2.0/. */ | ||||
|   | ||||
| -#include "AudioNodeEngineGeneric.h"
 | ||||
| +#include "AudioNodeEngineGenericImpl.h"
 | ||||
|   | ||||
|  namespace mozilla { | ||||
|  template struct Engine<xsimd::fma3<xsimd::sse4_2>>; | ||||
|  }  // namespace mozilla | ||||
| 
 | ||||
							
								
								
									
										82
									
								
								D173814.diff
									
									
									
									
									
								
							
							
						
						
									
										82
									
								
								D173814.diff
									
									
									
									
									
								
							| @ -1,82 +0,0 @@ | ||||
| diff --git a/widget/gtk/MozContainerWayland.h b/widget/gtk/MozContainerWayland.h
 | ||||
| --- a/widget/gtk/MozContainerWayland.h
 | ||||
| +++ b/widget/gtk/MozContainerWayland.h
 | ||||
| @@ -83,10 +83,13 @@
 | ||||
|                                                          nsIntSize aSize, | ||||
|                                                          int scale); | ||||
|  void moz_container_wayland_set_scale_factor(MozContainer* container); | ||||
|  void moz_container_wayland_set_scale_factor_locked( | ||||
|      const mozilla::MutexAutoLock& aProofOfLock, MozContainer* container); | ||||
| +bool moz_container_wayland_size_matches_scale_factor_locked(
 | ||||
| +    const mozilla::MutexAutoLock& aProofOfLock, MozContainer* container,
 | ||||
| +    int aWidth, int aHeight);
 | ||||
|   | ||||
|  void moz_container_wayland_add_initial_draw_callback_locked( | ||||
|      MozContainer* container, const std::function<void(void)>& initial_draw_cb); | ||||
|  void moz_container_wayland_add_or_fire_initial_draw_callback( | ||||
|      MozContainer* container, const std::function<void(void)>& initial_draw_cb); | ||||
| diff --git a/widget/gtk/MozContainerWayland.cpp b/widget/gtk/MozContainerWayland.cpp
 | ||||
| --- a/widget/gtk/MozContainerWayland.cpp
 | ||||
| +++ b/widget/gtk/MozContainerWayland.cpp
 | ||||
| @@ -595,10 +595,17 @@
 | ||||
|    if (container->wl_container.surface) { | ||||
|      moz_container_wayland_set_scale_factor_locked(lock, container); | ||||
|    } | ||||
|  } | ||||
|   | ||||
| +bool moz_container_wayland_size_matches_scale_factor_locked(
 | ||||
| +    const MutexAutoLock& aProofOfLock, MozContainer* container, int aWidth,
 | ||||
| +    int aHeight) {
 | ||||
| +  return aWidth % container->wl_container.buffer_scale == 0 &&
 | ||||
| +         aHeight % container->wl_container.buffer_scale == 0;
 | ||||
| +}
 | ||||
| +
 | ||||
|  static bool moz_container_wayland_surface_create_locked( | ||||
|      const MutexAutoLock& aProofOfLock, MozContainer* container) { | ||||
|    MozContainerWayland* wl_container = &container->wl_container; | ||||
|   | ||||
|    LOGWAYLAND("%s [%p]\n", __FUNCTION__, | ||||
| diff --git a/widget/gtk/WindowSurfaceWaylandMultiBuffer.cpp b/widget/gtk/WindowSurfaceWaylandMultiBuffer.cpp
 | ||||
| --- a/widget/gtk/WindowSurfaceWaylandMultiBuffer.cpp
 | ||||
| +++ b/widget/gtk/WindowSurfaceWaylandMultiBuffer.cpp
 | ||||
| @@ -283,12 +283,12 @@
 | ||||
|      return; | ||||
|    } | ||||
|    mFrameInProcess = false; | ||||
|   | ||||
|    MozContainer* container = mWindow->GetMozContainer(); | ||||
| -  MozContainerSurfaceLock lock(container);
 | ||||
| -  struct wl_surface* waylandSurface = lock.GetSurface();
 | ||||
| +  MozContainerSurfaceLock MozContainerLock(container);
 | ||||
| +  struct wl_surface* waylandSurface = MozContainerLock.GetSurface();
 | ||||
|    if (!waylandSurface) { | ||||
|      LOGWAYLAND( | ||||
|          "WindowSurfaceWaylandMB::Commit [%p] frame queued: can't lock " | ||||
|          "wl_surface\n", | ||||
|          (void*)mWindow.get()); | ||||
| @@ -317,12 +317,23 @@
 | ||||
|        LayoutDeviceIntRect r = iter.Get(); | ||||
|        wl_surface_damage_buffer(waylandSurface, r.x, r.y, r.width, r.height); | ||||
|      } | ||||
|    } | ||||
|   | ||||
| +  // aProofOfLock is a kind of substitution of MozContainerSurfaceLock.
 | ||||
| +  // MozContainer is locked but MozContainerSurfaceLock doen't convert to
 | ||||
| +  // MutexAutoLock& so we use aProofOfLock here.
 | ||||
|    moz_container_wayland_set_scale_factor_locked(aProofOfLock, container); | ||||
| -  mInProgressBuffer->AttachAndCommit(waylandSurface);
 | ||||
| +
 | ||||
| +  // It's possible that scale factor changed between Lock() and Commit()
 | ||||
| +  // but window size is the same.
 | ||||
| +  // Don't attach such buffer as it may have incorrect size,
 | ||||
| +  // we'll paint new content soon.
 | ||||
| +  if (moz_container_wayland_size_matches_scale_factor_locked(
 | ||||
| +          aProofOfLock, container, mWindowSize.width, mWindowSize.height)) {
 | ||||
| +    mInProgressBuffer->AttachAndCommit(waylandSurface);
 | ||||
| +  }
 | ||||
|   | ||||
|    mInProgressBuffer->ResetBufferAge(); | ||||
|    mFrontBuffer = mInProgressBuffer; | ||||
|    mFrontBufferInvalidRegion = aInvalidRegion; | ||||
|    mInProgressBuffer = nullptr; | ||||
| 
 | ||||
| @ -1,9 +1,9 @@ | ||||
| diff -up firefox-112.0/widget/gtk/GfxInfo.cpp.firefox-enable-vaapi firefox-112.0/widget/gtk/GfxInfo.cpp
 | ||||
| --- firefox-112.0/widget/gtk/GfxInfo.cpp.firefox-enable-vaapi	2023-04-05 11:10:14.156695694 +0200
 | ||||
| +++ firefox-112.0/widget/gtk/GfxInfo.cpp	2023-04-05 11:11:40.697665718 +0200
 | ||||
| @@ -810,14 +810,6 @@ const nsTArray<GfxDriverInfo>& GfxInfo::
 | ||||
| diff -up firefox-113.0/widget/gtk/GfxInfo.cpp.firefox-enable-vaapi firefox-113.0/widget/gtk/GfxInfo.cpp
 | ||||
| --- firefox-113.0/widget/gtk/GfxInfo.cpp.firefox-enable-vaapi	2023-05-09 19:43:38.495868810 +0200
 | ||||
| +++ firefox-113.0/widget/gtk/GfxInfo.cpp	2023-05-09 19:44:30.943597984 +0200
 | ||||
| @@ -818,14 +818,6 @@ const nsTArray<GfxDriverInfo>& GfxInfo::
 | ||||
|          nsIGfxInfo::FEATURE_BLOCKED_DEVICE, DRIVER_COMPARISON_IGNORED, | ||||
|          V(0, 0, 0, 0), "FEATURE_HARDWARE_VIDEO_DECODING_NO_LINUX_AMD", ""); | ||||
|          V(0, 0, 0, 0), "FEATURE_HARDWARE_VIDEO_DECODING_NO_R600", ""); | ||||
|   | ||||
| -    // Disable on Release/late Beta
 | ||||
| -#if !defined(EARLY_BETA_OR_EARLIER)
 | ||||
|  | ||||
							
								
								
									
										24
									
								
								firefox.spec
									
									
									
									
									
								
							
							
						
						
									
										24
									
								
								firefox.spec
									
									
									
									
									
								
							| @ -175,13 +175,13 @@ ExcludeArch: i686 | ||||
| 
 | ||||
| Summary:        Mozilla Firefox Web browser | ||||
| Name:           firefox | ||||
| Version:        112.0.2 | ||||
| Version:        113.0 | ||||
| Release:        1%{?pre_tag}%{?dist} | ||||
| URL:            https://www.mozilla.org/firefox/ | ||||
| License:        MPLv1.1 or GPLv2+ or LGPLv2+ | ||||
| Source0:        https://archive.mozilla.org/pub/firefox/releases/%{version}%{?pre_version}/source/firefox-%{version}%{?pre_version}.source.tar.xz | ||||
| %if %{with langpacks} | ||||
| Source1:        firefox-langpacks-%{version}%{?pre_version}-20230427.tar.xz | ||||
| Source1:        firefox-langpacks-%{version}%{?pre_version}-20230509.tar.xz | ||||
| %endif | ||||
| Source2:        cbindgen-vendor.tar.xz | ||||
| Source10:       firefox-mozconfig | ||||
| @ -229,9 +229,6 @@ Patch61:        firefox-glibc-dynstack.patch | ||||
| Patch71:        0001-GLIBCXX-fix-for-GCC-12.patch | ||||
| Patch78:        firefox-i686-build.patch | ||||
| Patch79:        firefox-gcc-13-build.patch | ||||
| #Patch80:        D172126.diff | ||||
| #Patch81:        D172864.diff | ||||
| Patch83:        D173814.diff | ||||
| 
 | ||||
| # Test patches | ||||
| # Generate without context by | ||||
| @ -253,10 +250,8 @@ Patch230:        firefox-enable-vaapi.patch | ||||
| # Upstream patches | ||||
| Patch402:        mozilla-1196777.patch | ||||
| Patch407:        mozilla-1667096.patch | ||||
| Patch408:        mozilla-1663844.patch | ||||
| Patch415:        mozilla-1670333.patch | ||||
| # https://phabricator.services.mozilla.com/D173021 | ||||
| Patch416:        libwebrtc-pipewire-capturer-import-dmabuf-directly-into-desktop-frame.patch | ||||
| # TODO: do we need it? | ||||
| #Patch415:        mozilla-1670333.patch | ||||
| 
 | ||||
| # PGO/LTO patches | ||||
| Patch600:        pgo.patch | ||||
| @ -516,9 +511,6 @@ This package contains results of tests executed during build. | ||||
| %patch71 -p1 -b .0001-GLIBCXX-fix-for-GCC-12 | ||||
| %patch78 -p1 -b .firefox-i686 | ||||
| %patch79 -p1 -b .firefox-gcc-13-build | ||||
| #%patch80 -p1 -b .D172126 | ||||
| #%patch81 -p1 -b .D172864 | ||||
| %patch83 -p1 -b .D173814 | ||||
| 
 | ||||
| # Test patches | ||||
| #%patch100 -p1 -b .firefox-tests-xpcshell | ||||
| @ -538,9 +530,8 @@ This package contains results of tests executed during build. | ||||
| 
 | ||||
| %patch402 -p1 -b .1196777 | ||||
| %patch407 -p1 -b .1667096 | ||||
| %patch408 -p1 -b .1663844 | ||||
| %patch415 -p1 -b .1670333 | ||||
| %patch416 -p1 -b .libwebrtc-pipewire-capturer-import-dmabuf-directly-into-desktop-frame | ||||
| # TODO: do we need it? | ||||
| #%patch415 -p1 -b .1670333 | ||||
| 
 | ||||
| # PGO patches | ||||
| %if %{build_with_pgo} | ||||
| @ -1091,6 +1082,9 @@ fi | ||||
| #--------------------------------------------------------------------- | ||||
| 
 | ||||
| %changelog | ||||
| * Tue May 9 2023 Martin Stransky <stransky@redhat.com>- 113.0-1 | ||||
| - Updated to 113.0 | ||||
| 
 | ||||
| * Thu Apr 27 2023 Martin Stransky <stransky@redhat.com>- 112.0.2-1 | ||||
| - Updated to 112.0.2 | ||||
| 
 | ||||
|  | ||||
| @ -1,505 +0,0 @@ | ||||
| From d9faa73cbbc186d7dd0dbfce0589012a0bed9f17 Mon Sep 17 00:00:00 2001 | ||||
| From: Jan Grulich <grulja@gmail.com> | ||||
| Date: Fri, 17 Mar 2023 10:58:10 +0100 | ||||
| Subject: [PATCH] PipeWire capturer: import DMABufs directly into desktop frame | ||||
| 
 | ||||
| Originally DMABufs were imported into a temporary buffer followed by a | ||||
| copy operation into the desktop frame itself. This is not needed as we | ||||
| can import them directly into desktop frames and avoid this overhead. | ||||
| 
 | ||||
| Also drop support for MemPtr buffers as both Mutter and KWin don't seem | ||||
| to support them and they are going to be too slow anyway. | ||||
| 
 | ||||
| Testing with latest Chromium, I could see two processes with usage around 20% and 40% without this change going down to 10% and 20% with | ||||
| this change applied. | ||||
| 
 | ||||
| Bug: webrtc:13429 | ||||
| Bug: chrome:1378258 | ||||
| Change-Id: Ice3292528ff56300931c8638f8e03d4883d5e331 | ||||
| Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/297501 | ||||
| Reviewed-by: Alexander Cooper <alcooper@chromium.org> | ||||
| Commit-Queue: Jan Grulich <grulja@gmail.com> | ||||
| Cr-Commit-Position: refs/heads/main@{#39594} | ||||
| ---
 | ||||
| 
 | ||||
| diff --git a/third_party/libwebrtc/modules/desktop_capture/linux/wayland/egl_dmabuf.cc b/third_party/libwebrtc/modules/desktop_capture/linux/wayland/egl_dmabuf.cc
 | ||||
| index 5bbd5d7aba..b529077c6d 100644
 | ||||
| --- a/third_party/libwebrtc/modules/desktop_capture/linux/wayland/egl_dmabuf.cc
 | ||||
| +++ b/third_party/libwebrtc/modules/desktop_capture/linux/wayland/egl_dmabuf.cc
 | ||||
| @@ -101,11 +101,23 @@ typedef void (*glDeleteTextures_func)(GLsizei n, const GLuint* textures);
 | ||||
|  typedef void (*glGenTextures_func)(GLsizei n, GLuint* textures); | ||||
|  typedef GLenum (*glGetError_func)(void); | ||||
|  typedef const GLubyte* (*glGetString_func)(GLenum name); | ||||
| -typedef void (*glGetTexImage_func)(GLenum target,
 | ||||
| -                                   GLint level,
 | ||||
| -                                   GLenum format,
 | ||||
| -                                   GLenum type,
 | ||||
| -                                   void* pixels);
 | ||||
| +typedef void (*glReadPixels_func)(GLint x,
 | ||||
| +                                  GLint y,
 | ||||
| +                                  GLsizei width,
 | ||||
| +                                  GLsizei height,
 | ||||
| +                                  GLenum format,
 | ||||
| +                                  GLenum type,
 | ||||
| +                                  void* data);
 | ||||
| +typedef void (*glGenFramebuffers_func)(GLsizei n, GLuint* ids);
 | ||||
| +typedef void (*glDeleteFramebuffers_func)(GLsizei n,
 | ||||
| +                                          const GLuint* framebuffers);
 | ||||
| +typedef void (*glBindFramebuffer_func)(GLenum target, GLuint framebuffer);
 | ||||
| +typedef void (*glFramebufferTexture2D_func)(GLenum target,
 | ||||
| +                                            GLenum attachment,
 | ||||
| +                                            GLenum textarget,
 | ||||
| +                                            GLuint texture,
 | ||||
| +                                            GLint level);
 | ||||
| +typedef GLenum (*glCheckFramebufferStatus_func)(GLenum target);
 | ||||
|  typedef void (*glTexParameteri_func)(GLenum target, GLenum pname, GLint param); | ||||
|  typedef void* (*glXGetProcAddressARB_func)(const char*); | ||||
| 
 | ||||
| @@ -118,7 +130,12 @@ glDeleteTextures_func GlDeleteTextures = nullptr;
 | ||||
|  glGenTextures_func GlGenTextures = nullptr; | ||||
|  glGetError_func GlGetError = nullptr; | ||||
|  glGetString_func GlGetString = nullptr; | ||||
| -glGetTexImage_func GlGetTexImage = nullptr;
 | ||||
| +glReadPixels_func GlReadPixels = nullptr;
 | ||||
| +glGenFramebuffers_func GlGenFramebuffers = nullptr;
 | ||||
| +glDeleteFramebuffers_func GlDeleteFramebuffers = nullptr;
 | ||||
| +glBindFramebuffer_func GlBindFramebuffer = nullptr;
 | ||||
| +glFramebufferTexture2D_func GlFramebufferTexture2D = nullptr;
 | ||||
| +glCheckFramebufferStatus_func GlCheckFramebufferStatus = nullptr;
 | ||||
|  glTexParameteri_func GlTexParameteri = nullptr; | ||||
|  glXGetProcAddressARB_func GlXGetProcAddressARB = nullptr; | ||||
| 
 | ||||
| @@ -279,12 +296,26 @@ static bool LoadGL() {
 | ||||
|          (glDeleteTextures_func)GlXGetProcAddressARB("glDeleteTextures"); | ||||
|      GlGenTextures = (glGenTextures_func)GlXGetProcAddressARB("glGenTextures"); | ||||
|      GlGetError = (glGetError_func)GlXGetProcAddressARB("glGetError"); | ||||
| -    GlGetTexImage = (glGetTexImage_func)GlXGetProcAddressARB("glGetTexImage");
 | ||||
| +    GlReadPixels = (glReadPixels_func)GlXGetProcAddressARB("glReadPixels");
 | ||||
| +    GlGenFramebuffers =
 | ||||
| +        (glGenFramebuffers_func)GlXGetProcAddressARB("glGenFramebuffers");
 | ||||
| +    GlDeleteFramebuffers =
 | ||||
| +        (glDeleteFramebuffers_func)GlXGetProcAddressARB("glDeleteFramebuffers");
 | ||||
| +    GlBindFramebuffer =
 | ||||
| +        (glBindFramebuffer_func)GlXGetProcAddressARB("glBindFramebuffer");
 | ||||
| +    GlFramebufferTexture2D = (glFramebufferTexture2D_func)GlXGetProcAddressARB(
 | ||||
| +        "glFramebufferTexture2D");
 | ||||
| +    GlCheckFramebufferStatus =
 | ||||
| +        (glCheckFramebufferStatus_func)GlXGetProcAddressARB(
 | ||||
| +            "glCheckFramebufferStatus");
 | ||||
| +
 | ||||
|      GlTexParameteri = | ||||
|          (glTexParameteri_func)GlXGetProcAddressARB("glTexParameteri"); | ||||
| 
 | ||||
|      return GlBindTexture && GlDeleteTextures && GlGenTextures && GlGetError && | ||||
| -           GlGetTexImage && GlTexParameteri;
 | ||||
| +           GlReadPixels && GlGenFramebuffers && GlDeleteFramebuffers &&
 | ||||
| +           GlBindFramebuffer && GlFramebufferTexture2D &&
 | ||||
| +           GlCheckFramebufferStatus && GlTexParameteri;
 | ||||
|    } | ||||
| 
 | ||||
|    return false; | ||||
| @@ -435,6 +466,14 @@ EglDmaBuf::~EglDmaBuf() {
 | ||||
|      EglTerminate(egl_.display); | ||||
|    } | ||||
| 
 | ||||
| +  if (fbo_) {
 | ||||
| +    GlDeleteFramebuffers(1, &fbo_);
 | ||||
| +  }
 | ||||
| +
 | ||||
| +  if (texture_) {
 | ||||
| +    GlDeleteTextures(1, &texture_);
 | ||||
| +  }
 | ||||
| +
 | ||||
|    // BUG: crbug.com/1290566 | ||||
|    // Closing libEGL.so.1 when using NVidia drivers causes a crash | ||||
|    // when EglGetPlatformDisplayEXT() is used, at least this one is enough | ||||
| @@ -466,20 +505,20 @@ bool EglDmaBuf::GetClientExtensions(EGLDisplay dpy, EGLint name) {
 | ||||
|  } | ||||
| 
 | ||||
|  RTC_NO_SANITIZE("cfi-icall") | ||||
| -std::unique_ptr<uint8_t[]> EglDmaBuf::ImageFromDmaBuf(
 | ||||
| -    const DesktopSize& size,
 | ||||
| -    uint32_t format,
 | ||||
| -    const std::vector<PlaneData>& plane_datas,
 | ||||
| -    uint64_t modifier) {
 | ||||
| -  std::unique_ptr<uint8_t[]> src;
 | ||||
| -
 | ||||
| +bool EglDmaBuf::ImageFromDmaBuf(const DesktopSize& size,
 | ||||
| +                                uint32_t format,
 | ||||
| +                                const std::vector<PlaneData>& plane_datas,
 | ||||
| +                                uint64_t modifier,
 | ||||
| +                                const DesktopVector& offset,
 | ||||
| +                                const DesktopSize& buffer_size,
 | ||||
| +                                uint8_t* data) {
 | ||||
|    if (!egl_initialized_) { | ||||
| -    return src;
 | ||||
| +    return false;
 | ||||
|    } | ||||
| 
 | ||||
|    if (plane_datas.size() <= 0) { | ||||
|      RTC_LOG(LS_ERROR) << "Failed to process buffer: invalid number of planes"; | ||||
| -    return src;
 | ||||
| +    return false;
 | ||||
|    } | ||||
| 
 | ||||
|    EGLint attribs[47]; | ||||
| @@ -568,20 +607,32 @@ std::unique_ptr<uint8_t[]> EglDmaBuf::ImageFromDmaBuf(
 | ||||
|    if (image == EGL_NO_IMAGE) { | ||||
|      RTC_LOG(LS_ERROR) << "Failed to record frame: Error creating EGLImage - " | ||||
|                        << FormatEGLError(EglGetError()); | ||||
| -    return src;
 | ||||
| +    return false;
 | ||||
|    } | ||||
| 
 | ||||
|    // create GL 2D texture for framebuffer | ||||
| -  GLuint texture;
 | ||||
| -  GlGenTextures(1, &texture);
 | ||||
| -  GlTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
 | ||||
| -  GlTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
 | ||||
| -  GlTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
 | ||||
| -  GlTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
 | ||||
| -  GlBindTexture(GL_TEXTURE_2D, texture);
 | ||||
| +  if (!texture_) {
 | ||||
| +    GlGenTextures(1, &texture_);
 | ||||
| +    GlTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
 | ||||
| +    GlTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
 | ||||
| +    GlTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
 | ||||
| +    GlTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
 | ||||
| +  }
 | ||||
| +  GlBindTexture(GL_TEXTURE_2D, texture_);
 | ||||
|    GlEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image); | ||||
| 
 | ||||
| -  src = std::make_unique<uint8_t[]>(plane_datas[0].stride * size.height());
 | ||||
| +  if (!fbo_) {
 | ||||
| +    GlGenFramebuffers(1, &fbo_);
 | ||||
| +  }
 | ||||
| +
 | ||||
| +  GlBindFramebuffer(GL_FRAMEBUFFER, fbo_);
 | ||||
| +  GlFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
 | ||||
| +                         texture_, 0);
 | ||||
| +  if (GlCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
 | ||||
| +    RTC_LOG(LS_ERROR) << "Failed to bind DMA buf framebuffer";
 | ||||
| +    EglDestroyImageKHR(egl_.display, image);
 | ||||
| +    return false;
 | ||||
| +  }
 | ||||
| 
 | ||||
|    GLenum gl_format = GL_BGRA; | ||||
|    switch (format) { | ||||
| @@ -598,17 +649,18 @@ std::unique_ptr<uint8_t[]> EglDmaBuf::ImageFromDmaBuf(
 | ||||
|        gl_format = GL_BGRA; | ||||
|        break; | ||||
|    } | ||||
| -  GlGetTexImage(GL_TEXTURE_2D, 0, gl_format, GL_UNSIGNED_BYTE, src.get());
 | ||||
| 
 | ||||
| -  if (GlGetError()) {
 | ||||
| +  GlReadPixels(offset.x(), offset.y(), buffer_size.width(),
 | ||||
| +               buffer_size.height(), gl_format, GL_UNSIGNED_BYTE, data);
 | ||||
| +
 | ||||
| +  const GLenum error = GlGetError();
 | ||||
| +  if (error) {
 | ||||
|      RTC_LOG(LS_ERROR) << "Failed to get image from DMA buffer."; | ||||
| -    return src;
 | ||||
|    } | ||||
| 
 | ||||
| -  GlDeleteTextures(1, &texture);
 | ||||
|    EglDestroyImageKHR(egl_.display, image); | ||||
| 
 | ||||
| -  return src;
 | ||||
| +  return !error;
 | ||||
|  } | ||||
| 
 | ||||
|  RTC_NO_SANITIZE("cfi-icall") | ||||
| diff --git a/third_party/libwebrtc/modules/desktop_capture/linux/wayland/egl_dmabuf.h b/third_party/libwebrtc/modules/desktop_capture/linux/wayland/egl_dmabuf.h
 | ||||
| index f1d96b2f80..22a8f5ab52 100644
 | ||||
| --- a/third_party/libwebrtc/modules/desktop_capture/linux/wayland/egl_dmabuf.h
 | ||||
| +++ b/third_party/libwebrtc/modules/desktop_capture/linux/wayland/egl_dmabuf.h
 | ||||
| @@ -41,11 +41,15 @@ class EglDmaBuf {
 | ||||
|    EglDmaBuf(); | ||||
|    ~EglDmaBuf(); | ||||
| 
 | ||||
| -  std::unique_ptr<uint8_t[]> ImageFromDmaBuf(
 | ||||
| -      const DesktopSize& size,
 | ||||
| -      uint32_t format,
 | ||||
| -      const std::vector<PlaneData>& plane_datas,
 | ||||
| -      uint64_t modifiers);
 | ||||
| +  // Returns whether the image was successfully imported from
 | ||||
| +  // given DmaBuf and its parameters
 | ||||
| +  bool ImageFromDmaBuf(const DesktopSize& size,
 | ||||
| +                       uint32_t format,
 | ||||
| +                       const std::vector<PlaneData>& plane_datas,
 | ||||
| +                       uint64_t modifiers,
 | ||||
| +                       const DesktopVector& offset,
 | ||||
| +                       const DesktopSize& buffer_size,
 | ||||
| +                       uint8_t* data);
 | ||||
|    std::vector<uint64_t> QueryDmaBufModifiers(uint32_t format); | ||||
| 
 | ||||
|    bool IsEglInitialized() const { return egl_initialized_; } | ||||
| @@ -58,6 +62,8 @@ class EglDmaBuf {
 | ||||
|    int32_t drm_fd_ = -1;               // for GBM buffer mmap | ||||
|    gbm_device* gbm_device_ = nullptr;  // for passed GBM buffer retrieval | ||||
| 
 | ||||
| +  GLuint fbo_ = 0;
 | ||||
| +  GLuint texture_ = 0;
 | ||||
|    EGLStruct egl_; | ||||
| 
 | ||||
|    absl::optional<std::string> GetRenderNode(); | ||||
| diff --git a/third_party/libwebrtc/modules/desktop_capture/linux/wayland/shared_screencast_stream.cc b/third_party/libwebrtc/modules/desktop_capture/linux/wayland/shared_screencast_stream.cc
 | ||||
| index 0ca75d00fc..a8879764c7 100644
 | ||||
| --- a/third_party/libwebrtc/modules/desktop_capture/linux/wayland/shared_screencast_stream.cc
 | ||||
| +++ b/third_party/libwebrtc/modules/desktop_capture/linux/wayland/shared_screencast_stream.cc
 | ||||
| @@ -149,6 +149,12 @@ class SharedScreenCastStreamPrivate {
 | ||||
|    struct spa_video_info_raw spa_video_format_; | ||||
| 
 | ||||
|    void ProcessBuffer(pw_buffer* buffer); | ||||
| +  bool ProcessMemFDBuffer(pw_buffer* buffer,
 | ||||
| +                          DesktopFrame& frame,
 | ||||
| +                          const DesktopVector& offset);
 | ||||
| +  bool ProcessDMABuffer(pw_buffer* buffer,
 | ||||
| +                        DesktopFrame& frame,
 | ||||
| +                        const DesktopVector& offset);
 | ||||
|    void ConvertRGBxToBGRx(uint8_t* frame, uint32_t size); | ||||
| 
 | ||||
|    // PipeWire callbacks | ||||
| @@ -268,9 +274,8 @@ void SharedScreenCastStreamPrivate::OnStreamParamChanged(
 | ||||
|    std::vector<const spa_pod*> params; | ||||
|    const int buffer_types = | ||||
|        has_modifier || (that->pw_server_version_ >= kDmaBufMinVersion) | ||||
| -          ? (1 << SPA_DATA_DmaBuf) | (1 << SPA_DATA_MemFd) |
 | ||||
| -                (1 << SPA_DATA_MemPtr)
 | ||||
| -          : (1 << SPA_DATA_MemFd) | (1 << SPA_DATA_MemPtr);
 | ||||
| +          ? (1 << SPA_DATA_DmaBuf) | (1 << SPA_DATA_MemFd)
 | ||||
| +          : (1 << SPA_DATA_MemFd);
 | ||||
| 
 | ||||
|    params.push_back(reinterpret_cast<spa_pod*>(spa_pod_builder_add_object( | ||||
|        &builder, SPA_TYPE_OBJECT_ParamBuffers, SPA_PARAM_Buffers, | ||||
| @@ -605,9 +610,6 @@ DesktopVector SharedScreenCastStreamPrivate::CaptureCursorPosition() {
 | ||||
|  RTC_NO_SANITIZE("cfi-icall") | ||||
|  void SharedScreenCastStreamPrivate::ProcessBuffer(pw_buffer* buffer) { | ||||
|    spa_buffer* spa_buffer = buffer->buffer; | ||||
| -  ScopedBuf map;
 | ||||
| -  std::unique_ptr<uint8_t[]> src_unique_ptr;
 | ||||
| -  uint8_t* src = nullptr;
 | ||||
| 
 | ||||
|    // Try to update the mouse cursor first, because it can be the only | ||||
|    // information carried by the buffer | ||||
| @@ -641,76 +643,6 @@ void SharedScreenCastStreamPrivate::ProcessBuffer(pw_buffer* buffer) {
 | ||||
|      return; | ||||
|    } | ||||
| 
 | ||||
| -  if (spa_buffer->datas[0].type == SPA_DATA_MemFd) {
 | ||||
| -    map.initialize(
 | ||||
| -        static_cast<uint8_t*>(
 | ||||
| -            mmap(nullptr,
 | ||||
| -                 spa_buffer->datas[0].maxsize + spa_buffer->datas[0].mapoffset,
 | ||||
| -                 PROT_READ, MAP_PRIVATE, spa_buffer->datas[0].fd, 0)),
 | ||||
| -        spa_buffer->datas[0].maxsize + spa_buffer->datas[0].mapoffset,
 | ||||
| -        spa_buffer->datas[0].fd);
 | ||||
| -
 | ||||
| -    if (!map) {
 | ||||
| -      RTC_LOG(LS_ERROR) << "Failed to mmap the memory: "
 | ||||
| -                        << std::strerror(errno);
 | ||||
| -      return;
 | ||||
| -    }
 | ||||
| -
 | ||||
| -    src = SPA_MEMBER(map.get(), spa_buffer->datas[0].mapoffset, uint8_t);
 | ||||
| -  } else if (spa_buffer->datas[0].type == SPA_DATA_DmaBuf) {
 | ||||
| -    const uint n_planes = spa_buffer->n_datas;
 | ||||
| -
 | ||||
| -    if (!n_planes) {
 | ||||
| -      return;
 | ||||
| -    }
 | ||||
| -
 | ||||
| -    std::vector<EglDmaBuf::PlaneData> plane_datas;
 | ||||
| -    for (uint32_t i = 0; i < n_planes; ++i) {
 | ||||
| -      EglDmaBuf::PlaneData data = {
 | ||||
| -          static_cast<int32_t>(spa_buffer->datas[i].fd),
 | ||||
| -          static_cast<uint32_t>(spa_buffer->datas[i].chunk->stride),
 | ||||
| -          static_cast<uint32_t>(spa_buffer->datas[i].chunk->offset)};
 | ||||
| -      plane_datas.push_back(data);
 | ||||
| -    }
 | ||||
| -
 | ||||
| -    // When importing DMA-BUFs, we use the stride (number of bytes from one row
 | ||||
| -    // of pixels in the buffer) provided by PipeWire. The stride from PipeWire
 | ||||
| -    // is given by the graphics driver and some drivers might add some
 | ||||
| -    // additional padding for memory layout optimizations so not everytime the
 | ||||
| -    // stride is equal to BYTES_PER_PIXEL x WIDTH. This is fine, because during
 | ||||
| -    // the import we will use OpenGL and same graphics driver so it will be able
 | ||||
| -    // to work with the stride it provided, but later on when we work with
 | ||||
| -    // images we get from DMA-BUFs we will need to update the stride to be equal
 | ||||
| -    // to BYTES_PER_PIXEL x WIDTH as that's the size of the DesktopFrame we
 | ||||
| -    // allocate for each captured frame.
 | ||||
| -    src_unique_ptr = egl_dmabuf_->ImageFromDmaBuf(
 | ||||
| -        stream_size_, spa_video_format_.format, plane_datas, modifier_);
 | ||||
| -    if (src_unique_ptr) {
 | ||||
| -      src = src_unique_ptr.get();
 | ||||
| -    } else {
 | ||||
| -      RTC_LOG(LS_ERROR) << "Dropping DMA-BUF modifier: " << modifier_
 | ||||
| -                        << " and trying to renegotiate stream parameters";
 | ||||
| -
 | ||||
| -      if (pw_server_version_ >= kDropSingleModifierMinVersion) {
 | ||||
| -        modifiers_.erase(
 | ||||
| -            std::remove(modifiers_.begin(), modifiers_.end(), modifier_),
 | ||||
| -            modifiers_.end());
 | ||||
| -      } else {
 | ||||
| -        modifiers_.clear();
 | ||||
| -      }
 | ||||
| -
 | ||||
| -      pw_loop_signal_event(pw_thread_loop_get_loop(pw_main_loop_),
 | ||||
| -                           renegotiate_);
 | ||||
| -      return;
 | ||||
| -    }
 | ||||
| -  } else if (spa_buffer->datas[0].type == SPA_DATA_MemPtr) {
 | ||||
| -    src = static_cast<uint8_t*>(spa_buffer->datas[0].data);
 | ||||
| -  }
 | ||||
| -
 | ||||
| -  if (!src) {
 | ||||
| -    return;
 | ||||
| -  }
 | ||||
| -
 | ||||
|    // Use SPA_META_VideoCrop metadata to get the frame size. KDE and GNOME do | ||||
|    // handle screen/window sharing differently. KDE/KWin doesn't use | ||||
|    // SPA_META_VideoCrop metadata and when sharing a window, it always sets | ||||
| @@ -763,8 +695,8 @@ void SharedScreenCastStreamPrivate::ProcessBuffer(pw_buffer* buffer) {
 | ||||
|    } | ||||
| 
 | ||||
|    // Get the position of the video crop within the stream. Just double-check | ||||
| -  // that the position doesn't exceed the size of the stream itself. NOTE:
 | ||||
| -  // Currently it looks there is no implementation using this.
 | ||||
| +  // that the position doesn't exceed the size of the stream itself.
 | ||||
| +  // NOTE: Currently it looks there is no implementation using this.
 | ||||
|    uint32_t y_offset = | ||||
|        videocrop_metadata_use && | ||||
|                (videocrop_metadata->region.position.y + frame_size_.height() <= | ||||
| @@ -777,22 +709,7 @@ void SharedScreenCastStreamPrivate::ProcessBuffer(pw_buffer* buffer) {
 | ||||
|                 stream_size_.width()) | ||||
|            ? videocrop_metadata->region.position.x | ||||
|            : 0; | ||||
| -
 | ||||
| -  const uint32_t stream_stride = kBytesPerPixel * stream_size_.width();
 | ||||
| -  uint32_t buffer_stride = spa_buffer->datas[0].chunk->stride;
 | ||||
| -  uint32_t src_stride = buffer_stride;
 | ||||
| -
 | ||||
| -  if (spa_buffer->datas[0].type == SPA_DATA_DmaBuf &&
 | ||||
| -      buffer_stride > stream_stride) {
 | ||||
| -    // When DMA-BUFs are used, sometimes spa_buffer->stride we get might
 | ||||
| -    // contain additional padding, but after we import the buffer, the stride
 | ||||
| -    // we used is no longer relevant and we should just calculate it based on
 | ||||
| -    // the stream width. For more context see https://crbug.com/1333304.
 | ||||
| -    src_stride = stream_stride;
 | ||||
| -  }
 | ||||
| -
 | ||||
| -  uint8_t* updated_src =
 | ||||
| -      src + (src_stride * y_offset) + (kBytesPerPixel * x_offset);
 | ||||
| +  DesktopVector offset = DesktopVector(x_offset, y_offset);
 | ||||
| 
 | ||||
|    webrtc::MutexLock lock(&queue_lock_); | ||||
| 
 | ||||
| @@ -813,9 +730,17 @@ void SharedScreenCastStreamPrivate::ProcessBuffer(pw_buffer* buffer) {
 | ||||
|      queue_.ReplaceCurrentFrame(SharedDesktopFrame::Wrap(std::move(frame))); | ||||
|    } | ||||
| 
 | ||||
| -  queue_.current_frame()->CopyPixelsFrom(
 | ||||
| -      updated_src, (src_stride - (kBytesPerPixel * x_offset)),
 | ||||
| -      DesktopRect::MakeWH(frame_size_.width(), frame_size_.height()));
 | ||||
| +  bool bufferProcessed = false;
 | ||||
| +  if (spa_buffer->datas[0].type == SPA_DATA_MemFd) {
 | ||||
| +    bufferProcessed =
 | ||||
| +        ProcessMemFDBuffer(buffer, *queue_.current_frame(), offset);
 | ||||
| +  } else if (spa_buffer->datas[0].type == SPA_DATA_DmaBuf) {
 | ||||
| +    bufferProcessed = ProcessDMABuffer(buffer, *queue_.current_frame(), offset);
 | ||||
| +  }
 | ||||
| +
 | ||||
| +  if (!bufferProcessed) {
 | ||||
| +    return;
 | ||||
| +  }
 | ||||
| 
 | ||||
|    if (spa_video_format_.format == SPA_VIDEO_FORMAT_RGBx || | ||||
|        spa_video_format_.format == SPA_VIDEO_FORMAT_RGBA) { | ||||
| @@ -832,6 +757,87 @@ void SharedScreenCastStreamPrivate::ProcessBuffer(pw_buffer* buffer) {
 | ||||
|        DesktopRect::MakeSize(queue_.current_frame()->size())); | ||||
|  } | ||||
| 
 | ||||
| +RTC_NO_SANITIZE("cfi-icall")
 | ||||
| +bool SharedScreenCastStreamPrivate::ProcessMemFDBuffer(
 | ||||
| +    pw_buffer* buffer,
 | ||||
| +    DesktopFrame& frame,
 | ||||
| +    const DesktopVector& offset) {
 | ||||
| +  spa_buffer* spa_buffer = buffer->buffer;
 | ||||
| +  ScopedBuf map;
 | ||||
| +  uint8_t* src = nullptr;
 | ||||
| +
 | ||||
| +  map.initialize(
 | ||||
| +      static_cast<uint8_t*>(
 | ||||
| +          mmap(nullptr,
 | ||||
| +               spa_buffer->datas[0].maxsize + spa_buffer->datas[0].mapoffset,
 | ||||
| +               PROT_READ, MAP_PRIVATE, spa_buffer->datas[0].fd, 0)),
 | ||||
| +      spa_buffer->datas[0].maxsize + spa_buffer->datas[0].mapoffset,
 | ||||
| +      spa_buffer->datas[0].fd);
 | ||||
| +
 | ||||
| +  if (!map) {
 | ||||
| +    RTC_LOG(LS_ERROR) << "Failed to mmap the memory: " << std::strerror(errno);
 | ||||
| +    return false;
 | ||||
| +  }
 | ||||
| +
 | ||||
| +  src = SPA_MEMBER(map.get(), spa_buffer->datas[0].mapoffset, uint8_t);
 | ||||
| +
 | ||||
| +  uint32_t buffer_stride = spa_buffer->datas[0].chunk->stride;
 | ||||
| +  uint32_t src_stride = buffer_stride;
 | ||||
| +
 | ||||
| +  uint8_t* updated_src =
 | ||||
| +      src + (src_stride * offset.y()) + (kBytesPerPixel * offset.x());
 | ||||
| +
 | ||||
| +  frame.CopyPixelsFrom(
 | ||||
| +      updated_src, (src_stride - (kBytesPerPixel * offset.x())),
 | ||||
| +      DesktopRect::MakeWH(frame.size().width(), frame.size().height()));
 | ||||
| +
 | ||||
| +  return true;
 | ||||
| +}
 | ||||
| +
 | ||||
| +RTC_NO_SANITIZE("cfi-icall")
 | ||||
| +bool SharedScreenCastStreamPrivate::ProcessDMABuffer(
 | ||||
| +    pw_buffer* buffer,
 | ||||
| +    DesktopFrame& frame,
 | ||||
| +    const DesktopVector& offset) {
 | ||||
| +  spa_buffer* spa_buffer = buffer->buffer;
 | ||||
| +
 | ||||
| +  const uint n_planes = spa_buffer->n_datas;
 | ||||
| +
 | ||||
| +  if (!n_planes) {
 | ||||
| +    return false;
 | ||||
| +  }
 | ||||
| +
 | ||||
| +  std::vector<EglDmaBuf::PlaneData> plane_datas;
 | ||||
| +  for (uint32_t i = 0; i < n_planes; ++i) {
 | ||||
| +    EglDmaBuf::PlaneData data = {
 | ||||
| +        static_cast<int32_t>(spa_buffer->datas[i].fd),
 | ||||
| +        static_cast<uint32_t>(spa_buffer->datas[i].chunk->stride),
 | ||||
| +        static_cast<uint32_t>(spa_buffer->datas[i].chunk->offset)};
 | ||||
| +    plane_datas.push_back(data);
 | ||||
| +  }
 | ||||
| +
 | ||||
| +  const bool imported = egl_dmabuf_->ImageFromDmaBuf(
 | ||||
| +      stream_size_, spa_video_format_.format, plane_datas, modifier_, offset,
 | ||||
| +      frame.size(), frame.data());
 | ||||
| +  if (!imported) {
 | ||||
| +    RTC_LOG(LS_ERROR) << "Dropping DMA-BUF modifier: " << modifier_
 | ||||
| +                      << " and trying to renegotiate stream parameters";
 | ||||
| +
 | ||||
| +    if (pw_server_version_ >= kDropSingleModifierMinVersion) {
 | ||||
| +      modifiers_.erase(
 | ||||
| +          std::remove(modifiers_.begin(), modifiers_.end(), modifier_),
 | ||||
| +          modifiers_.end());
 | ||||
| +    } else {
 | ||||
| +      modifiers_.clear();
 | ||||
| +    }
 | ||||
| +
 | ||||
| +    pw_loop_signal_event(pw_thread_loop_get_loop(pw_main_loop_), renegotiate_);
 | ||||
| +    return false;
 | ||||
| +  }
 | ||||
| +
 | ||||
| +  return true;
 | ||||
| +}
 | ||||
| +
 | ||||
|  void SharedScreenCastStreamPrivate::ConvertRGBxToBGRx(uint8_t* frame, | ||||
|                                                        uint32_t size) { | ||||
|    for (uint32_t i = 0; i < size; i += 4) { | ||||
| @ -1,37 +0,0 @@ | ||||
| diff -up firefox-109.0/dom/media/gmp/GMPSharedMemManager.h.1663844 firefox-109.0/dom/media/gmp/GMPSharedMemManager.h
 | ||||
| --- firefox-109.0/dom/media/gmp/GMPSharedMemManager.h.1663844	2023-01-09 20:34:10.000000000 +0100
 | ||||
| +++ firefox-109.0/dom/media/gmp/GMPSharedMemManager.h	2023-01-12 09:28:56.035741438 +0100
 | ||||
| @@ -26,7 +26,7 @@ class GMPSharedMem {
 | ||||
|    // returned to the parent pool (which is not included).  If more than | ||||
|    // this are needed, we presume the client has either crashed or hung | ||||
|    // (perhaps temporarily). | ||||
| -  static const uint32_t kGMPBufLimit = 20;
 | ||||
| +  static const uint32_t kGMPBufLimit = 40;
 | ||||
|   | ||||
|    GMPSharedMem() { | ||||
|      for (size_t i = 0; i < sizeof(mGmpAllocated) / sizeof(mGmpAllocated[0]); | ||||
| diff -up firefox-109.0/dom/media/platforms/agnostic/gmp/GMPDecoderModule.cpp.1663844 firefox-109.0/dom/media/platforms/agnostic/gmp/GMPDecoderModule.cpp
 | ||||
| --- firefox-109.0/dom/media/platforms/agnostic/gmp/GMPDecoderModule.cpp.1663844	2023-01-09 20:34:10.000000000 +0100
 | ||||
| +++ firefox-109.0/dom/media/platforms/agnostic/gmp/GMPDecoderModule.cpp	2023-01-12 09:28:56.036741473 +0100
 | ||||
| @@ -84,6 +84,9 @@ media::DecodeSupportSet GMPDecoderModule
 | ||||
|   | ||||
|  media::DecodeSupportSet GMPDecoderModule::SupportsMimeType( | ||||
|      const nsACString& aMimeType, DecoderDoctorDiagnostics* aDiagnostics) const { | ||||
| +  if (MP4Decoder::IsH264(aMimeType)) {
 | ||||
| +    return media::DecodeSupport::SoftwareDecode;
 | ||||
| +  }
 | ||||
|    return media::DecodeSupport::Unsupported; | ||||
|  } | ||||
|   | ||||
| diff -up firefox-109.0/dom/media/platforms/agnostic/gmp/GMPVideoDecoder.cpp.1663844 firefox-109.0/dom/media/platforms/agnostic/gmp/GMPVideoDecoder.cpp
 | ||||
| --- firefox-109.0/dom/media/platforms/agnostic/gmp/GMPVideoDecoder.cpp.1663844	2023-01-12 09:28:56.036741473 +0100
 | ||||
| +++ firefox-109.0/dom/media/platforms/agnostic/gmp/GMPVideoDecoder.cpp	2023-01-12 14:18:12.354866405 +0100
 | ||||
| @@ -81,6 +81,8 @@ void GMPVideoDecoder::Decoded(GMPVideoi4
 | ||||
|                                  }); | ||||
|   | ||||
|      mDecodedData.AppendElement(std::move(v)); | ||||
| +    mDecodePromise.ResolveIfExists(std::move(mDecodedData), __func__);
 | ||||
| +    mDecodedData = DecodedData();
 | ||||
|    } else { | ||||
|      mDecodedData.Clear(); | ||||
|      mDecodePromise.RejectIfExists( | ||||
							
								
								
									
										4
									
								
								sources
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								sources
									
									
									
									
									
								
							| @ -1,4 +1,4 @@ | ||||
| SHA512 (cbindgen-vendor.tar.xz) = 0d45c1decfd7aaee853748745c9f5a907c0c6a0cf809c2387aac1cdcf680b0844b1ef4d05148e0527de4ff6e4d4666110bea317bd00b7d73a1210eb58a815563 | ||||
| SHA512 (mochitest-python.tar.gz) = e0a2c569dafe013b6a4c073516388549a8f398d8aa4538a3bc69dcda44737a3a3cf070285e9fa040a15d7a62446665c6158d42a1b6dc3e8d7f4680bc2ef17a16 | ||||
| SHA512 (firefox-langpacks-112.0.2-20230427.tar.xz) = 20a1bd9c9de131fd544d379a2867294cd6d9812bf7d66e8e2237c40eb86e1a44a1c5bc194f9f38e1249ded947d00ae9d0c695ea2813a46997ec64ced7b07e89e | ||||
| SHA512 (firefox-112.0.2.source.tar.xz) = 2cd7adeb6c9a39ad4c5366982e0e58382d7f205e6f2cee02b8ec2867034d1c0c884eeeb870a35db35cba60fa9c84aea73f8c77cfd9f36b5146dde06464aaabd1 | ||||
| SHA512 (firefox-langpacks-113.0-20230509.tar.xz) = 090478c1e29540bc99fe1857c83ec93da0dab5b44c5f8765d14e51a30ff5baf2fe8983e997fe0980efc69afbce6dc185899a9bc39826e55294472a327d53efc2 | ||||
| SHA512 (firefox-113.0.source.tar.xz) = 96b0f0774083270f4fcce06085b177ced25ba05da7291d777f1da1d5bbad30721bc6363b76e06ccb64fc092778c8326a426a8bfdfa3cbaafd4f1169b924744a5 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user