Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  NativeLayerCA.h

  Sprache: C
 

/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */


#ifndef mozilla_layers_NativeLayerCA_h
#define mozilla_layers_NativeLayerCA_h

#include <IOSurface/IOSurfaceRef.h>

#include <ostream>

#include "mozilla/Mutex.h"
#include "mozilla/TimeStamp.h"

#include "mozilla/gfx/MacIOSurface.h"
#include "mozilla/layers/NativeLayer.h"
#include "mozilla/layers/NativeLayerMacSurfaceHandler.h"
#include "mozilla/webrender/RenderMacIOSurfaceTextureHost.h"
#include "CFTypeRefPtr.h"
#include "nsRegion.h"
#include "nsISupportsImpl.h"

#ifdef __OBJC__
@class CALayer;
@class CARenderer;
#else
typedef void CALayer;
typedef void CARenderer;
#endif

namespace mozilla {

namespace gl {
class GLContextCGL;
class MozFramebuffer;
}  // namespace gl
namespace wr {
class RenderMacIOSurfaceTextureHost;
}  // namespace wr

namespace layers {

class NativeLayerRootSnapshotterCA;

enum class VideoLowPowerType {
  // These must be kept synchronized with the telemetry histogram enums.
  NotVideo,           // Never emitted as telemetry. No video is visible.
  LowPower,           // As best we can tell, we are in the "detached",
                      // low-power compositing mode. We don't use "Success"
                      // because of name collision with telemetry generation.
  FailMultipleVideo,  // There is more than one video visible.
  FailWindowed,       // The window is not fullscreen.
  FailOverlaid,       // Something is on top of the video (likely captions).
  FailBacking,        // The layer behind the video is not full-coverage black.
  FailMacOSVersion,   // macOS version does not meet requirements.
  FailPref,           // Pref is not set.
  FailSurface,        // Surface is not eligible.
  FailEnqueue,        // Enqueueing the video didn't work.
};

// The type of update needed to apply the pending changes to a NativeLayerCA
// representation.
//
// Order is important. Each enum must fully encompass the work implied by the
// previous enums.
enum class NativeLayerCAUpdateType {
  None,
  OnlyVideo,
  All,
};

class SnapshotterCADelegate {
 public:
  virtual ~SnapshotterCADelegate();

  virtual float BackingScale() const { return 1.0f; }
  virtual bool DoCustomReadbackForReftestsIfDesired(
      const gfx::IntSize& aReadbackSize, gfx::SurfaceFormat aReadbackFormat,
      const Range<uint8_t>& aReadbackBuffer) {
    return false;
  }
  virtual void UpdateSnapshotterLayers(CALayer* aRootCALayer) = 0;
  virtual void OnSnapshotterDestroyed(
      NativeLayerRootSnapshotterCA* aSnapshotter) {}
};

// NativeLayerRootCA is the CoreAnimation implementation of the NativeLayerRoot
// interface. A NativeLayerRootCA is created by the widget around an existing
// CALayer with a call to CreateForCALayer - this CALayer is the root of the
// "onscreen" representation of this layer tree.
// All methods can be called from any thread, there is internal locking.
// All effects from mutating methods are buffered locally and don't modify the
// underlying CoreAnimation layers until CommitToScreen() is called. This
// ensures that the modifications happen on the right thread.
//
// More specifically: During normal operation, screen updates are driven from a
// compositing thread. On this thread, the layers are created / destroyed, their
// contents are painted, and the result is committed to the screen. However,
// there are some scenarios that need to involve the main thread, most notably
// window resizing: During a window resize, we still need the drawing part to
// happen on the compositing thread, but the modifications to the underlying
// CALayers need to happen on the main thread, once compositing is done.
//
// NativeLayerRootCA + NativeLayerCA create and maintain *two* CALayer tree
// representations: An "onscreen" representation and an "offscreen"
// representation. These representations are updated via calls to
// CommitToScreen() and CommitOffscreen(), respectively. The reason for having
// two representations is the following: Our implementation of the snapshotter
// API uses CARenderer, which lets us render the composited result of our layer
// tree into a GPU buffer. But CARenderer requires "ownership" of the rendered
// CALayers in the sense that it associates the CALayers with a local
// "CAContext". A CALayer can only be associated with one CAContext at any time.
// If we wanted te render our *onscreen* CALayers with CARenderer, we would need
// to remove them from the window, reparent them to the CARenderer, render them,
// and then put them back into the window. This would lead to a visible flashing
// effect. To solve this problem, we build two CALayer representations, so that
// one representation can stay inside the window and the other can stay attached
// to the CARenderer.
class NativeLayerRootCA final : public NativeLayerRoot {
 public:
  static already_AddRefed<NativeLayerRootCA> CreateForCALayer(CALayer* aLayer);

