diff --git a/gfx/layers/composite/ImageComposite.cpp b/gfx/layers/composite/ImageComposite.cpp index daac765f4f7f..3be74f601dc9 100644 --- a/gfx/layers/composite/ImageComposite.cpp +++ b/gfx/layers/composite/ImageComposite.cpp @@ -34,7 +34,7 @@ TimeStamp ImageComposite::GetBiasedTime(const TimeStamp& aInput) const { } } -void ImageComposite::UpdateBias(size_t aImageIndex) { +void ImageComposite::UpdateBias(size_t aImageIndex, bool aFrameChanged) { MOZ_ASSERT(aImageIndex < ImagesCount()); TimeStamp compositionTime = GetCompositionTime(); @@ -81,7 +81,15 @@ void ImageComposite::UpdateBias(size_t aImageIndex) { mBias = ImageComposite::BIAS_POSITIVE; return; } - mBias = ImageComposite::BIAS_NONE; + if (aFrameChanged) { + // The current and next video frames are a sufficient distance from the + // composition time and we can reliably pick the right frame without bias. + // Reset the bias. + // We only do this when the frame changed. Otherwise, when playing a 30fps + // video on a 60fps display, we'd keep resetting the bias during the "middle + // frames". + mBias = ImageComposite::BIAS_NONE; + } } int ImageComposite::ChooseImageIndex() { @@ -110,7 +118,10 @@ int ImageComposite::ChooseImageIndex() { bool wasVisibleAtPreviousComposition = compositionOpportunityId == mLastChooseImageIndexComposition.Next(); - UpdateCompositedFrame(imageIndex, wasVisibleAtPreviousComposition); + + bool frameChanged = + UpdateCompositedFrame(imageIndex, wasVisibleAtPreviousComposition); + UpdateBias(imageIndex, frameChanged); mLastChooseImageIndexComposition = compositionOpportunityId; @@ -171,7 +182,8 @@ void ImageComposite::SetImages(nsTArray&& aNewImages) { mImages = std::move(aNewImages); } -void ImageComposite::UpdateCompositedFrame( +// Returns whether the frame changed. +bool ImageComposite::UpdateCompositedFrame( int aImageIndex, bool aWasVisibleAtPreviousComposition) { MOZ_RELEASE_ASSERT(aImageIndex >= 0); MOZ_RELEASE_ASSERT(aImageIndex < static_cast(mImages.Length())); @@ -212,7 +224,8 @@ void ImageComposite::UpdateCompositedFrame( #endif if (mLastFrameID == image.mFrameID && mLastProducerID == image.mProducerID) { - return; + // The frame didn't change. + return false; } CountSkippedFrames(&image); @@ -247,6 +260,8 @@ void ImageComposite::UpdateCompositedFrame( mLastFrameID = image.mFrameID; mLastProducerID = image.mProducerID; mLastFrameUpdateComposition = compositionOpportunityId; + + return true; } void ImageComposite::OnFinishRendering(int aImageIndex, @@ -266,12 +281,6 @@ void ImageComposite::OnFinishRendering(int aImageIndex, mLastProducerID); AppendImageCompositeNotification(info); } - - // Update mBias. This can change which frame ChooseImage(Index) would - // return, and we don't want to do that until we've finished compositing - // since callers of ChooseImage(Index) assume the same image will be chosen - // during a given composition. - UpdateBias(aImageIndex); } const ImageComposite::TimedImage* ImageComposite::GetImage( diff --git a/gfx/layers/composite/ImageComposite.h b/gfx/layers/composite/ImageComposite.h index 20f40ec1b03a..05e812c8b358 100644 --- a/gfx/layers/composite/ImageComposite.h +++ b/gfx/layers/composite/ImageComposite.h @@ -53,8 +53,6 @@ class ImageComposite { }; protected: - void UpdateBias(size_t aImageIndex); - virtual TimeStamp GetCompositionTime() const = 0; virtual CompositionOpportunityId GetCompositionOpportunityId() const = 0; virtual void AppendImageCompositeNotification( @@ -104,9 +102,12 @@ class ImageComposite { void CountSkippedFrames(const TimedImage* aImage); // Update mLastFrameID and mLastProducerID, and report dropped frames. - void UpdateCompositedFrame(int aImageIndex, + // Returns whether the frame changed. + bool UpdateCompositedFrame(int aImageIndex, bool aWasVisibleAtPreviousComposition); + void UpdateBias(size_t aImageIndex, bool aFrameUpdated); + // Emit a profiler marker about video frame timestamp jitter. void DetectTimeStampJitter(const TimedImage* aNewImage); diff --git a/gfx/layers/composite/ImageHost.h b/gfx/layers/composite/ImageHost.h index 5ad81dae6869..5d712d5bddeb 100644 --- a/gfx/layers/composite/ImageHost.h +++ b/gfx/layers/composite/ImageHost.h @@ -102,7 +102,7 @@ class ImageHost : public CompositableHost, public ImageComposite { // Acquire the TextureSource for the currently prepared frame. RefPtr AcquireTextureSource(const RenderInfo& aInfo); - // Send ImageComposite notifications and update the ChooseImage bias. + // Send ImageComposite notifications. void FinishRendering(const RenderInfo& aInfo); // This should only be called inside a lock, or during rendering. It is diff --git a/gfx/layers/wr/WebRenderImageHost.cpp b/gfx/layers/wr/WebRenderImageHost.cpp index 5e011b7f8169..9cf6efaf9390 100644 --- a/gfx/layers/wr/WebRenderImageHost.cpp +++ b/gfx/layers/wr/WebRenderImageHost.cpp @@ -169,8 +169,7 @@ TextureHost* WebRenderImageHost::GetAsTextureHostForComposite( SetCurrentTextureHost(img->mTextureHost); if (mCurrentAsyncImageManager->GetCompositionTime()) { - // We are in a composition. Send ImageCompositeNotifications and call - // UpdateBias. + // We are in a composition. Send ImageCompositeNotifications. OnFinishRendering(imageIndex, img, mAsyncRef.mProcessId, mAsyncRef.mHandle); }