tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

NativeLayerCA.h (21558B)


      1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* This Source Code Form is subject to the terms of the Mozilla Public
      3 * License, v. 2.0. If a copy of the MPL was not distributed with this
      4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      5 
      6 #ifndef mozilla_layers_NativeLayerCA_h
      7 #define mozilla_layers_NativeLayerCA_h
      8 
      9 #include <IOSurface/IOSurfaceRef.h>
     10 
     11 #include <deque>
     12 #include <ostream>
     13 
     14 #include "mozilla/Mutex.h"
     15 #include "mozilla/TimeStamp.h"
     16 
     17 #include "mozilla/gfx/MacIOSurface.h"
     18 #include "mozilla/layers/NativeLayer.h"
     19 #include "mozilla/layers/NativeLayerMacSurfaceHandler.h"
     20 #include "mozilla/webrender/RenderMacIOSurfaceTextureHost.h"
     21 #include "CFTypeRefPtr.h"
     22 #include "nsRegion.h"
     23 #include "nsISupportsImpl.h"
     24 
     25 #ifdef __OBJC__
     26 @class CALayer;
     27 @class CARenderer;
     28 #else
     29 typedef void CALayer;
     30 typedef void CARenderer;
     31 #endif
     32 
     33 namespace mozilla {
     34 
     35 namespace gl {
     36 class GLContextCGL;
     37 class MozFramebuffer;
     38 }  // namespace gl
     39 namespace wr {
     40 class RenderMacIOSurfaceTextureHost;
     41 }  // namespace wr
     42 
     43 namespace layers {
     44 
     45 class NativeLayerRootSnapshotterCA;
     46 
     47 enum class VideoLowPowerType {
     48  // These must be kept synchronized with the telemetry histogram enums.
     49  NotVideo,           // Never emitted as telemetry. No video is visible.
     50  LowPower,           // As best we can tell, we are in the "detached",
     51                      // low-power compositing mode. We don't use "Success"
     52                      // because of name collision with telemetry generation.
     53  FailMultipleVideo,  // There is more than one video visible.
     54  FailWindowed,       // The window is not fullscreen.
     55  FailOverlaid,       // Something is on top of the video (likely captions).
     56  FailBacking,        // The layer behind the video is not full-coverage black.
     57  FailMacOSVersion,   // macOS version does not meet requirements.
     58  FailPref,           // Pref is not set.
     59  FailSurface,        // Surface is not eligible.
     60  FailEnqueue,        // Enqueueing the video didn't work.
     61 };
     62 
     63 // The type of update needed to apply the pending changes to a NativeLayerCA
     64 // representation.
     65 //
     66 // Order is important. Each enum must fully encompass the work implied by the
     67 // previous enums.
     68 enum class NativeLayerCAUpdateType {
     69  None,
     70  OnlyVideo,
     71  All,
     72 };
     73 
     74 class SnapshotterCADelegate {
     75 public:
     76  virtual ~SnapshotterCADelegate();
     77 
     78  virtual float BackingScale() const { return 1.0f; }
     79  virtual bool DoCustomReadbackForReftestsIfDesired(
     80      const gfx::IntSize& aReadbackSize, gfx::SurfaceFormat aReadbackFormat,
     81      const Range<uint8_t>& aReadbackBuffer) {
     82    return false;
     83  }
     84  virtual void UpdateSnapshotterLayers(CALayer* aRootCALayer) = 0;
     85  virtual void OnSnapshotterDestroyed(
     86      NativeLayerRootSnapshotterCA* aSnapshotter) {}
     87 };
     88 
     89 // NativeLayerRootCA is the CoreAnimation implementation of the NativeLayerRoot
     90 // interface. A NativeLayerRootCA is created by the widget around an existing
     91 // CALayer with a call to CreateForCALayer - this CALayer is the root of the
     92 // "onscreen" representation of this layer tree.
     93 // All methods can be called from any thread, there is internal locking.
     94 // All effects from mutating methods are buffered locally and don't modify the
     95 // underlying CoreAnimation layers until CommitToScreen() is called. This
     96 // ensures that the modifications happen on the right thread.
     97 //
     98 // More specifically: During normal operation, screen updates are driven from a
     99 // compositing thread. On this thread, the layers are created / destroyed, their
    100 // contents are painted, and the result is committed to the screen. However,
    101 // there are some scenarios that need to involve the main thread, most notably
    102 // window resizing: During a window resize, we still need the drawing part to
    103 // happen on the compositing thread, but the modifications to the underlying
    104 // CALayers need to happen on the main thread, once compositing is done.
    105 //
    106 // NativeLayerRootCA + NativeLayerCA create and maintain *two* CALayer tree
    107 // representations: An "onscreen" representation and an "offscreen"
    108 // representation. These representations are updated via calls to
    109 // CommitToScreen() and CommitOffscreen(), respectively. The reason for having
    110 // two representations is the following: Our implementation of the snapshotter
    111 // API uses CARenderer, which lets us render the composited result of our layer
    112 // tree into a GPU buffer. But CARenderer requires "ownership" of the rendered
    113 // CALayers in the sense that it associates the CALayers with a local
    114 // "CAContext". A CALayer can only be associated with one CAContext at any time.
    115 // If we wanted te render our *onscreen* CALayers with CARenderer, we would need
    116 // to remove them from the window, reparent them to the CARenderer, render them,
    117 // and then put them back into the window. This would lead to a visible flashing
    118 // effect. To solve this problem, we build two CALayer representations, so that
    119 // one representation can stay inside the window and the other can stay attached
    120 // to the CARenderer.
    121 class NativeLayerRootCA final : public NativeLayerRoot {
    122 public:
    123  static already_AddRefed<NativeLayerRootCA> CreateForCALayer(CALayer* aLayer);
    124 
    125  virtual NativeLayerRootCA* AsNativeLayerRootCA() override { return this; }
    126 
    127  // Can be called on any thread at any point. Returns whether comitting was
    128  // successful. Will return false if called off the main thread while
    129  // off-main-thread commits are suspended.
    130  bool CommitToScreen() override;
    131 
    132  void CommitOffscreen(CALayer* aRootCALayer);
    133  void OnNativeLayerRootSnapshotterDestroyed(
    134      NativeLayerRootSnapshotterCA* aNativeLayerRootSnapshotter);
    135 
    136  // Enters a mode during which CommitToScreen(), when called on a non-main
    137  // thread, will not apply any updates to the CALayer tree.
    138  void SuspendOffMainThreadCommits();
    139 
    140  // Exits the mode entered by SuspendOffMainThreadCommits().
    141  // Returns true if the last CommitToScreen() was canceled due to suspension,
    142  // indicating that another call to CommitToScreen() is needed.
    143  bool UnsuspendOffMainThreadCommits();
    144 
    145  bool AreOffMainThreadCommitsSuspended();
    146 
    147  void DumpLayerTreeToFile(const char* aPath,
    148                           const MutexAutoLock& aProofOfLock);
    149 
    150  enum class WhichRepresentation : uint8_t { ONSCREEN, OFFSCREEN };
    151 
    152  // Overridden methods
    153  already_AddRefed<NativeLayer> CreateLayer(
    154      const gfx::IntSize& aSize, bool aIsOpaque,
    155      SurfacePoolHandle* aSurfacePoolHandle) override;
    156  void AppendLayer(NativeLayer* aLayer) override;
    157  void RemoveLayer(NativeLayer* aLayer) override;
    158  void SetLayers(const nsTArray<RefPtr<NativeLayer>>& aLayers) override;
    159  UniquePtr<NativeLayerRootSnapshotter> CreateSnapshotter() override;
    160 
    161  void SetBackingScale(float aBackingScale);
    162  float BackingScale();
    163 
    164  already_AddRefed<NativeLayer> CreateLayerForExternalTexture(
    165      bool aIsOpaque) override;
    166  already_AddRefed<NativeLayer> CreateLayerForColor(
    167      gfx::DeviceColor aColor) override;
    168 
    169  // A macOS-specific layer creation method, which uses no
    170  // SurfacePoolHandle, because it will be handed surfaces directly.
    171  already_AddRefed<NativeLayerCA> CreateLayerForSurfacePresentation(
    172      const gfx::IntSize& aSize, bool aIsOpaque);
    173 
    174  void SetWindowIsFullscreen(bool aFullscreen);
    175 
    176  VideoLowPowerType CheckVideoLowPower(const MutexAutoLock& aProofOfLock);
    177 
    178 protected:
    179  explicit NativeLayerRootCA(CALayer* aLayer);
    180  ~NativeLayerRootCA() override;
    181 
    182  // Do a commit of the pending changes to the CALayers. This is used for both
    183  // onscreen commits (modifying the CALayers attached to the NSView), and for
    184  // "offscreen" commits.
    185  // "Offscreen" commits are updating a separate copy of the CALayer tree for
    186  // use with CARenderer by the snapshotter.
    187  void CommitRepresentation(WhichRepresentation aRepresentation,
    188                            CALayer* aRootCALayer,
    189                            const nsTArray<RefPtr<NativeLayerCA>>& aSublayers,
    190                            bool aMutatedLayerStructure,
    191                            bool aWindowIsFullscreen);
    192 
    193  void SetMutatedLayerStructure();
    194 
    195  using UpdateType = NativeLayerCAUpdateType;
    196  UpdateType GetMaxUpdateRequired(
    197      WhichRepresentation aRepresentation,
    198      const nsTArray<RefPtr<NativeLayerCA>>& aSublayers,
    199      bool aMutatedLayerStructure) const;
    200 
    201  // An implementation of SnapshotterCADelegate, backed by a NativeLayerRootCA.
    202  struct SnapshotterDelegate final : public SnapshotterCADelegate {
    203    explicit SnapshotterDelegate(NativeLayerRootCA* aLayerRoot);
    204    virtual ~SnapshotterDelegate() override;
    205    virtual float BackingScale() const override {
    206      return mLayerRoot->BackingScale();
    207    }
    208    virtual void UpdateSnapshotterLayers(CALayer* aRootCALayer) override {
    209      mLayerRoot->CommitOffscreen(aRootCALayer);
    210    }
    211    virtual void OnSnapshotterDestroyed(
    212        NativeLayerRootSnapshotterCA* aSnapshotter) override {
    213      mLayerRoot->OnNativeLayerRootSnapshotterDestroyed(aSnapshotter);
    214    }
    215    RefPtr<NativeLayerRootCA> mLayerRoot;
    216  };
    217 
    218  Mutex mMutex MOZ_UNANNOTATED;              // protects all other fields
    219  CALayer* mOnscreenRootCALayer = nullptr;   // strong
    220  CALayer* mOffscreenRootCALayer = nullptr;  // strong
    221  NativeLayerRootSnapshotterCA* mWeakSnapshotter = nullptr;
    222  nsTArray<RefPtr<NativeLayerCA>> mSublayers;  // in z-order
    223  float mBackingScale = 1.0f;
    224  bool mMutated = false;
    225 
    226  // While mOffMainThreadCommitsSuspended is true, no commits
    227  // should happen on a non-main thread, because they might race with
    228  // main-thread driven updates such as window shape changes, and cause
    229  // glitches.
    230  bool mOffMainThreadCommitsSuspended = false;
    231 
    232  // Set to true if CommitToScreen() was aborted because of commit suspension.
    233  // Set to false when CommitToScreen() completes successfully. When true,
    234  // indicates that CommitToScreen() needs to be called at the next available
    235  // opportunity.
    236  bool mCommitPending = false;
    237 
    238  // Updated by the layer's view's window to match the fullscreen state
    239  // of that window.
    240  bool mWindowIsFullscreen = false;
    241 
    242  // Whether mSublayers has changed since the last onscreen / offscreen commit.
    243  bool mMutatedOnscreenLayerStructure = false;
    244  bool mMutatedOffscreenLayerStructure = false;
    245 
    246  // How many times have we committed since the last time we emitted
    247  // telemetry?
    248  unsigned int mTelemetryCommitCount = 0;
    249 };
    250 
    251 class RenderSourceNLRS;
    252 
    253 #ifdef XP_MACOSX
    254 class NativeLayerRootSnapshotterCA final : public NativeLayerRootSnapshotter {
    255 public:
    256  static UniquePtr<NativeLayerRootSnapshotterCA> Create(
    257      UniquePtr<SnapshotterCADelegate>&& aDelegate);
    258  virtual ~NativeLayerRootSnapshotterCA();
    259 
    260  bool ReadbackPixels(const gfx::IntSize& aReadbackSize,
    261                      gfx::SurfaceFormat aReadbackFormat,
    262                      const Range<uint8_t>& aReadbackBuffer) override;
    263  already_AddRefed<profiler_screenshots::RenderSource> GetWindowContents(
    264      const gfx::IntSize& aWindowSize) override;
    265  already_AddRefed<profiler_screenshots::DownscaleTarget> CreateDownscaleTarget(
    266      const gfx::IntSize& aSize) override;
    267  already_AddRefed<profiler_screenshots::AsyncReadbackBuffer>
    268  CreateAsyncReadbackBuffer(const gfx::IntSize& aSize) override;
    269 
    270 protected:
    271  NativeLayerRootSnapshotterCA(UniquePtr<SnapshotterCADelegate>&& aDelegate,
    272                               RefPtr<gl::GLContext>&& aGL);
    273  void UpdateSnapshot(const gfx::IntSize& aSize);
    274 
    275  UniquePtr<SnapshotterCADelegate> mDelegate;
    276  RefPtr<gl::GLContext> mGL;
    277 
    278  // Can be null. Created and updated in UpdateSnapshot.
    279  RefPtr<RenderSourceNLRS> mSnapshot;
    280  CARenderer* mRenderer = nullptr;  // strong
    281 };
    282 #endif
    283 
    284 // Wraps one CALayer representation of NativeLayerCA.
    285 struct NativeLayerCARepresentation {
    286  using UpdateType = NativeLayerCAUpdateType;
    287 
    288  NativeLayerCARepresentation();
    289  ~NativeLayerCARepresentation();
    290 
    291  // Returns null if the layer is currently completely clipped out.
    292  CALayer* UnderlyingCALayer() {
    293    return mWrappingCALayerHasExtent ? mWrappingCALayer : nullptr;
    294  }
    295 
    296  bool EnqueueSurface(IOSurfaceRef aSurfaceRef);
    297 
    298  // Applies buffered changes to the native CALayers. The contract with the
    299  // caller is as follows: If any of these values have changed since the last
    300  // call to ApplyChanges, mMutated[Field] needs to have been set to true
    301  // before the call. If aUpdate is not All, then a partial update will be
    302  // applied. In such a case, ApplyChanges may not make any changes that
    303  // require a CATransacation, because no transaction will be created. In a
    304  // a partial update, the return value will indicate if all the needed
    305  // changes were able to be applied under these restrictions. A false return
    306  // value indicates an All update is necessary.
    307  bool ApplyChanges(NativeLayerCAUpdateType aUpdate, const gfx::IntSize& aSize,
    308                    bool aIsOpaque, const gfx::IntPoint& aPosition,
    309                    const gfx::Matrix4x4& aTransform,
    310                    const gfx::IntRect& aDisplayRect,
    311                    const Maybe<gfx::IntRect>& aClipRect,
    312                    const Maybe<gfx::RoundedRect>& aRoundedClip,
    313                    float aBackingScale, bool aSurfaceIsFlipped,
    314                    gfx::SamplingFilter aSamplingFilter, bool aSpecializeVideo,
    315                    const CFTypeRefPtr<IOSurfaceRef>& aFrontSurface,
    316                    const Maybe<gfx::DeviceColor>& aColor, bool aIsDRM,
    317                    bool aIsVideo);
    318 
    319  // Return whether any aspects of this layer representation have been mutated
    320  // since the last call to ApplyChanges, i.e. whether ApplyChanges needs to
    321  // be called.
    322  // This is used to optimize away a CATransaction commit if no layers have
    323  // changed.
    324  NativeLayerCAUpdateType HasUpdate(bool aIsVideo);
    325 
    326  // Lazily initialized by first call to ApplyChanges. mWrappingLayer is the
    327  // layer that applies the intersection of mDisplayRect and mClipRect (if
    328  // set), and mContentCALayer is the layer that hosts the IOSurface. We do
    329  // not share clip layers between consecutive NativeLayerCA objects with the
    330  // same clip rect.
    331  CALayer* mWrappingCALayer = nullptr;      // strong
    332  CALayer* mRoundedClipCALayer = nullptr;   // strong
    333  CALayer* mContentCALayer = nullptr;       // strong
    334  CALayer* mOpaquenessTintLayer = nullptr;  // strong
    335 
    336 #ifdef NIGHTLY_BUILD
    337  bool mLogNextVideoSurface = false;
    338 #endif
    339 
    340  bool mWrappingCALayerHasExtent : 1;
    341 
    342  // These are all initialized to true by the constructor.
    343  bool mMutatedPosition : 1;
    344  bool mMutatedTransform : 1;
    345  bool mMutatedDisplayRect : 1;
    346  bool mMutatedClipRect : 1;
    347  bool mMutatedRoundedClipRect : 1;
    348  bool mMutatedBackingScale : 1;
    349  bool mMutatedSize : 1;
    350  bool mMutatedSurfaceIsFlipped : 1;
    351  bool mMutatedFrontSurface : 1;
    352  bool mMutatedSamplingFilter : 1;
    353  bool mMutatedSpecializeVideo : 1;
    354  bool mMutatedIsDRM : 1;
    355  // Don't forget to update the constructor when you add a field here.
    356 };
    357 
    358 // NativeLayerCA wraps a CALayer and lets you draw to it. It ensures that only
    359 // fully-drawn frames make their way to the screen, by maintaining a swap chain
    360 // of IOSurfaces.
    361 // All calls to mutating methods are buffered, and don't take effect on the
    362 // underlying CoreAnimation layers until ApplyChanges() is called.
    363 // The two most important methods are NextSurface and NotifySurfaceReady:
    364 // NextSurface takes an available surface from the swap chain or creates a new
    365 // surface if necessary. This surface can then be drawn to. Once drawing is
    366 // finished, NotifySurfaceReady marks the surface as ready. This surface is
    367 // committed to the layer during the next call to ApplyChanges().
    368 // The swap chain keeps track of invalid areas within the surfaces.
    369 class NativeLayerCA : public NativeLayer {
    370 public:
    371  virtual NativeLayerCA* AsNativeLayerCA() override { return this; }
    372 
    373  // Overridden methods
    374  gfx::IntSize GetSize() override;
    375  void SetPosition(const gfx::IntPoint& aPosition) override;
    376  gfx::IntPoint GetPosition() override;
    377  void SetTransform(const gfx::Matrix4x4& aTransform) override;
    378  gfx::Matrix4x4 GetTransform() override;
    379  gfx::IntRect GetRect() override;
    380  void SetSamplingFilter(gfx::SamplingFilter aSamplingFilter) override;
    381  RefPtr<gfx::DrawTarget> NextSurfaceAsDrawTarget(
    382      const gfx::IntRect& aDisplayRect, const gfx::IntRegion& aUpdateRegion,
    383      gfx::BackendType aBackendType) override;
    384  Maybe<GLuint> NextSurfaceAsFramebuffer(const gfx::IntRect& aDisplayRect,
    385                                         const gfx::IntRegion& aUpdateRegion,
    386                                         bool aNeedsDepth) override;
    387  void NotifySurfaceReady() override;
    388  void DiscardBackbuffers() override;
    389  bool IsOpaque() override;
    390  void SetClipRect(const Maybe<gfx::IntRect>& aClipRect) override;
    391  Maybe<gfx::IntRect> ClipRect() override;
    392  void SetRoundedClipRect(const Maybe<gfx::RoundedRect>& aClip) override;
    393  Maybe<gfx::RoundedRect> RoundedClipRect() override;
    394  gfx::IntRect CurrentSurfaceDisplayRect() override;
    395  void SetDisplayRect(const gfx::IntRect& aDisplayRect);
    396  void SetSurfaceIsFlipped(bool aIsFlipped) override;
    397  bool SurfaceIsFlipped() override;
    398 
    399  // Used to force a specific IOSurfaceRef to be used.
    400  void SetSurfaceToPresent(CFTypeRefPtr<IOSurfaceRef> aSurfaceRef,
    401                           gfx::IntSize& aSize, bool aIsDRM, bool aIsHDR);
    402 
    403  void DumpLayer(std::ostream& aOutputStream);
    404 
    405  void AttachExternalImage(wr::RenderTextureHost* aExternalImage) override;
    406  GpuFence* GetGpuFence() override;
    407 
    408  void SetRootWindowIsFullscreen(bool aFullscreen);
    409 
    410 protected:
    411  friend class NativeLayerRootCA;
    412  friend struct NativeLayerCARepresentation;
    413  using UpdateType = NativeLayerCAUpdateType;
    414  using WhichRepresentation = NativeLayerRootCA::WhichRepresentation;
    415  using Representation = NativeLayerCARepresentation;
    416 
    417  NativeLayerCA(const gfx::IntSize& aSize, bool aIsOpaque,
    418                SurfacePoolHandleCA* aSurfacePoolHandle);
    419  explicit NativeLayerCA(bool aIsOpaque);
    420  explicit NativeLayerCA(gfx::DeviceColor aColor);
    421  // This constructor is used for surfaces being directly supplied
    422  // to the layer.
    423  explicit NativeLayerCA(const gfx::IntSize& aSize, bool aIsOpaque);
    424 
    425  ~NativeLayerCA() override;
    426 
    427  // To be called by NativeLayerRootCA:
    428  CALayer* UnderlyingCALayer(WhichRepresentation aRepresentation);
    429 
    430  NativeLayerCAUpdateType HasUpdate(WhichRepresentation aRepresentation);
    431 
    432  // Apply pending updates to the underlaying CALayer. Sets *aMustRebuild to
    433  // true if the update requires changing which set of CALayers should be in the
    434  // parent.
    435  bool ApplyChanges(WhichRepresentation aRepresentation, UpdateType aUpdate,
    436                    bool* aMustRebuild);
    437 
    438  void SetBackingScale(float aBackingScale);
    439 
    440  // Invalidate aUpdateRegion and make sure that mInProgressSurface retains any
    441  // valid content from the previous surface outside of aUpdateRegion, so that
    442  // only aUpdateRegion needs to be drawn. If content needs to be copied,
    443  // aCopyFn is called to do the copying.
    444  // aCopyFn: Fn(CFTypeRefPtr<IOSurfaceRef> aValidSourceIOSurface,
    445  //             const gfx::IntRegion& aCopyRegion) -> void
    446  template <typename F>
    447  void HandlePartialUpdate(const MutexAutoLock& aProofOfLock,
    448                           const gfx::IntRect& aDisplayRect,
    449                           const gfx::IntRegion& aUpdateRegion, F&& aCopyFn);
    450 
    451  bool IsVideo(const MutexAutoLock& aProofOfLock);
    452  bool ShouldSpecializeVideo(const MutexAutoLock& aProofOfLock);
    453 
    454  // This function returns a CGRect if a clip should be applied to the layer.
    455  // If set, the CGRect has the scaled position of the clip relative to the
    456  // surface origin and the scaled size of the clip rect.
    457  static Maybe<CGRect> CalculateClipGeometry(
    458      const gfx::IntSize& aSize, const gfx::IntPoint& aPosition,
    459      const gfx::Matrix4x4& aTransform, const gfx::IntRect& aDisplayRect,
    460      const Maybe<gfx::IntRect>& aClipRect, float aBackingScale);
    461 
    462  Representation& GetRepresentation(WhichRepresentation aRepresentation);
    463  template <typename F>
    464  void ForAllRepresentations(F aFn);
    465 
    466  // Controls access to all fields of this class.
    467  Mutex mMutex MOZ_UNANNOTATED;
    468 
    469  // The IOSurface to use for this layer. Optional.
    470  // If not present, we get use a surface from mSurfaceHandler or mTextureHost
    471  // instead. We mark the surface as "in use" as long as it is in
    472  // mSurfaceToPresent, to prevent other processes from recycling it.
    473  CFTypeRefPtr<IOSurfaceRef> mSurfaceToPresent;
    474 
    475  Maybe<NativeLayerMacSurfaceHandler> mSurfaceHandler;
    476 
    477  RefPtr<wr::RenderMacIOSurfaceTextureHost> mTextureHost;
    478  bool mTextureHostIsVideo = false;
    479 
    480  Representation mOnscreenRepresentation;
    481  Representation mOffscreenRepresentation;
    482 
    483  gfx::IntPoint mPosition;
    484  gfx::Matrix4x4 mTransform;
    485  gfx::IntRect mDisplayRect;
    486  gfx::IntSize mSize;
    487  Maybe<gfx::IntRect> mClipRect;
    488  Maybe<gfx::RoundedRect> mRoundedClipRect;
    489  Maybe<gfx::DeviceColor> mColor;
    490  gfx::SamplingFilter mSamplingFilter = gfx::SamplingFilter::POINT;
    491  float mBackingScale = 1.0f;
    492  bool mSurfaceIsFlipped = false;
    493  const bool mIsOpaque = false;
    494  bool mRootWindowIsFullscreen = false;
    495  bool mSpecializeVideo = false;
    496  bool mIsDRM = false;
    497  bool mIsHDR = false;
    498 
    499 #ifdef NIGHTLY_BUILD
    500  // Track the consistency of our caller's API usage. Layers that are drawn
    501  // should only ever be called with NotifySurfaceReady. Layers that are
    502  // external should only ever be called with AttachExternalImage.
    503  bool mHasEverAttachExternalImage = false;
    504  bool mHasEverNotifySurfaceReady = false;
    505 #endif
    506 };
    507 
    508 }  // namespace layers
    509 }  // namespace mozilla
    510 
    511 #endif  // mozilla_layers_NativeLayerCA_h