  virtual NativeLayerRootCA* AsNativeLayerRootCA() override { return this; }

  // Can be called on any thread at any point. Returns whether comitting was
  // successful. Will return false if called off the main thread while
  // off-main-thread commits are suspended.
  bool CommitToScreen() override;

  void CommitOffscreen(CALayer* aRootCALayer);
  void OnNativeLayerRootSnapshotterDestroyed(
      NativeLayerRootSnapshotterCA* aNativeLayerRootSnapshotter);

  // Enters a mode during which CommitToScreen(), when called on a non-main
  // thread, will not apply any updates to the CALayer tree.
  void SuspendOffMainThreadCommits();

  // Exits the mode entered by SuspendOffMainThreadCommits().
  // Returns true if the last CommitToScreen() was canceled due to suspension,
  // indicating that another call to CommitToScreen() is needed.
  bool UnsuspendOffMainThreadCommits();

  bool AreOffMainThreadCommitsSuspended();

  void DumpLayerTreeToFile(const char* aPath,
                           const MutexAutoLock& aProofOfLock);

  enum class WhichRepresentation : uint8_t { ONSCREEN, OFFSCREEN };

  // Overridden methods
  already_AddRefed<NativeLayer> CreateLayer(
      const gfx::IntSize& aSize, bool aIsOpaque,
      SurfacePoolHandle* aSurfacePoolHandle) override;
  void AppendLayer(NativeLayer* aLayer) override;
  void RemoveLayer(NativeLayer* aLayer) override;
  void SetLayers(const nsTArray<RefPtr<NativeLayer>>& aLayers) override;
  UniquePtr<NativeLayerRootSnapshotter> CreateSnapshotter() override;

  void SetBackingScale(float aBackingScale);
  float BackingScale();

  already_AddRefed<NativeLayer> CreateLayerForExternalTexture(
      bool aIsOpaque) override;
  already_AddRefed<NativeLayer> CreateLayerForColor(
      gfx::DeviceColor aColor) override;

  // A macOS-specific layer creation method, which uses no
  // SurfacePoolHandle, because it will be handed surfaces directly.
  already_AddRefed<NativeLayerCA> CreateLayerForSurfacePresentation(
      const gfx::IntSize& aSize, bool aIsOpaque);

  void SetWindowIsFullscreen(bool aFullscreen);

  VideoLowPowerType CheckVideoLowPower(const MutexAutoLock& aProofOfLock);

 protected:
  explicit NativeLayerRootCA(CALayer* aLayer);
  ~NativeLayerRootCA() override;

  // Do a commit of the pending changes to the CALayers. This is used for both
  // onscreen commits (modifying the CALayers attached to the NSView), and for
  // "offscreen" commits.
  // "Offscreen" commits are updating a separate copy of the CALayer tree for
  // use with CARenderer by the snapshotter.
  void CommitRepresentation(WhichRepresentation aRepresentation,
                            CALayer* aRootCALayer,
                            const nsTArray<RefPtr<NativeLayerCA>>& aSublayers,
                            bool aMutatedLayerStructure,
                            bool aWindowIsFullscreen);

