platform_view.h 27.8 KB
Newer Older
M
Michael Goderbauer 已提交
1
// Copyright 2013 The Flutter Authors. All rights reserved.
2 3 4
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

5 6
#ifndef COMMON_PLATFORM_VIEW_H_
#define COMMON_PLATFORM_VIEW_H_
7

8 9
#include <memory>

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/semantics/custom_accessibility_action.h"
15
#include "flutter/lib/ui/semantics/semantics_node.h"
16 17 18
#include "flutter/lib/ui/window/platform_message.h"
#include "flutter/lib/ui/window/pointer_data_packet.h"
#include "flutter/lib/ui/window/viewport_metrics.h"
19
#include "flutter/shell/common/surface.h"
20
#include "flutter/shell/common/vsync_waiter.h"
21
#include "third_party/skia/include/core/SkSize.h"
22
#include "third_party/skia/include/gpu/GrContext.h"
23

24
namespace flutter {
25

26
class Shell;
27

28 29 30 31 32 33 34 35 36 37 38 39 40 41
//------------------------------------------------------------------------------
/// @brief      Platform views are created by the shell on the platform task
///             runner. Unless explicitly specified, all platform view methods
///             are called on the platform task runner as well. Platform views
///             are usually sub-classed on a per platform basis and the bulk of
///             the window system integration happens using that subclass. Since
///             most platform window toolkits are usually only safe to access on
///             a single "main" thread, any interaction that requires access to
///             the underlying platform's window toolkit is routed through the
///             platform view associated with that shell. This involves
///             operations like settings up and tearing down the render surface,
///             platform messages, interacting with accessibility features on
///             the platform, input events, etc.
///
42
class PlatformView {
43
 public:
44 45 46 47 48
  //----------------------------------------------------------------------------
  /// @brief      Used to forward events from the platform view to interested
  ///             subsystems. This forwarding is done by the shell which sets
  ///             itself up as the delegate of the platform view.
  ///
49 50
  class Delegate {
   public:
51 52 53 54 55 56 57 58 59
    //--------------------------------------------------------------------------
    /// @brief      Notifies the delegate that the platform view was created
    ///             with the given render surface. This surface is platform
    ///             (iOS, Android) and client-rendering API (OpenGL, Software,
    ///             Metal, Vulkan) specific. This is usually a sign to the
    ///             rasterizer to setup and begin rendering to that surface.
    ///
    /// @param[in]  surface  The surface
    ///
60
    virtual void OnPlatformViewCreated(std::unique_ptr<Surface> surface) = 0;
61

62 63 64 65 66 67
    //--------------------------------------------------------------------------
    /// @brief      Notifies the delegate that the platform view was destroyed.
    ///             This is usually a sign to the rasterizer to suspend
    ///             rendering a previously configured surface and collect any
    ///             intermediate resources.
    ///
68
    virtual void OnPlatformViewDestroyed() = 0;
69

70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
    //--------------------------------------------------------------------------
    /// @brief      Notifies the delegate that the specified callback needs to
    ///             be invoked after the rasterizer is done rendering the next
    ///             frame. This callback will be called on the render thread and
    ///             it is caller responsibility to perform any re-threading as
    ///             necessary. Due to the asynchronous nature of rendering in
    ///             Flutter, embedders usually add a placeholder over the
    ///             contents in which Flutter is going to render when Flutter is
    ///             first initialized. This callback may be used as a signal to
    ///             remove that placeholder.
    ///
    /// @attention  The callback will be invoked on the render thread and not
    ///             the calling thread.
    ///
    /// @param[in]  closure  The callback to execute on the next frame.
    ///
86
    virtual void OnPlatformViewSetNextFrameCallback(fml::closure closure) = 0;
87

88 89 90 91 92 93 94 95
    //--------------------------------------------------------------------------
    /// @brief      Notifies the delegate the viewport metrics of the platform
    ///             view have been updated. The rasterizer will need to be
    ///             reconfigured to render the frame in the updated viewport
    ///             metrics.
    ///
    /// @param[in]  metrics  The updated viewport metrics.
    ///
96
    virtual void OnPlatformViewSetViewportMetrics(
97
        const ViewportMetrics& metrics) = 0;
98

99 100 101 102 103 104 105 106 107
    //--------------------------------------------------------------------------
    /// @brief      Notifies the delegate that the platform has dispatched a
    ///             platform message from the embedder to the Flutter
    ///             application. This message must be forwarded to the running
    ///             isolate hosted by the engine on the UI thread.
    ///
    /// @param[in]  message  The platform message to dispatch to the running
    ///                      root isolate.
    ///
108
    virtual void OnPlatformViewDispatchPlatformMessage(
109
        fml::RefPtr<PlatformMessage> message) = 0;
110

111 112 113 114 115 116 117 118 119
    //--------------------------------------------------------------------------
    /// @brief      Notifies the delegate that the platform view has encountered
    ///             a pointer event. This pointer event needs to be forwarded to
    ///             the running root isolate hosted by the engine on the UI
    ///             thread.
    ///
    /// @param[in]  packet  The pointer data packet containing multiple pointer
    ///                     events.
    ///
120
    virtual void OnPlatformViewDispatchPointerDataPacket(
121
        std::unique_ptr<PointerDataPacket> packet) = 0;
122

123 124 125 126 127 128 129 130 131 132 133 134
    //--------------------------------------------------------------------------
    /// @brief      Notifies the delegate that the platform view has encountered
    ///             an accessibility related action on the specified node. This
    ///             event must be forwarded to the running root isolate hosted
    ///             by the engine on the UI thread.
    ///
    /// @param[in]  id      The identifier of the accessibility node.
    /// @param[in]  action  The accessibility related action performed on the
    ///                     node of the specified ID.
    /// @param[in]  args    An optional list of argument that apply to the
    ///                     specified action.
    ///
135 136
    virtual void OnPlatformViewDispatchSemanticsAction(
        int32_t id,
137
        SemanticsAction action,
138 139
        std::vector<uint8_t> args) = 0;

140 141 142 143 144 145 146 147 148
    //--------------------------------------------------------------------------
    /// @brief      Notifies the delegate that the embedder has expressed an
    ///             opinion about whether the accessibility tree needs to be
    ///             enabled or disabled. This information needs to be forwarded
    ///             to the root isolate running on the UI thread.
    ///
    /// @param[in]  enabled  Whether the accessibility tree is enabled or
    ///                      disabled.
    ///
149
    virtual void OnPlatformViewSetSemanticsEnabled(bool enabled) = 0;
150

151 152 153 154 155 156 157 158 159 160 161 162 163
    //--------------------------------------------------------------------------
    /// @brief      Notifies the delegate that the embedder has expressed an
    ///             opinion about the features to enable in the accessibility
    ///             tree.
    ///
    ///             The engine does not care about the accessibility feature
    ///             flags as all it does is forward this information from the
    ///             embedder to the framework. However, curious readers may
    ///             refer to `AccessibilityFeatures` in `window.dart` for
    ///             currently supported accessibility feature flags.
    ///
    /// @param[in]  flags  The features to enable in the accessibility tree.
    ///
164
    virtual void OnPlatformViewSetAccessibilityFeatures(int32_t flags) = 0;
165

166 167 168 169 170 171 172 173 174 175 176 177
    //--------------------------------------------------------------------------
    /// @brief      Notifies the delegate that the embedder has specified a
    ///             texture that it want the rasterizer to composite within the
    ///             Flutter layer tree. All textures must have a unique
    ///             identifier. When the rasterizer encounters an external
    ///             texture within its hierarchy, it gives the embedder a chance
    ///             to update that texture on the GPU thread before it
    ///             composites the same on-screen.
    ///
    /// @param[in]  texture  The texture that is being updated by the embedder
    ///                      but composited by Flutter in its own hierarchy.
    ///
178
    virtual void OnPlatformViewRegisterTexture(
179 180 181 182 183 184 185 186 187 188 189 190
        std::shared_ptr<Texture> texture) = 0;

