| // Copyright 2017 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef COMPONENTS_VIZ_COMMON_SURFACES_LOCAL_SURFACE_ID_H_ |
| #define COMPONENTS_VIZ_COMMON_SURFACES_LOCAL_SURFACE_ID_H_ |
| |
| #include <inttypes.h> |
| |
| #include <compare> |
| #include <iosfwd> |
| #include <limits> |
| #include <string> |
| |
| #include "base/unguessable_token.h" |
| #include "components/viz/common/viz_common_export.h" |
| #include "mojo/public/cpp/bindings/struct_traits.h" |
| |
| namespace perfetto { |
| template <typename MessageType> |
| class TracedProto; |
| namespace protos::pbzero { |
| class LocalSurfaceId; |
| } |
| } // namespace perfetto |
| |
| namespace viz { |
| namespace mojom { |
| class LocalSurfaceIdDataView; |
| } |
| |
| class ParentLocalSurfaceIdAllocator; |
| class ChildLocalSurfaceIdAllocator; |
| |
| constexpr uint32_t kInvalidParentSequenceNumber = 0; |
| constexpr uint32_t kInvalidChildSequenceNumber = 0; |
| constexpr uint32_t kInitialParentSequenceNumber = 1; |
| constexpr uint32_t kInitialChildSequenceNumber = 1; |
| constexpr uint32_t kMaxParentSequenceNumber = |
| std::numeric_limits<uint32_t>::max(); |
| constexpr uint32_t kMaxChildSequenceNumber = |
| std::numeric_limits<uint32_t>::max(); |
| |
| // This struct is the part of SurfaceId that can be modified by the client. |
| // LocalSurfaceId uniquely identifies a surface among the surfaces created by a |
| // particular client. A SurfaceId, which is FrameSinkId+LocalSurfaceId, uniquely |
| // identifies a surface globally across all clients. |
| // |
| // LocalSurfaceId consists of: |
| // |
| // - parent_sequence_number: This part is incremented by the embedder of the |
| // client. |
| // |
| // - child_sequence_number: This part is incremented by the client itself. |
| // |
| // - embed_token: An UnguessableToken generated by the embedder. The purpose of |
| // this value is to make SurfaceIds unguessable, because FrameSinkIds and |
| // LocalSurfaceIds are otherwise predictable and clients might exploit this |
| // fact to embed surfaces they're not allowed to. This value is generated once |
| // by ParentLocalSurfaceIdAllocator and remains constant during the lifetime |
| // of the embedding, even if a new LocalSurfaceId is generated for the |
| // embedded client because of some change in its state (e.g. size, |
| // device scale factor, etc.), or for other reasons. If a client is |
| // re-parented, then the new parent allocates a new LocalSurfaceId, with a new |
| // embed token, and communicates that to the embedded client. |
| // |
| // The embedder uses ParentLocalSurfaceIdAllocator to generate LocalSurfaceIds |
| // for the embedee. If Surface Synchronization is on, the embedee uses |
| // ChildLocalSurfaceIdAllocator to generate LocalSurfaceIds for itself. If |
| // Surface Synchronization is off, the embedee also uses |
| // ParentLocalSurfaceIdAllocator, as the parent doesn't generate LocalSurfaceIds |
| // for the child. |
| class VIZ_COMMON_EXPORT LocalSurfaceId { |
| public: |
| constexpr LocalSurfaceId() |
| : parent_sequence_number_(kInvalidParentSequenceNumber), |
| child_sequence_number_(kInvalidChildSequenceNumber) {} |
| |
| constexpr LocalSurfaceId(const LocalSurfaceId& other) = default; |
| constexpr LocalSurfaceId& operator=(const LocalSurfaceId& other) = default; |
| |
| constexpr LocalSurfaceId(uint32_t parent_sequence_number, |
| const base::UnguessableToken& embed_token) |
| : parent_sequence_number_(parent_sequence_number), |
| child_sequence_number_(kInitialChildSequenceNumber), |
| embed_token_(embed_token) {} |
| |
| constexpr LocalSurfaceId(uint32_t parent_sequence_number, |
| uint32_t child_sequence_number, |
| const base::UnguessableToken& embed_token) |
| : parent_sequence_number_(parent_sequence_number), |
| child_sequence_number_(child_sequence_number), |
| embed_token_(embed_token) {} |
| |
| static constexpr LocalSurfaceId MaxSequenceId() { |
| return LocalSurfaceId(kMaxParentSequenceNumber, kMaxChildSequenceNumber, |
| base::UnguessableToken()); |
| } |
| |
| constexpr bool is_valid() const { |
| return parent_sequence_number_ != kInvalidParentSequenceNumber && |
| child_sequence_number_ != kInvalidChildSequenceNumber && |
| !embed_token_.is_empty(); |
| } |
| |
| constexpr uint32_t parent_sequence_number() const { |
| return parent_sequence_number_; |
| } |
| |
| constexpr uint32_t child_sequence_number() const { |
| return child_sequence_number_; |
| } |
| |
| constexpr const base::UnguessableToken& embed_token() const { |
| return embed_token_; |
| } |
| |
| // The |embed_trace_id| is used as the id for trace events associated with |
| // embedding this LocalSurfaceId. |
| uint64_t embed_trace_id() const { return persistent_hash() << 1; } |
| |
| // The |submission_trace_id| is used as the id for trace events associated |
| // with submission of a CompositorFrame to a surface with this LocalSurfaceId. |
| uint64_t submission_trace_id() const { return (persistent_hash() << 1) | 1; } |
| |
| friend std::strong_ordering operator<=>(const LocalSurfaceId&, |
| const LocalSurfaceId&) = default; |
| |
| // This implementation is fast and appropriate for a hash table lookup. |
| // However the hash differs per process, and is inappropriate for tracing. |
| size_t hash() const; |
| |
| // This implementation is slow and not appropriate for a hash table lookup. |
| // However the hash is consistent across processes and can be used for |
| // tracing. |
| size_t persistent_hash() const; |
| |
| std::string ToString() const; |
| |
| // Returns whether this LocalSurfaceId was generated after |other|. In the |
| // case where both `this` and `other` have advanced separate sequences, then |
| // this will return false. |
| bool IsNewerThan(const LocalSurfaceId& other) const; |
| |
| // Returns whether this LocalSurfaceId was generated after |other|. In the |
| // case where both `this` and `other` have advanced separate sequences, then |
| // this will return false. In the case where `embed_token_` has changed, this |
| // will return true. |
| bool IsNewerThanOrEmbeddingChanged(const LocalSurfaceId& other) const; |
| |
| // Returns whether this LocalSurfaceId was generated after |other| or equal to |
| // it. |
| bool IsSameOrNewerThan(const LocalSurfaceId& other) const; |
| |
| // Returns the smallest valid LocalSurfaceId with the same embed token as this |
| // LocalSurfaceID. |
| LocalSurfaceId ToSmallestId() const; |
| |
| using TraceProto = perfetto::protos::pbzero::LocalSurfaceId; |
| void WriteIntoTrace(perfetto::TracedProto<TraceProto> proto) const; |
| |
| private: |
| friend struct mojo::StructTraits<mojom::LocalSurfaceIdDataView, |
| LocalSurfaceId>; |
| friend class ParentLocalSurfaceIdAllocator; |
| friend class ChildLocalSurfaceIdAllocator; |
| |
| |
| uint32_t parent_sequence_number_; |
| uint32_t child_sequence_number_; |
| base::UnguessableToken embed_token_; |
| }; |
| |
| VIZ_COMMON_EXPORT std::ostream& operator<<( |
| std::ostream& out, |
| const LocalSurfaceId& local_surface_id); |
| |
| } // namespace viz |
| |
| #endif // COMPONENTS_VIZ_COMMON_SURFACES_LOCAL_SURFACE_ID_H_ |