  void SetMutatedLayerStructure();

  using UpdateType = NativeLayerCAUpdateType;
  UpdateType GetMaxUpdateRequired(
      WhichRepresentation aRepresentation,
      const nsTArray<RefPtr<NativeLayerCA>>& aSublayers,
      bool aMutatedLayerStructure) const;

  // An implementation of SnapshotterCADelegate, backed by a NativeLayerRootCA.
  struct SnapshotterDelegate final : public SnapshotterCADelegate {
    explicit SnapshotterDelegate(NativeLayerRootCA* aLayerRoot);
    virtual ~SnapshotterDelegate() override;
    virtual float BackingScale() const override {
      return mLayerRoot->BackingScale();
    }
    virtual void UpdateSnapshotterLayers(CALayer* aRootCALayer) override {
      mLayerRoot->CommitOffscreen(aRootCALayer);
    }
    virtual void OnSnapshotterDestroyed(
        NativeLayerRootSnapshotterCA* aSnapshotter) override {
      mLayerRoot->OnNativeLayerRootSnapshotterDestroyed(aSnapshotter);
    }
    RefPtr<NativeLayerRootCA> mLayerRoot;
  };

  Mutex mMutex MOZ_UNANNOTATED;              // protects all other fields
  CALayer* mOnscreenRootCALayer = nullptr;   // strong
  CALayer* mOffscreenRootCALayer = nullptr;  // strong
  NativeLayerRootSnapshotterCA* mWeakSnapshotter = nullptr;
  nsTArray<RefPtr<NativeLayerCA>> mSublayers;  // in z-order
  float mBackingScale = 1.0f;
  bool mMutated = false;

  // While mOffMainThreadCommitsSuspended is true, no commits
  // should happen on a non-main thread, because they might race with
  // main-thread driven updates such as window shape changes, and cause
  // glitches.
  bool mOffMainThreadCommitsSuspended = false;

  // Set to true if CommitToScreen() was aborted because of commit suspension.
  // Set to false when CommitToScreen() completes successfully. When true,
  // indicates that CommitToScreen() needs to be called at the next available
  // opportunity.
  bool mCommitPending = false;

  // Updated by the layer's view's window to match the fullscreen state
  // of that window.
  bool mWindowIsFullscreen = false;

  // Whether mSublayers has changed since the last onscreen / offscreen commit.
  bool mMutatedOnscreenLayerStructure = false;
  bool mMutatedOffscreenLayerStructure = false;

  // How many times have we committed since the last time we emitted
  // telemetry?
  unsigned int mTelemetryCommitCount = 0;
};

class RenderSourceNLRS;

#ifdef XP_MACOSX
class NativeLayerRootSnapshotterCA final : public NativeLayerRootSnapshotter {
 public:
  static UniquePtr<NativeLayerRootSnapshotterCA> Create(
      UniquePtr<SnapshotterCADelegate>&& aDelegate);
  virtual ~NativeLayerRootSnapshotterCA();

  bool ReadbackPixels(const gfx::IntSize& aReadbackSize,
                      gfx::SurfaceFormat aReadbackFormat,
                      const Range<uint8_t>& aReadbackBuffer) override;
  already_AddRefed<profiler_screenshots::RenderSource> GetWindowContents(
      const gfx::IntSize& aWindowSize) override;
  already_AddRefed<profiler_screenshots::DownscaleTarget> CreateDownscaleTarget(
      const gfx::IntSize& aSize) override;
  already_AddRefed<profiler_screenshots::AsyncReadbackBuffer>
  CreateAsyncReadbackBuffer(const gfx::IntSize& aSize) override;

 protected:
  NativeLayerRootSnapshotterCA(UniquePtr<SnapshotterCADelegate>&& aDelegate,
                               RefPtr<gl::GLContext>&& aGL);
  void UpdateSnapshot(const gfx::IntSize& aSize);