    //--------------------------------------------------------------------------
    /// @brief      Notifies the delegate that the embedder will no longer
    ///             attempt to composite the specified texture within the layer
    ///             tree. This allows the rasterizer to collect associated
    ///             resources.
    ///
    /// @param[in]  texture_id  The identifier of the texture to unregister. If
    ///                         the texture has not been previously registered,
    ///                         this call does nothing.
    ///
191
    virtual void OnPlatformViewUnregisterTexture(int64_t texture_id) = 0;
192

193 194 195 196 197 198 199 200 201 202 203 204 205 206
    //--------------------------------------------------------------------------
    /// @brief      Notifies the delegate that the embedder has updated the
    ///             contents of the texture with the specified identifier.
    ///             Typically, Flutter will only render a frame if there is an
    ///             updated layer tree. However, in cases where the layer tree
    ///             is static but one of the externally composited textures has
    ///             been updated by the embedder, the embedder needs to notify
    ///             the rasterizer to render a new frame. In such cases, the
    ///             existing layer tree may be reused with the frame composited
    ///             with all updated external textures.
    ///
    /// @param[in]  texture_id  The identifier of the texture that has been
    ///                         updated.
    ///
207 208
    virtual void OnPlatformViewMarkTextureFrameAvailable(
        int64_t texture_id) = 0;
209 210
  };

211 212 213 214 215 216 217 218 219 220 221
  //----------------------------------------------------------------------------
  /// @brief      Creates a platform view with the specified delegate and task
  ///             runner. The base class by itself does not do much but is
  ///             suitable for use in test environments where full platform
  ///             integration may not be necessary. The platform view may only
  ///             be created, accessed and destroyed on the platform task
  ///             runner.
  ///
  /// @param      delegate      The delegate. This is typically the shell.
  /// @param[in]  task_runners  The task runners used by this platform view.
  ///
222
  explicit PlatformView(Delegate& delegate, TaskRunners task_runners);
223

224 225 226 227 228
  //----------------------------------------------------------------------------
  /// @brief      Destroys the platform view. The platform view is owned by the
  ///             shell and will be destroyed by the same on the platform tasks
  ///             runner.
  ///
229
  virtual ~PlatformView();
230

231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248
  //----------------------------------------------------------------------------
  /// @brief      Invoked by the shell to obtain a platform specific vsync
  ///             waiter. It is optional for platforms to override this method
  ///             and provide a custom vsync waiter because a timer based
  ///             fall-back waiter is used by default. However, it is highly
  ///             recommended that platform provide their own Vsync waiter as
  ///             the timer based fall-back will not render frames aligned with
  ///             vsync boundaries.
  ///
  /// @attention  If a timer based fall-back is used, a warning is logged to the
  ///             console. In case this method is overridden in a subclass, it
  ///             must return a valid vsync waiter. Returning null will lead to
  ///             internal errors. If a valid vsync waiter cannot be returned,
  ///             subclasses should just call the based class method instead.
  ///
  /// @return     A vsync waiter. If is an internal error to return a null
  ///             waiter.
  ///
249
  virtual std::unique_ptr<VsyncWaiter> CreateVSyncWaiter();
250

251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269
  //----------------------------------------------------------------------------
  /// @brief      Used by embedders to dispatch a platform message to a
  ///             running root isolate hosted by the engine. If an isolate is
  ///             not running, the message is dropped. If there is no one on the
  ///             other side listening on the channel, the message is dropped.
  ///             When a platform message is dropped, any response handles
  ///             associated with that message will be dropped as well. All
  ///             users of platform messages must assume that message may not be
  ///             delivered and/or their response handles may not be invoked.
  ///             Platform messages are not buffered.
  ///
  ///             For embedders that wish to respond to platform message
  ///             directed from the framework to the embedder, the
  ///             `HandlePlatformMessage` method may be overridden.
  ///
  /// @see        HandlePlatformMessage()
  ///
  /// @param[in]  message  The platform message to deliver to the root isolate.
  ///
270
  void DispatchPlatformMessage(fml::RefPtr<PlatformMessage> message);
271

272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296
  //----------------------------------------------------------------------------
  /// @brief      Overridden by embedders to perform actions in response to
  ///             platform messages sent from the framework to the embedder.
  ///             Default implementation of this method simply returns an empty
  ///             response.
  ///
  ///             Embedders that wish to send platform messages to the framework
  ///             may use the `DispatchPlatformMessage` method. This method is
  ///             for messages that go the other way.
  ///
  /// @see        DisplatchPlatformMessage()
  ///
  /// @param[in]  message  The message
  ///
  virtual void HandlePlatformMessage(fml::RefPtr<PlatformMessage> message);

