• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2013 The Flutter 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 COMMON_PLATFORM_VIEW_H_
6 #define COMMON_PLATFORM_VIEW_H_
7 
8 #include <memory>
9 
10 #include "flutter/common/task_runners.h"
11 #include "flutter/flow/texture.h"
12 #include "flutter/fml/macros.h"
13 #include "flutter/fml/memory/weak_ptr.h"
14 #include "flutter/lib/ui/window/platform_message.h"
15 #include "flutter/lib/ui/window/pointer_data_packet.h"
16 #include "flutter/lib/ui/window/viewport_metrics.h"
17 #include "flutter/shell/common/surface.h"
18 #include "flutter/shell/common/vsync_waiter.h"
19 #include "third_party/skia/include/core/SkSize.h"
20 #include "third_party/skia/include/gpu/GrContext.h"
21 
22 namespace flutter {
23 using IdleCallback = std::function<void(int64_t)>;
24 
25 class Shell;
26 
27 //------------------------------------------------------------------------------
28 /// @brief      Platform views are created by the shell on the platform task
29 ///             runner. Unless explicitly specified, all platform view methods
30 ///             are called on the platform task runner as well. Platform views
31 ///             are usually sub-classed on a per platform basis and the bulk of
32 ///             the window system integration happens using that subclass. Since
33 ///             most platform window toolkits are usually only safe to access on
34 ///             a single "main" thread, any interaction that requires access to
35 ///             the underlying platform's window toolkit is routed through the
36 ///             platform view associated with that shell. This involves
37 ///             operations like settings up and tearing down the render surface,
38 ///             platform messages, interacting with accessibility features on
39 ///             the platform, input events, etc.
40 ///
41 class PlatformView {
42  public:
43   //----------------------------------------------------------------------------
44   /// @brief      Used to forward events from the platform view to interested
45   ///             subsystems. This forwarding is done by the shell which sets
46   ///             itself up as the delegate of the platform view.
47   ///
48   class Delegate {
49    public:
50     //--------------------------------------------------------------------------
51     /// @brief      Notifies the delegate that the platform view was created
52     ///             with the given render surface. This surface is platform
53     ///             (iOS, Android) and client-rendering API (OpenGL, Software,
54     ///             Metal, Vulkan) specific. This is usually a sign to the
55     ///             rasterizer to setup and begin rendering to that surface.
56     ///
57     /// @param[in]  surface  The surface
58     ///
59     virtual void OnPlatformViewCreated(std::unique_ptr<Surface> surface) = 0;
60 
61     //--------------------------------------------------------------------------
62     /// @brief      Notifies the delegate that the platform view was destroyed.
63     ///             This is usually a sign to the rasterizer to suspend
64     ///             rendering a previously configured surface and collect any
65     ///             intermediate resources.
66     ///
67     virtual void OnPlatformViewDestroyed() = 0;
68 
69     //--------------------------------------------------------------------------
70     /// @brief      Notifies the delegate that the specified callback needs to
71     ///             be invoked after the rasterizer is done rendering the next
72     ///             frame. This callback will be called on the render thread and
73     ///             it is caller responsibility to perform any re-threading as
74     ///             necessary. Due to the asynchronous nature of rendering in
75     ///             Flutter, embedders usually add a placeholder over the
76     ///             contents in which Flutter is going to render when Flutter is
77     ///             first initialized. This callback may be used as a signal to
78     ///             remove that placeholder.
79     ///
80     /// @attention  The callback will be invoked on the render thread and not
81     ///             the calling thread.
82     ///
83     /// @param[in]  closure  The callback to execute on the next frame.
84     ///
85     virtual void OnPlatformViewSetNextFrameCallback(fml::closure closure) = 0;
86 
87     //--------------------------------------------------------------------------
88     /// @brief      ACE PC preview.
89     ///
90     virtual void OnSetIdleNotificationCallback(const IdleCallback& idleCallback) = 0;
91 
92     //--------------------------------------------------------------------------
93     /// @brief      Notifies the delegate the viewport metrics of the platform
94     ///             view have been updated. The rasterizer will need to be
95     ///             reconfigured to render the frame in the updated viewport
96     ///             metrics.
97     ///
98     /// @param[in]  metrics  The updated viewport metrics.
99     ///
100     virtual void OnPlatformViewSetViewportMetrics(
101         const ViewportMetrics& metrics) = 0;
102 
103     //--------------------------------------------------------------------------
104     /// @brief      Notifies the delegate that the platform has dispatched a
105     ///             platform message from the embedder to the Flutter
106     ///             application. This message must be forwarded to the running
107     ///             isolate hosted by the engine on the UI thread.
108     ///
109     /// @param[in]  message  The platform message to dispatch to the running
110     ///                      root isolate.
111     ///
112     virtual void OnPlatformViewDispatchPlatformMessage(
113         fml::RefPtr<PlatformMessage> message) = 0;
114 
115     //--------------------------------------------------------------------------
116     /// @brief      Notifies the delegate that the platform view has encountered
117     ///             a pointer event. This pointer event needs to be forwarded to
118     ///             the running root isolate hosted by the engine on the UI
119     ///             thread.
120     ///
121     /// @param[in]  packet  The pointer data packet containing multiple pointer
122     ///                     events.
123     ///
124     virtual void OnPlatformViewDispatchPointerDataPacket(
125         std::unique_ptr<PointerDataPacket> packet) = 0;
126 
127     //--------------------------------------------------------------------------
128     /// @brief      Notifies the delegate that the embedder has specified a
129     ///             texture that it want the rasterizer to composite within the
130     ///             Flutter layer tree. All textures must have a unique
131     ///             identifier. When the rasterizer encounters an external
132     ///             texture within its hierarchy, it gives the embedder a chance
133     ///             to update that texture on the GPU thread before it
134     ///             composites the same on-screen.
135     ///
136     /// @param[in]  texture  The texture that is being updated by the embedder
137     ///                      but composited by Flutter in its own hierarchy.
138     ///
139     virtual void OnPlatformViewRegisterTexture(
140         std::shared_ptr<Texture> texture) = 0;
141 
142     //--------------------------------------------------------------------------
143     /// @brief      Notifies the delegate that the embedder will no longer
144     ///             attempt to composite the specified texture within the layer
145     ///             tree. This allows the rasterizer to collect associated
146     ///             resources.
147     ///
148     /// @param[in]  texture_id  The identifier of the texture to unregister. If
149     ///                         the texture has not been previously registered,
150     ///                         this call does nothing.
151     ///
152     virtual void OnPlatformViewUnregisterTexture(int64_t texture_id) = 0;
153 
154     //--------------------------------------------------------------------------
155     /// @brief      Notifies the delegate that the embedder has updated the
156     ///             contents of the texture with the specified identifier.
157     ///             Typically, Flutter will only render a frame if there is an
158     ///             updated layer tree. However, in cases where the layer tree
159     ///             is static but one of the externally composited textures has
160     ///             been updated by the embedder, the embedder needs to notify
161     ///             the rasterizer to render a new frame. In such cases, the
162     ///             existing layer tree may be reused with the frame composited
163     ///             with all updated external textures.
164     ///
165     /// @param[in]  texture_id  The identifier of the texture that has been
166     ///                         updated.
167     ///
168     virtual void OnPlatformViewMarkTextureFrameAvailable(
169         int64_t texture_id) = 0;
170   };
171 
172   //----------------------------------------------------------------------------
173   /// @brief      Creates a platform view with the specified delegate and task
174   ///             runner. The base class by itself does not do much but is
175   ///             suitable for use in test environments where full platform
176   ///             integration may not be necessary. The platform view may only
177   ///             be created, accessed and destroyed on the platform task
178   ///             runner.
179   ///
180   /// @param      delegate      The delegate. This is typically the shell.
181   /// @param[in]  task_runners  The task runners used by this platform view.
182   ///
183   explicit PlatformView(Delegate& delegate, TaskRunners task_runners);
184 
185   //----------------------------------------------------------------------------
186   /// @brief      Destroys the platform view. The platform view is owned by the
187   ///             shell and will be destroyed by the same on the platform tasks
188   ///             runner.
189   ///
190   virtual ~PlatformView();
191 
192   //----------------------------------------------------------------------------
193   /// @brief      Invoked by the shell to obtain a platform specific vsync
194   ///             waiter. It is optional for platforms to override this method
195   ///             and provide a custom vsync waiter because a timer based
196   ///             fall-back waiter is used by default. However, it is highly
197   ///             recommended that platform provide their own Vsync waiter as
198   ///             the timer based fall-back will not render frames aligned with
199   ///             vsync boundaries.
200   ///
201   /// @attention  If a timer based fall-back is used, a warning is logged to the
202   ///             console. In case this method is overridden in a subclass, it
203   ///             must return a valid vsync waiter. Returning null will lead to
204   ///             internal errors. If a valid vsync waiter cannot be returned,
205   ///             subclasses should just call the based class method instead.
206   ///
207   /// @return     A vsync waiter. If is an internal error to return a null
208   ///             waiter.
209   ///
210   virtual std::unique_ptr<VsyncWaiter> CreateVSyncWaiter(int32_t platform);
211 
212   //----------------------------------------------------------------------------
213   /// @brief      Used by embedders to dispatch a platform message to a
214   ///             running root isolate hosted by the engine. If an isolate is
215   ///             not running, the message is dropped. If there is no one on the
216   ///             other side listening on the channel, the message is dropped.
217   ///             When a platform message is dropped, any response handles
218   ///             associated with that message will be dropped as well. All
219   ///             users of platform messages must assume that message may not be
220   ///             delivered and/or their response handles may not be invoked.
221   ///             Platform messages are not buffered.
222   ///
223   ///             For embedders that wish to respond to platform message
224   ///             directed from the framework to the embedder, the
225   ///             `HandlePlatformMessage` method may be overridden.
226   ///
227   /// @see        HandlePlatformMessage()
228   ///
229   /// @param[in]  message  The platform message to deliver to the root isolate.
230   ///
231   void DispatchPlatformMessage(fml::RefPtr<PlatformMessage> message);
232 
233   //----------------------------------------------------------------------------
234   /// @brief      Overridden by embedders to perform actions in response to
235   ///             platform messages sent from the framework to the embedder.
236   ///             Default implementation of this method simply returns an empty
237   ///             response.
238   ///
239   ///             Embedders that wish to send platform messages to the framework
240   ///             may use the `DispatchPlatformMessage` method. This method is
241   ///             for messages that go the other way.
242   ///
243   /// @see        DisplatchPlatformMessage()
244   ///
245   /// @param[in]  message  The message
246   ///
247   virtual void HandlePlatformMessage(fml::RefPtr<PlatformMessage> message);
248 
249   //----------------------------------------------------------------------------
250   /// @brief      Ace PC preivew
251   ///
252   void SetIdleNotificationCallback(const IdleCallback& idleCallback);
253 
254   //----------------------------------------------------------------------------
255   /// @brief      Used by embedders to specify the updated viewport metrics. In
256   ///             response to this call, on the GPU thread, the rasterizer may
257   ///             need to be reconfigured to the updated viewport dimensions. On
258   ///             the UI thread, the framework may need to start generating a
259   ///             new frame for the updated viewport metrics as well.
260   ///
261   /// @param[in]  metrics  The updated viewport metrics.
262   ///
263   void SetViewportMetrics(const ViewportMetrics& metrics);
264 
265   //----------------------------------------------------------------------------
266   /// @brief      Used by embedders to notify the shell that a platform view
267   ///             has been created. This notification is used to create a
268   ///             rendering surface and pick the client rendering API to use to
269   ///             render into this surface. No frames will be scheduled or
270   ///             rendered before this call. The surface must remain valid till
271   ///             the corresponding call to NotifyDestroyed.
272   ///
273   void NotifyCreated();
274 
275   //----------------------------------------------------------------------------
276   /// @brief      Used by embedders to notify the shell that the platform view
277   ///             has been destroyed. This notification used to collect the
278   ///             rendering surface and all associated resources. Frame
279   ///             scheduling is also suspended.
280   ///
281   /// @attention  Subclasses may choose to override this method to perform
282   ///             platform specific functions. However, they must call the base
283   ///             class method at some point in their implementation.
284   ///
285   virtual void NotifyDestroyed();
286 
287   //----------------------------------------------------------------------------
288   /// @brief      Used by the shell to obtain a Skia GPU context that is capable
289   ///             of operating on the IO thread. The context must be in the same
290   ///             share-group as the Skia GPU context used on the render thread.
291   ///             This context will always be used on the IO thread. Because it
292   ///             is in the same share-group as the separate render thread
293   ///             context, any GPU resources uploaded in this context will be
294   ///             visible to the render thread context (synchronization of GPU
295   ///             resources is managed by Skia).
296   ///
297   ///             If such context cannot be created on the IO thread, callers
298   ///             may return `nullptr`. This will mean that all texture uploads
299   ///             will be queued onto the render thread which will cause
300   ///             performance issues. When this context is `nullptr`, an error
301   ///             is logged to the console. It is highly recommended that all
302   ///             platforms provide a resource context.
303   ///
304   /// @attention  Unlike all other methods on the platform view, this will be
305   ///             called on IO task runner.
306   ///
307   /// @return     The Skia GPU context that is in the same share-group as the
308   ///             main render thread GPU context. May be `nullptr` in case such
309   ///             a context cannot be created.
310   ///
311   virtual sk_sp<GrContext> CreateResourceContext() const;
312 
313   //----------------------------------------------------------------------------
314   /// @brief      Used by the shell to notify the embedder that the resource
315   ///             context previously obtained via a call to
316   ///             `CreateResourceContext()` is being collected. The embedder is
317   ///             free to collect an platform specific resources associated with
318   ///             this context.
319   ///
320   /// @attention  Unlike all other methods on the platform view, this will be
321   ///             called on IO task runner.
322   ///
323   virtual void ReleaseResourceContext() const;
324 
325   //----------------------------------------------------------------------------
326   /// @brief      Returns a weak pointer to the platform view. Since the
327   ///             platform view may only be created, accessed and destroyed on
328   ///             the platform thread, any access to the platform view from a
329   ///             non-platform task runner needs a weak pointer to the platform
330   ///             view along with a reference to the platform task runner. A
331   ///             task must be posted to the platform task runner with the weak
332   ///             pointer captured in the same. The platform view method may
333   ///             only be called in the posted task once the weak pointer
334   ///             validity has been checked. This method is used by callers to
335   ///             obtain that weak pointer.
336   ///
337   /// @return     The weak pointer to the platform view.
338   ///
339   fml::WeakPtr<PlatformView> GetWeakPtr() const;
340 
341   //----------------------------------------------------------------------------
342   /// @brief      Gives embedders a chance to react to a "cold restart" of the
343   ///             running isolate. The default implementation of this method
344   ///             does nothing.
345   ///
346   ///             While a "hot restart" patches a running isolate, a "cold
347   ///             restart" restarts the root isolate in a running shell.
348   ///
349   virtual void OnPreEngineRestart() const;
350 
351   //----------------------------------------------------------------------------
352   /// @brief      Sets a callback that gets executed when the rasterizer renders
353   ///             the next frame. Due to the asynchronous nature of rendering in
354   ///             Flutter, embedders usually add a placeholder over the
355   ///             contents in which Flutter is going to render when Flutter is
356   ///             first initialized. This callback may be used as a signal to
357   ///             remove that placeholder. The callback is executed on the
358   ///             render task runner and not the platform task runner. It is
359   ///             the embedder's responsibility to re-thread as necessary.
360   ///
361   /// @attention  The callback is executed on the render task runner and not the
362   ///             platform task runner. Embedders must re-thread as necessary.
363   ///
364   /// @param[in]  closure  The callback to execute on the render thread when the
365   ///                      next frame gets rendered.
366   ///
367   void SetNextFrameCallback(fml::closure closure);
368 
369   //----------------------------------------------------------------------------
370   /// @brief      Dispatches pointer events from the embedder to the
371   ///             framework. Each pointer data packet may contain multiple
372   ///             pointer input events. Each call to this method wakes up the UI
373   ///             thread.
374   ///
375   /// @param[in]  packet  The pointer data packet to dispatch to the framework.
376   ///
377   void DispatchPointerDataPacket(std::unique_ptr<PointerDataPacket> packet);
378 
379   //--------------------------------------------------------------------------
380   /// @brief      Used by the embedder to specify a texture that it wants the
381   ///             rasterizer to composite within the Flutter layer tree. All
382   ///             textures must have a unique identifier. When the rasterizer
383   ///             encounters an external texture within its hierarchy, it gives
384   ///             the embedder a chance to update that texture on the GPU thread
385   ///             before it composites the same on-screen.
386   ///
387   /// @attention  This method must only be called once per texture. When the
388   ///             texture is updated, calling `MarkTextureFrameAvailable` with
389   ///             the specified texture identifier is sufficient to make Flutter
390   ///             re-render the frame with the updated texture composited
391   ///             in-line.
392   ///
393   /// @see        UnregisterTexture, MarkTextureFrameAvailable
394   ///
395   /// @param[in]  texture  The texture that is being updated by the embedder
396   ///                      but composited by Flutter in its own hierarchy.
397   ///
398   void RegisterTexture(std::shared_ptr<flutter::Texture> texture);
399 
400   //--------------------------------------------------------------------------
401   /// @brief      Used by the embedder to notify the rasterizer that it will no
402   ///             longer attempt to composite the specified texture within the
403   ///             layer tree. This allows the rasterizer to collect associated
404   ///             resources.
405   ///
406   /// @attention  This call must only be called once per texture identifier.
407   ///
408   /// @see        RegisterTexture, MarkTextureFrameAvailable
409   ///
410   /// @param[in]  texture_id  The identifier of the texture to unregister. If
411   ///                         the texture has not been previously registered,
412   ///                         this call does nothing.
413   ///
414   void UnregisterTexture(int64_t texture_id);
415 
416   //--------------------------------------------------------------------------
417   /// @brief      Used by the embedder to notify the rasterizer that the context
418   ///             of the previously registered texture have been updated.
419   ///             Typically, Flutter will only render a frame if there is an
420   ///             updated layer tree. However, in cases where the layer tree
421   ///             is static but one of the externally composited textures has
422   ///             been updated by the embedder, the embedder needs to notify
423   ///             the rasterizer to render a new frame. In such cases, the
424   ///             existing layer tree may be reused with the frame re-composited
425   ///             with all updated external textures. Unlike the calls to
426   ///             register and unregister the texture, this call must be made
427   ///             each time a new texture frame is available.
428   ///
429   /// @see        RegisterTexture, UnregisterTexture
430   ///
431   /// @param[in]  texture_id  The identifier of the texture that has been
432   ///                         updated.
433   ///
434   void MarkTextureFrameAvailable(int64_t texture_id);
435 
436  protected:
437   PlatformView::Delegate& delegate_;
438   const TaskRunners task_runners_;
439 
440   SkISize size_;
441   fml::WeakPtrFactory<PlatformView> weak_factory_;
442 
443   // Unlike all other methods on the platform view, this is called on the GPU
444   // task runner.
445   virtual std::unique_ptr<Surface> CreateRenderingSurface();
446 
447  private:
448   FML_DISALLOW_COPY_AND_ASSIGN(PlatformView);
449 };
450 
451 }  // namespace flutter
452 
453 #endif  // COMMON_PLATFORM_VIEW_H_
454