  UniquePtr<SnapshotterCADelegate> mDelegate;
  RefPtr<gl::GLContext> mGL;

  // Can be null. Created and updated in UpdateSnapshot.
  RefPtr<RenderSourceNLRS> mSnapshot;
  CARenderer* mRenderer = nullptr;  // strong
};
#endif

// Wraps one CALayer representation of NativeLayerCA.
struct NativeLayerCARepresentation {
  using UpdateType = NativeLayerCAUpdateType;

  NativeLayerCARepresentation();
  ~NativeLayerCARepresentation();

  // Returns null if the layer is currently completely clipped out.
  CALayer* UnderlyingCALayer() {
    return mWrappingCALayerHasExtent ? mWrappingCALayer : nullptr;
  }

  bool EnqueueSurface(IOSurfaceRef aSurfaceRef);

  // Applies buffered changes to the native CALayers. The contract with the
  // caller is as follows: If any of these values have changed since the last
  // call to ApplyChanges, mMutated[Field] needs to have been set to true
  // before the call. If aUpdate is not All, then a partial update will be
  // applied. In such a case, ApplyChanges may not make any changes that
  // require a CATransacation, because no transaction will be created. In a
  // a partial update, the return value will indicate if all the needed
  // changes were able to be applied under these restrictions. A false return
  // value indicates an All update is necessary.
  bool ApplyChanges(NativeLayerCAUpdateType aUpdate, const gfx::IntSize& aSize,
                    bool aIsOpaque, const gfx::IntPoint& aPosition,
                    const gfx::Matrix4x4& aTransform,
                    const gfx::IntRect& aDisplayRect,
                    const Maybe<gfx::IntRect>& aClipRect,
                    const Maybe<gfx::RoundedRect>& aRoundedClip,
                    float aBackingScale, bool aSurfaceIsFlipped,
                    gfx::SamplingFilter aSamplingFilter, bool aSpecializeVideo,
                    const CFTypeRefPtr<IOSurfaceRef>& aFrontSurface,
                    const Maybe<gfx::DeviceColor>& aColor, bool aIsDRM,
                    bool aIsVideo);

  // Return whether any aspects of this layer representation have been mutated
  // since the last call to ApplyChanges, i.e. whether ApplyChanges needs to
  // be called.
  // This is used to optimize away a CATransaction commit if no layers have
  // changed.
  NativeLayerCAUpdateType HasUpdate(bool aIsVideo);

  // Lazily initialized by first call to ApplyChanges. mWrappingLayer is the
  // layer that applies the intersection of mDisplayRect and mClipRect (if
  // set), and mContentCALayer is the layer that hosts the IOSurface. We do
  // not share clip layers between consecutive NativeLayerCA objects with the
  // same clip rect.
  CALayer* mWrappingCALayer = nullptr;      // strong
  CALayer* mRoundedClipCALayer = nullptr;   // strong
  CALayer* mContentCALayer = nullptr;       // strong
  CALayer* mOpaquenessTintLayer = nullptr;  // strong

#ifdef NIGHTLY_BUILD
  bool mLogNextVideoSurface = false;
#endif

  bool mWrappingCALayerHasExtent : 1;