  //----------------------------------------------------------------------------
  /// @brief      Used by embedders to dispatch an accessibility action to a
  ///             running isolate hosted by the engine.
  ///
  /// @param[in]  id      The identifier of the accessibility node on which to
  ///                     perform the action.
  /// @param[in]  action  The action
  /// @param[in]  args    The arguments
  ///
297
  void DispatchSemanticsAction(int32_t id,
298
                               SemanticsAction action,
299
                               std::vector<uint8_t> args);
300

301 302 303 304 305 306 307 308 309 310 311
  //----------------------------------------------------------------------------
  /// @brief      Used by embedder to notify the running isolate hosted by the
  ///             engine on the UI thread that the accessibility tree needs to
  ///             be generated.
  ///
  /// @attention  Subclasses may choose to override this method to perform
  ///             platform specific functions. However, they must call the base
  ///             class method at some point in their implementation.
  ///
  /// @param[in]  enabled  Whether the accessibility tree needs to be generated.
  ///
312
  virtual void SetSemanticsEnabled(bool enabled);
313

314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331
  //----------------------------------------------------------------------------
  /// @brief      Used by the embedder to specify the features to enable in the
  ///             accessibility tree generated by the isolate. This information
  ///             is forwarded to the root isolate hosted by the engine on the
  ///             UI thread.
  ///
  ///             The engine does not care about the accessibility feature flags
  ///             as all it does is forward this information from the embedder
  ///             to the framework. However, curious readers may refer to
  ///             `AccessibilityFeatures` in `window.dart` for currently
  ///             supported accessibility feature flags.
  ///
  /// @attention  Subclasses may choose to override this method to perform
  ///             platform specific functions. However, they must call the base
  ///             class method at some point in their implementation.
  ///
  /// @param[in]  flags  The features to enable in the accessibility tree.
  ///
332
  virtual void SetAccessibilityFeatures(int32_t flags);
333

334 335
  //----------------------------------------------------------------------------
  /// @brief      Used by the framework to tell the embedder to apply the
336 337
  ///             specified semantics node updates. The default implementation
  ///             of this method does nothing.
338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358
  ///
  /// @see        SemanticsNode, SemticsNodeUpdates,
  ///             CustomAccessibilityActionUpdates
  ///
  /// @param[in]  updates  A map with the stable semantics node identifier as
  ///                      key and the node properties as the value.
  /// @param[in]  actions  A map with the stable semantics node identifier as
  ///                      key and the custom node action as the value.
  ///
  virtual void UpdateSemantics(SemanticsNodeUpdates updates,
                               CustomAccessibilityActionUpdates actions);

