From 6bf0a5cb5034a7e684dcc3500e841785237ce2dd Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 19:32:43 +0200 Subject: Adding upstream version 1:115.7.0. Signed-off-by: Daniel Baumann --- widget/android/AndroidVsync.cpp | 150 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 150 insertions(+) create mode 100644 widget/android/AndroidVsync.cpp (limited to 'widget/android/AndroidVsync.cpp') diff --git a/widget/android/AndroidVsync.cpp b/widget/android/AndroidVsync.cpp new file mode 100644 index 0000000000..6aed5f1e53 --- /dev/null +++ b/widget/android/AndroidVsync.cpp @@ -0,0 +1,150 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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 "AndroidVsync.h" + +#include "AndroidBridge.h" +#include "nsTArray.h" + +/** + * Implementation for the AndroidVsync class. + */ + +namespace mozilla { +namespace widget { + +StaticDataMutex> AndroidVsync::sInstance( + "AndroidVsync::sInstance"); + +/* static */ RefPtr AndroidVsync::GetInstance() { + auto weakInstance = sInstance.Lock(); + RefPtr instance(*weakInstance); + if (!instance) { + instance = new AndroidVsync(); + *weakInstance = instance; + } + return instance; +} + +/** + * Owned by the Java AndroidVsync instance. + */ +class AndroidVsyncSupport final + : public java::AndroidVsync::Natives { + public: + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(AndroidVsyncSupport) + + using Base = java::AndroidVsync::Natives; + using Base::AttachNative; + using Base::DisposeNative; + + explicit AndroidVsyncSupport(AndroidVsync* aAndroidVsync) + : mAndroidVsync(std::move(aAndroidVsync), + "AndroidVsyncSupport::mAndroidVsync") {} + + // Called by Java + void NotifyVsync(const java::AndroidVsync::LocalRef& aInstance, + int64_t aFrameTimeNanos) { + auto androidVsync = mAndroidVsync.Lock(); + if (*androidVsync) { + (*androidVsync)->NotifyVsync(aFrameTimeNanos); + } + } + + // Called by the AndroidVsync destructor + void Unlink() { + auto androidVsync = mAndroidVsync.Lock(); + *androidVsync = nullptr; + } + + protected: + ~AndroidVsyncSupport() = default; + + DataMutex mAndroidVsync; +}; + +AndroidVsync::AndroidVsync() : mImpl("AndroidVsync.mImpl") { + AndroidVsyncSupport::Init(); + + auto impl = mImpl.Lock(); + impl->mSupport = new AndroidVsyncSupport(this); + impl->mSupportJava = java::AndroidVsync::New(); + AndroidVsyncSupport::AttachNative(impl->mSupportJava, impl->mSupport); +} + +AndroidVsync::~AndroidVsync() { + auto impl = mImpl.Lock(); + impl->mInputObservers.Clear(); + impl->mRenderObservers.Clear(); + impl->UpdateObservingVsync(); + impl->mSupport->Unlink(); +} + +void AndroidVsync::RegisterObserver(Observer* aObserver, ObserverType aType) { + auto impl = mImpl.Lock(); + if (aType == AndroidVsync::INPUT) { + impl->mInputObservers.AppendElement(aObserver); + } else { + impl->mRenderObservers.AppendElement(aObserver); + } + impl->UpdateObservingVsync(); +} + +void AndroidVsync::UnregisterObserver(Observer* aObserver, ObserverType aType) { + auto impl = mImpl.Lock(); + if (aType == AndroidVsync::INPUT) { + impl->mInputObservers.RemoveElement(aObserver); + } else { + impl->mRenderObservers.RemoveElement(aObserver); + } + aObserver->Dispose(); + impl->UpdateObservingVsync(); +} + +void AndroidVsync::Impl::UpdateObservingVsync() { + bool shouldObserve = + !mInputObservers.IsEmpty() || !mRenderObservers.IsEmpty(); + if (shouldObserve != mObservingVsync) { + mObservingVsync = mSupportJava->ObserveVsync(shouldObserve); + } +} + +// Always called on the Java UI thread. +void AndroidVsync::NotifyVsync(int64_t aFrameTimeNanos) { + MOZ_ASSERT(AndroidBridge::IsJavaUiThread()); + + // Convert aFrameTimeNanos to a TimeStamp. The value converts trivially to + // the internal ticks representation of TimeStamp_posix; both use the + // monotonic clock and are in nanoseconds. + TimeStamp timeStamp = TimeStamp::FromSystemTime(aFrameTimeNanos); + + // Do not keep the lock held while calling OnVsync. + nsTArray observers; + { + auto impl = mImpl.Lock(); + observers.AppendElements(impl->mInputObservers); + observers.AppendElements(impl->mRenderObservers); + } + for (Observer* observer : observers) { + observer->OnVsync(timeStamp); + } +} + +void AndroidVsync::OnMaybeUpdateRefreshRate() { + MOZ_ASSERT(NS_IsMainThread()); + + auto impl = mImpl.Lock(); + + nsTArray observers; + observers.AppendElements(impl->mRenderObservers); + + for (Observer* observer : observers) { + observer->OnMaybeUpdateRefreshRate(); + } +} + +} // namespace widget +} // namespace mozilla -- cgit v1.2.3