  // These are all initialized to true by the constructor.
  bool mMutatedPosition : 1;
  bool mMutatedTransform : 1;
  bool mMutatedDisplayRect : 1;
  bool mMutatedClipRect : 1;
  bool mMutatedRoundedClipRect : 1;
  bool mMutatedBackingScale : 1;
  bool mMutatedSize : 1;
  bool mMutatedSurfaceIsFlipped : 1;
  bool mMutatedFrontSurface : 1;
  bool mMutatedSamplingFilter : 1;
  bool mMutatedSpecializeVideo : 1;
  bool mMutatedIsDRM : 1;
  // Don't forget to update the constructor when you add a field here.
};

// NativeLayerCA wraps a CALayer and lets you draw to it. It ensures that only
// fully-drawn frames make their way to the screen, by maintaining a swap chain
// of IOSurfaces.
// All calls to mutating methods are buffered, and don't take effect on the
// underlying CoreAnimation layers until ApplyChanges() is called.
// The two most important methods are NextSurface and NotifySurfaceReady:
// NextSurface takes an available surface from the swap chain or creates a new
// surface if necessary. This surface can then be drawn to. Once drawing is
// finished, NotifySurfaceReady marks the surface as ready. This surface is
// committed to the layer during the next call to ApplyChanges().
// The swap chain keeps track of invalid areas within the surfaces.
class NativeLayerCA : public NativeLayer {
 public:
  virtual NativeLayerCA* AsNativeLayerCA() override { return this; }

  // Overridden methods
  gfx::IntSize GetSize() override;
  void SetPosition(const gfx::IntPoint& aPosition) override;
  gfx::IntPoint GetPosition() override;
  void SetTransform(const gfx::Matrix4x4& aTransform) override;
  gfx::Matrix4x4 GetTransform() override;
  gfx::IntRect GetRect() override;
  void SetSamplingFilter(gfx::SamplingFilter aSamplingFilter) override;
  RefPtr<gfx::DrawTarget> NextSurfaceAsDrawTarget(
      const gfx::IntRect& aDisplayRect, const gfx::IntRegion& aUpdateRegion,
      gfx::BackendType aBackendType) override;
  Maybe<GLuint> NextSurfaceAsFramebuffer(const gfx::IntRect& aDisplayRect,
                                         const gfx::IntRegion& aUpdateRegion,
                                         bool aNeedsDepth) override;
  void NotifySurfaceReady() override;
  void DiscardBackbuffers() override;
  bool IsOpaque() override;
  void SetClipRect(const Maybe<gfx::IntRect>& aClipRect) override;
  Maybe<gfx::IntRect> ClipRect() override;
  void SetRoundedClipRect(const Maybe<gfx::RoundedRect>& aClip) override;
  Maybe<gfx::RoundedRect> RoundedClipRect() override;
  gfx::IntRect CurrentSurfaceDisplayRect() override;
  void SetDisplayRect(const gfx::IntRect& aDisplayRect);
  void SetSurfaceIsFlipped(bool aIsFlipped) override;
  bool SurfaceIsFlipped() override;

  // Used to force a specific IOSurfaceRef to be used.
  void SetSurfaceToPresent(CFTypeRefPtr<IOSurfaceRef> aSurfaceRef,
                           gfx::IntSize& aSize, bool aIsDRM, bool aIsHDR);

  void DumpLayer(std::ostream& aOutputStream);

  void AttachExternalImage(wr::RenderTextureHost* aExternalImage) override;
  GpuFence* GetGpuFence() override;

  void SetRootWindowIsFullscreen(bool aFullscreen);

 protected:
  friend class NativeLayerRootCA;
  friend struct NativeLayerCARepresentation;
  using UpdateType = NativeLayerCAUpdateType;
  using WhichRepresentation = NativeLayerRootCA::WhichRepresentation;
  using Representation = NativeLayerCARepresentation;

  NativeLayerCA(const gfx::IntSize& aSize, bool aIsOpaque,
                SurfacePoolHandleCA* aSurfacePoolHandle);
  explicit NativeLayerCA(bool aIsOpaque);
  explicit NativeLayerCA(gfx::DeviceColor aColor);
  // This constructor is used for surfaces being directly supplied
  // to the layer.
  explicit NativeLayerCA(const gfx::IntSize& aSize, bool aIsOpaque);

  ~NativeLayerCA() override;

  // To be called by NativeLayerRootCA:
  CALayer* UnderlyingCALayer(WhichRepresentation aRepresentation);

  NativeLayerCAUpdateType HasUpdate(WhichRepresentation aRepresentation);

