1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "InputTaskManager.h"
8 #include "VsyncTaskManager.h"
9 #include "nsRefreshDriver.h"
13 StaticRefPtr
<InputTaskManager
> InputTaskManager::gInputTaskManager
;
15 void InputTaskManager::EnableInputEventPrioritization() {
16 MOZ_ASSERT(NS_IsMainThread());
17 MOZ_ASSERT(mInputQueueState
== STATE_DISABLED
);
18 mInputQueueState
= STATE_ENABLED
;
21 void InputTaskManager::FlushInputEventPrioritization() {
22 MOZ_ASSERT(NS_IsMainThread());
23 MOZ_ASSERT(mInputQueueState
== STATE_ENABLED
||
24 mInputQueueState
== STATE_SUSPEND
);
26 mInputQueueState
== STATE_ENABLED
? STATE_FLUSHING
: STATE_SUSPEND
;
29 void InputTaskManager::SuspendInputEventPrioritization() {
30 MOZ_ASSERT(NS_IsMainThread());
31 MOZ_ASSERT(mInputQueueState
== STATE_ENABLED
||
32 mInputQueueState
== STATE_FLUSHING
);
33 mInputQueueState
= STATE_SUSPEND
;
36 void InputTaskManager::ResumeInputEventPrioritization() {
37 MOZ_ASSERT(NS_IsMainThread());
38 MOZ_ASSERT(mInputQueueState
== STATE_SUSPEND
);
39 mInputQueueState
= STATE_ENABLED
;
42 int32_t InputTaskManager::GetPriorityModifierForEventLoopTurn(
43 const MutexAutoLock
& aProofOfLock
) {
44 // When the state is disabled, the input task that we have is
45 // very likely SuspendInputEventQueue, so here we also use
46 // normal priority as ResumeInputEventQueue, FlushInputEventQueue and
47 // SetInputEventQueueEnabled all uses normal priority, to
48 // ensure the ordering is correct.
49 if (State() == InputTaskManager::STATE_DISABLED
) {
50 return static_cast<int32_t>(EventQueuePriority::Normal
) -
51 static_cast<int32_t>(EventQueuePriority::InputHigh
);
54 return GetPriorityModifierForEventLoopTurnForStrictVsyncAlignment();
57 void InputTaskManager::WillRunTask() {
58 TaskManager::WillRunTask();
59 mInputPriorityController
.WillRunTask();
63 InputTaskManager::GetPriorityModifierForEventLoopTurnForStrictVsyncAlignment() {
64 MOZ_ASSERT(!IsSuspended());
66 size_t inputCount
= PendingTaskCount();
68 mInputPriorityController
.ShouldUseHighestPriority(this)) {
69 return static_cast<int32_t>(EventQueuePriority::InputHighest
) -
70 static_cast<int32_t>(EventQueuePriority::InputHigh
);
73 if (State() == STATE_FLUSHING
||
74 nsRefreshDriver::GetNextTickHint().isNothing()) {
78 return static_cast<int32_t>(EventQueuePriority::InputLow
) -
79 static_cast<int32_t>(EventQueuePriority::InputHigh
);
82 InputTaskManager::InputPriorityController::InputPriorityController()
83 : mInputVsyncState(InputVsyncState::NoPendingVsync
) {}
85 bool InputTaskManager::InputPriorityController::ShouldUseHighestPriority(
86 InputTaskManager
* aInputTaskManager
) {
87 if (mInputVsyncState
== InputVsyncState::HasPendingVsync
) {
91 if (mInputVsyncState
== InputVsyncState::RunVsync
) {
95 if (mInputVsyncState
== InputVsyncState::NoPendingVsync
&&
96 VsyncTaskManager::Get()->PendingTaskCount()) {
97 EnterPendingVsyncState(aInputTaskManager
->PendingTaskCount());
104 void InputTaskManager::InputPriorityController::EnterPendingVsyncState(
105 uint32_t aNumPendingTasks
) {
106 MOZ_ASSERT(mInputVsyncState
== InputVsyncState::NoPendingVsync
);
108 mInputVsyncState
= InputVsyncState::HasPendingVsync
;
109 mMaxInputTasksToRun
= aNumPendingTasks
;
110 mRunInputStartTime
= TimeStamp::Now();
113 void InputTaskManager::InputPriorityController::WillRunVsync() {
114 if (mInputVsyncState
== InputVsyncState::RunVsync
||
115 mInputVsyncState
== InputVsyncState::HasPendingVsync
) {
116 LeavePendingVsyncState(false);
120 void InputTaskManager::InputPriorityController::LeavePendingVsyncState(
123 MOZ_ASSERT(mInputVsyncState
== InputVsyncState::HasPendingVsync
);
124 mInputVsyncState
= InputVsyncState::RunVsync
;
126 mInputVsyncState
= InputVsyncState::NoPendingVsync
;
129 mMaxInputTasksToRun
= 0;
132 void InputTaskManager::InputPriorityController::WillRunTask() {
133 switch (mInputVsyncState
) {
134 case InputVsyncState::NoPendingVsync
:
136 case InputVsyncState::HasPendingVsync
:
137 MOZ_ASSERT(mMaxInputTasksToRun
> 0);
138 --mMaxInputTasksToRun
;
139 if (!mMaxInputTasksToRun
||
140 TimeStamp::Now() - mRunInputStartTime
>=
141 TimeDuration::FromMilliseconds(
142 StaticPrefs::dom_input_event_queue_duration_max())) {
143 LeavePendingVsyncState(true);
147 MOZ_DIAGNOSTIC_ASSERT(
148 false, "Shouldn't run this input task when we suppose to run vsync");
154 void InputTaskManager::Init() { gInputTaskManager
= new InputTaskManager(); }
156 } // namespace mozilla