1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_ANIMATION_WORKLET_MUTATOR_DISPATCHER_IMPL_H_
6 #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_ANIMATION_WORKLET_MUTATOR_DISPATCHER_IMPL_H_
7 
8 #include <memory>
9 
10 #include "base/macros.h"
11 #include "base/memory/weak_ptr.h"
12 #include "base/single_thread_task_runner.h"
13 #include "base/time/tick_clock.h"
14 #include "third_party/blink/renderer/platform/graphics/animation_worklet_mutator.h"
15 #include "third_party/blink/renderer/platform/graphics/animation_worklet_mutator_dispatcher.h"
16 #include "third_party/blink/renderer/platform/graphics/mutator_client.h"
17 #include "third_party/blink/renderer/platform/heap/handle.h"
18 #include "third_party/blink/renderer/platform/heap/persistent.h"
19 #include "third_party/blink/renderer/platform/heap/visitor.h"
20 #include "third_party/blink/renderer/platform/wtf/functional.h"
21 #include "third_party/blink/renderer/platform/wtf/hash_set.h"
22 #include "third_party/blink/renderer/platform/wtf/thread_safe_ref_counted.h"
23 
24 namespace blink {
25 
26 class CompositorMutatorClient;
27 class MainThreadMutatorClient;
28 
29 // Fans out requests to all of the registered AnimationWorkletMutators which can
30 // then run worklet animations to produce mutation updates. Requests for
31 // animation frames are received from AnimationWorkletMutators and generate a
32 // new frame.
33 class PLATFORM_EXPORT AnimationWorkletMutatorDispatcherImpl final
34     : public AnimationWorkletMutatorDispatcher {
35  public:
36   // There are three outputs for the two interface surfaces of the created
37   // class blob. The returned owning pointer to the Client, which
38   // also owns the rest of the structure. |mutatee| and |mutatee_runner| form a
39   // pair for referencing the AnimationWorkletMutatorDispatcherImpl. i.e. Put
40   // tasks on the TaskRunner using the WeakPtr to get to the methods.
41   static std::unique_ptr<CompositorMutatorClient> CreateCompositorThreadClient(
42       base::WeakPtr<AnimationWorkletMutatorDispatcherImpl>* mutatee,
43       scoped_refptr<base::SingleThreadTaskRunner>* mutatee_runner);
44   static std::unique_ptr<MainThreadMutatorClient> CreateMainThreadClient(
45       base::WeakPtr<AnimationWorkletMutatorDispatcherImpl>* mutatee,
46       scoped_refptr<base::SingleThreadTaskRunner>* mutatee_runner);
47 
48   explicit AnimationWorkletMutatorDispatcherImpl(bool main_thread_task_runner);
49   ~AnimationWorkletMutatorDispatcherImpl() override;
50 
51   // AnimationWorkletMutatorDispatcher implementation.
52   void MutateSynchronously(
53       std::unique_ptr<AnimationWorkletDispatcherInput>) override;
54 
55   bool MutateAsynchronously(std::unique_ptr<AnimationWorkletDispatcherInput>,
56                             MutateQueuingStrategy,
57                             AsyncMutationCompleteCallback) override;
58 
59   // TODO(majidvp): Remove when timeline inputs are known.
60   bool HasMutators() override;
61 
62   // Interface for use by the AnimationWorklet Thread(s) to request calls.
63   // (To the given Mutator on the given TaskRunner.)
64   void RegisterAnimationWorkletMutator(
65       CrossThreadPersistent<AnimationWorkletMutator>,
66       scoped_refptr<base::SingleThreadTaskRunner> mutator_runner);
67 
68   void UnregisterAnimationWorkletMutator(
69       CrossThreadPersistent<AnimationWorkletMutator>);
70 
SetClient(MutatorClient * client)71   void SetClient(MutatorClient* client) { client_ = client; }
72 
73   void SynchronizeAnimatorName(const String& animator_name);
74 
client()75   MutatorClient* client() { return client_; }
76 
GetTaskRunner()77   scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner() {
78     return host_queue_;
79   }
80 
GetWeakPtr()81   base::WeakPtr<AnimationWorkletMutatorDispatcherImpl> GetWeakPtr() {
82     return weak_factory_.GetWeakPtr();
83   }
84 
SetClockForTesting(std::unique_ptr<base::TickClock> tick_clock)85   void SetClockForTesting(std::unique_ptr<base::TickClock> tick_clock) {
86     tick_clock_.reset(tick_clock.release());
87   }
88 
89  private:
90   class OutputVectorRef;
91   struct AsyncMutationRequest;
92 
93   using InputMap = HashMap<int, std::unique_ptr<AnimationWorkletInput>>;
94 
95   using AnimationWorkletMutatorToTaskRunnerMap =
96       HashMap<CrossThreadPersistent<AnimationWorkletMutator>,
97               scoped_refptr<base::SingleThreadTaskRunner>>;
98 
99   InputMap CreateInputMap(AnimationWorkletDispatcherInput& mutator_input) const;
100 
101   // Dispatches mutation update requests. The callback is triggered once all
102   // mutation updates have been computed and it runs on the animation worklet
103   // thread associated with the last mutation to complete.
104   void RequestMutations(CrossThreadOnceClosure done_callback);
105 
106   // Dispatches mutation update requests. The request time includes time
107   // in the queue. In the event that a queued request is replaced, the
108   // replacement uses the original request time.
109   // |done_callback| is called on the impl thread on completion of the mutation
110   // cycle.
111   void MutateAsynchronouslyInternal(
112       base::TimeTicks request_time,
113       AsyncMutationCompleteCallback done_callback);
114 
115   // Called when the asynchronous mutation cycle is complete. The mutation id
116   // is used for asynchronous task monitoring and request time is used for
117   // collecting UMA stats of the total time between mutation request and
118   // completion.
119   void AsyncMutationsDone(int async_mutation_id, base::TimeTicks request_time);
120 
121   // Returns true if any updates were applied.
122   bool ApplyMutationsOnHostThread();
123 
124   // Timing function used for UMA metrics. Uses a tick clock that may be
125   // overridden for testing purposes.
126   base::TimeTicks NowTicks() const;
127 
128   // The AnimationWorkletProxyClients are also owned by the WorkerClients
129   // dictionary.
130   AnimationWorkletMutatorToTaskRunnerMap mutator_map_;
131 
132   template <typename ClientType>
133   static std::unique_ptr<ClientType> CreateClient(
134       base::WeakPtr<AnimationWorkletMutatorDispatcherImpl>* weak_interface,
135       scoped_refptr<base::SingleThreadTaskRunner>* queue,
136       bool create_main_thread_client);
137 
138   scoped_refptr<base::SingleThreadTaskRunner> host_queue_;
139 
140   // The MutatorClient owns (std::unique_ptr) us, so this pointer is
141   // valid as long as this class exists.
142   MutatorClient* client_;
143 
144   // Map of mutator scope IDs to mutator input. The Mutate methods safeguards
145   // against concurrent calls (important once async mutations are introduced) by
146   // checking that the map has been reset on entry. For this reason, it is
147   // important to reset the map at the end of the mutation cycle.
148   InputMap mutator_input_map_;
149 
150   // Reference to a vector for collecting mutation output. The vector is
151   // accessed across threads, thus it must be guaranteed to persist until the
152   // last mutation update is complete, and updates must be done in a thread-safe
153   // manner. The Mutate method guards against concurrent calls (important once
154   // async mutations are introduced)  by checking that the output vector is
155   // empty. For this reason, it is important to clear the output at the end of
156   // the mutation cycle.
157   scoped_refptr<OutputVectorRef> outputs_;
158 
159   // Active callback for the completion of an async mutation cycle.
160   AsyncMutationCompleteCallback on_async_mutation_complete_;
161 
162   // Queues for pending mutation requests. Each queue can hold a single request.
163   // On completion of a mutation cycle, a fresh mutation cycle is started if
164   // either queue contains a request. The priority queue takes precedence if
165   // both queues contain a request.  The request stored in the replaceable queue
166   // can be updated in a later async mutation call, whereas the priority queue
167   // entry cannot, as each priority request is required to run.
168   std::unique_ptr<AsyncMutationRequest> queued_priority_request;
169   std::unique_ptr<AsyncMutationRequest> queued_replaceable_request;
170 
171   std::unique_ptr<base::TickClock> tick_clock_;
172 
173   base::WeakPtrFactory<AnimationWorkletMutatorDispatcherImpl> weak_factory_{
174       this};
175 
176   DISALLOW_COPY_AND_ASSIGN(AnimationWorkletMutatorDispatcherImpl);
177 };
178 
179 }  // namespace blink
180 
181 #endif  // THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_ANIMATION_WORKLET_MUTATOR_DISPATCHER_IMPL_H_
182