  // Apply pending updates to the underlaying CALayer. Sets *aMustRebuild to
  // true if the update requires changing which set of CALayers should be in the
  // parent.
  bool ApplyChanges(WhichRepresentation aRepresentation, UpdateType aUpdate,
                    bool* aMustRebuild);

  void SetBackingScale(float aBackingScale);

  // Invalidate aUpdateRegion and make sure that mInProgressSurface retains any
  // valid content from the previous surface outside of aUpdateRegion, so that
  // only aUpdateRegion needs to be drawn. If content needs to be copied,
  // aCopyFn is called to do the copying.
  // aCopyFn: Fn(CFTypeRefPtr<IOSurfaceRef> aValidSourceIOSurface,
  //             const gfx::IntRegion& aCopyRegion) -> void
  template <typename F>
  void HandlePartialUpdate(const MutexAutoLock& aProofOfLock,
                           const gfx::IntRect& aDisplayRect,
                           const gfx::IntRegion& aUpdateRegion, F&& aCopyFn);

  bool IsVideo(const MutexAutoLock& aProofOfLock);
  bool ShouldSpecializeVideo(const MutexAutoLock& aProofOfLock);

  // This function returns a CGRect if a clip should be applied to the layer.
  // If set, the CGRect has the scaled position of the clip relative to the
  // surface origin and the scaled size of the clip rect.
  static Maybe<CGRect> CalculateClipGeometry(
      const gfx::IntSize& aSize, const gfx::IntPoint& aPosition,
      const gfx::Matrix4x4& aTransform, const gfx::IntRect& aDisplayRect,
      const Maybe<gfx::IntRect>& aClipRect, float aBackingScale);

  Representation& GetRepresentation(WhichRepresentation aRepresentation);
  template <typename F>
  void ForAllRepresentations(F aFn);

  // Controls access to all fields of this class.
  Mutex mMutex MOZ_UNANNOTATED;

  // The IOSurface to use for this layer. Optional.
  // If not present, we get use a surface from mSurfaceHandler or mTextureHost
  // instead. We mark the surface as "in use" as long as it is in
  // mSurfaceToPresent, to prevent other processes from recycling it.
  CFTypeRefPtr<IOSurfaceRef> mSurfaceToPresent;

  Maybe<NativeLayerMacSurfaceHandler> mSurfaceHandler;

  RefPtr<wr::RenderMacIOSurfaceTextureHost> mTextureHost;
  bool mTextureHostIsVideo = false;

  Representation mOnscreenRepresentation;
  Representation mOffscreenRepresentation;

  gfx::IntPoint mPosition;
  gfx::Matrix4x4 mTransform;
  gfx::IntRect mDisplayRect;
  gfx::IntSize mSize;
  Maybe<gfx::IntRect> mClipRect;
  Maybe<gfx::RoundedRect> mRoundedClipRect;
  Maybe<gfx::DeviceColor> mColor;
  gfx::SamplingFilter mSamplingFilter = gfx::SamplingFilter::POINT;
  float mBackingScale = 1.0f;
  bool mSurfaceIsFlipped = false;
  const bool mIsOpaque = false;
  bool mRootWindowIsFullscreen = false;
  bool mSpecializeVideo = false;
  bool mIsDRM = false;
  bool mIsHDR = false;

#ifdef NIGHTLY_BUILD
  // Track the consistency of our caller's API usage. Layers that are drawn
  // should only ever be called with NotifySurfaceReady. Layers that are
  // external should only ever be called with AttachExternalImage.
  bool mHasEverAttachExternalImage = false;
  bool mHasEverNotifySurfaceReady = false;
#endif
};

}  // namespace layers
}  // namespace mozilla

#endif  // mozilla_layers_NativeLayerCA_h

Messung V0.5 in Prozent
C=86 H=97 G=91

¤ Dauer der Verarbeitung: 0.12 Sekunden  (vorverarbeitet am  2026-08-25) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Open Source Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Statistik
#Sources=277311
#Domains=752002