  //----------------------------------------------------------------------------
  /// @brief      Used by embedders to specify the updated viewport metrics. In
  ///             response to this call, on the GPU thread, the rasterizer may
  ///             need to be reconfigured to the updated viewport dimensions. On
  ///             the UI thread, the framework may need to start generating a
  ///             new frame for the updated viewport metrics as well.
  ///
  /// @param[in]  metrics  The updated viewport metrics.
  ///
359
  void SetViewportMetrics(const ViewportMetrics& metrics);
360

361 362 363 364 365 366 367 368
  //----------------------------------------------------------------------------
  /// @brief      Used by embedders to notify the shell that a platform view
  ///             has been created. This notification is used to create a
  ///             rendering surface and pick the client rendering API to use to
  ///             render into this surface. No frames will be scheduled or
  ///             rendered before this call. The surface must remain valid till
  ///             the corresponding call to NotifyDestroyed.
  ///
369
  void NotifyCreated();
370

371 372 373 374 375 376 377 378 379 380
  //----------------------------------------------------------------------------
  /// @brief      Used by embedders to notify the shell that the platform view
  ///             has been destroyed. This notification used to collect the
  ///             rendering surface and all associated resources. Frame
  ///             scheduling is also suspended.
  ///
  /// @attention  Subclasses may choose to override this method to perform
  ///             platform specific functions. However, they must call the base
  ///             class method at some point in their implementation.
  ///
381
  virtual void NotifyDestroyed();
382

383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406
  //----------------------------------------------------------------------------
  /// @brief      Used by the shell to obtain a Skia GPU context that is capable
  ///             of operating on the IO thread. The context must be in the same
  ///             share-group as the Skia GPU context used on the render thread.
  ///             This context will always be used on the IO thread. Because it
  ///             is in the same share-group as the separate render thread
  ///             context, any GPU resources uploaded in this context will be
  ///             visible to the render thread context (synchronization of GPU
  ///             resources is managed by Skia).
  ///
  ///             If such context cannot be created on the IO thread, callers
  ///             may return `nullptr`. This will mean that all texture uploads
  ///             will be queued onto the render thread which will cause
  ///             performance issues. When this context is `nullptr`, an error
  ///             is logged to the console. It is highly recommended that all
  ///             platforms provide a resource context.
  ///
  /// @attention  Unlike all other methods on the platform view, this will be
  ///             called on IO task runner.
  ///
  /// @return     The Skia GPU context that is in the same share-group as the
  ///             main render thread GPU context. May be `nullptr` in case such
  ///             a context cannot be created.
  ///
407
  virtual sk_sp<GrContext> CreateResourceContext() const;
408

409 410 411 412 413 414 415 416 417 418
  //----------------------------------------------------------------------------
  /// @brief      Used by the shell to notify the embedder that the resource
  ///             context previously obtained via a call to
  ///             `CreateResourceContext()` is being collected. The embedder is
  ///             free to collect an platform specific resources associated with
  ///             this context.
  ///
  /// @attention  Unlike all other methods on the platform view, this will be
  ///             called on IO task runner.
  ///
419 420
  virtual void ReleaseResourceContext() const;

421 422 423 424 425 426 427 428 429 430 431 432 433 434
  //----------------------------------------------------------------------------
  /// @brief      Returns a weak pointer to the platform view. Since the
  ///             platform view may only be created, accessed and destroyed on
  ///             the platform thread, any access to the platform view from a
  ///             non-platform task runner needs a weak pointer to the platform
  ///             view along with a reference to the platform task runner. A
  ///             task must be posted to the platform task runner with the weak
  ///             pointer captured in the same. The platform view method may
  ///             only be called in the posted task once the weak pointer
  ///             validity has been checked. This method is used by callers to
  ///             obtain that weak pointer.
  ///
  /// @return     The weak pointer to the platform view.
  ///
435
  fml::WeakPtr<PlatformView> GetWeakPtr() const;
436

437 438 439 440 441 442 443 444
  //----------------------------------------------------------------------------
  /// @brief      Gives embedders a chance to react to a "cold restart" of the
  ///             running isolate. The default implementation of this method
  ///             does nothing.
  ///
  ///             While a "hot restart" patches a running isolate, a "cold
  ///             restart" restarts the root isolate in a running shell.
  ///
445 446
  virtual void OnPreEngineRestart() const;

447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462
  //----------------------------------------------------------------------------
  /// @brief      Sets a callback that gets executed when the rasterizer renders
  ///             the next frame. Due to the asynchronous nature of rendering in
  ///             Flutter, embedders usually add a placeholder over the
  ///             contents in which Flutter is going to render when Flutter is
  ///             first initialized. This callback may be used as a signal to
  ///             remove that placeholder. The callback is executed on the
  ///             render task runner and not the platform task runner. It is
  ///             the embedder's responsibility to re-thread as necessary.
  ///
  /// @attention  The callback is executed on the render task runner and not the
  ///             platform task runner. Embedders must re-thread as necessary.
  ///
  /// @param[in]  closure  The callback to execute on the render thread when the
  ///                      next frame gets rendered.
  ///
463
  void SetNextFrameCallback(fml::closure closure);
464

465 466 467 468 469 470 471 472
  //----------------------------------------------------------------------------
  /// @brief      Dispatches pointer events from the embedder to the
  ///             framework. Each pointer data packet may contain multiple
  ///             pointer input events. Each call to this method wakes up the UI
  ///             thread.
  ///
  /// @param[in]  packet  The pointer data packet to dispatch to the framework.
  ///
473
  void DispatchPointerDataPacket(std::unique_ptr<PointerDataPacket> packet);
474

475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493
  //--------------------------------------------------------------------------
  /// @brief      Used by the embedder to specify a texture that it wants the
  ///             rasterizer to composite within the Flutter layer tree. All
  ///             textures must have a unique identifier. When the rasterizer
  ///             encounters an external texture within its hierarchy, it gives
  ///             the embedder a chance to update that texture on the GPU thread
  ///             before it composites the same on-screen.
  ///
  /// @attention  This method must only be called once per texture. When the
  ///             texture is updated, calling `MarkTextureFrameAvailable` with
  ///             the specified texture identifier is sufficient to make Flutter
  ///             re-render the frame with the updated texture composited
  ///             in-line.
  ///
  /// @see        UnregisterTexture, MarkTextureFrameAvailable
  ///
  /// @param[in]  texture  The texture that is being updated by the embedder
  ///                      but composited by Flutter in its own hierarchy.
  ///
494
  void RegisterTexture(std::shared_ptr<flutter::Texture> texture);
495

496 497 498 499 500 501 502 503 504 505 506 507 508 509
  //--------------------------------------------------------------------------
  /// @brief      Used by the embedder to notify the rasterizer that it will no
  ///             longer attempt to composite the specified texture within the
  ///             layer tree. This allows the rasterizer to collect associated
  ///             resources.
  ///
  /// @attention  This call must only be called once per texture identifier.
  ///
  /// @see        RegisterTexture, MarkTextureFrameAvailable
  ///
  /// @param[in]  texture_id  The identifier of the texture to unregister. If
  ///                         the texture has not been previously registered,
  ///                         this call does nothing.
  ///
510 511
  void UnregisterTexture(int64_t texture_id);

512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529
  //--------------------------------------------------------------------------
  /// @brief      Used by the embedder to notify the rasterizer that the context
  ///             of the previously registered texture have been updated.
  ///             Typically, Flutter will only render a frame if there is an
  ///             updated layer tree. However, in cases where the layer tree
  ///             is static but one of the externally composited textures has
  ///             been updated by the embedder, the embedder needs to notify
  ///             the rasterizer to render a new frame. In such cases, the
  ///             existing layer tree may be reused with the frame re-composited
  ///             with all updated external textures. Unlike the calls to
  ///             register and unregister the texture, this call must be made
  ///             each time a new texture frame is available.
  ///
  /// @see        RegisterTexture, UnregisterTexture
  ///
  /// @param[in]  texture_id  The identifier of the texture that has been
  ///                         updated.
  ///
530
  void MarkTextureFrameAvailable(int64_t texture_id);
531

532
 protected:
533
  PlatformView::Delegate& delegate_;
534
  const TaskRunners task_runners_;
535

536
  SkISize size_;
537 538
  fml::WeakPtrFactory<PlatformView> weak_factory_;

539 540
  // Unlike all other methods on the platform view, this is called on the GPU
  // task runner.
541
  virtual std::unique_ptr<Surface> CreateRenderingSurface();
542

543
 private:
544
  FML_DISALLOW_COPY_AND_ASSIGN(PlatformView);
545 546
};

547
}  // namespace flutter
548

549
#endif  // COMMON_PLATFORM_VIEW_H_