| // Copyright 2019 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef SRC_DEVICES_SYSMEM_DRIVERS_SYSMEM_BUFFER_COLLECTION_TOKEN_H_ |
| #define SRC_DEVICES_SYSMEM_DRIVERS_SYSMEM_BUFFER_COLLECTION_TOKEN_H_ |
| |
| #include <fidl/fuchsia.sysmem/cpp/fidl.h> |
| #include <fidl/fuchsia.sysmem2.internal/cpp/fidl.h> |
| #include <fidl/fuchsia.sysmem2/cpp/fidl.h> |
| |
| #include "lib/zx/channel.h" |
| #include "logging.h" |
| #include "logical_buffer_collection.h" |
| #include "node.h" |
| |
| namespace sysmem_driver { |
| |
| class BufferCollectionToken; |
| |
| class BufferCollectionToken : public Node, public LoggingMixin { |
| public: |
| ~BufferCollectionToken() override; |
| |
| // The returned reference is owned by new_node_properties, which in turn is owned by |
| // logical_buffer_collection->root_. |
| static BufferCollectionToken& EmplaceInTree( |
| fbl::RefPtr<LogicalBufferCollection> logical_buffer_collection, |
| NodeProperties* new_node_properties, const TokenServerEnd& server_end); |
| |
| template <class CompleterSync> |
| void TokenReleaseImpl(ConnectionVersion version, CompleterSync& completer) { |
| // BufferCollectionToken has one additional error case we want to check, so check before calling |
| // Node::CloseImpl(). |
| if (buffer_collection_request_) { |
| FailSync(FROM_HERE, version, completer, ZX_ERR_BAD_STATE, |
| "BufferCollectionToken::Close()/Release() when buffer_collection_request_"); |
| // We're failing async - no need to try to fail sync. |
| return; |
| } |
| ReleaseImpl(version, completer); |
| } |
| |
| void OnServerKoid(); |
| |
| void SetDispensableInternal(); |
| |
| bool is_done(); |
| |
| void SetBufferCollectionRequest(CollectionServerEnd buffer_collection_request); |
| |
| std::optional<CollectionServerEnd> TakeBufferCollectionRequest(); |
| |
| void CloseServerBinding(zx_status_t epitaph) override; |
| |
| // Node interface |
| bool ReadyForAllocation() override; |
| void OnBuffersAllocated(const AllocationResult& allocation_result) override; |
| BufferCollectionToken* buffer_collection_token() override; |
| const BufferCollectionToken* buffer_collection_token() const override; |
| BufferCollection* buffer_collection() override; |
| const BufferCollection* buffer_collection() const override; |
| BufferCollectionTokenGroup* buffer_collection_token_group() override; |
| const BufferCollectionTokenGroup* buffer_collection_token_group() const override; |
| OrphanedNode* orphaned_node() override; |
| const OrphanedNode* orphaned_node() const override; |
| bool is_connected_type() const override; |
| bool is_currently_connected() const override; |
| const char* node_type_string() const override; |
| ConnectionVersion connection_version() const override; |
| |
| void Bind(TokenServerEnd server_end); |
| |
| protected: |
| void BindInternalV1(zx::channel token_request, |
| ErrorHandlerWrapper error_handler_wrapper) override; |
| void BindInternalV2(zx::channel token_request, |
| ErrorHandlerWrapper error_handler_wrapper) override; |
| void BindInternalCombinedV1AndV2(zx::channel server_end, |
| ErrorHandlerWrapper error_handler_wrapper) override; |
| |
| private: |
| friend class FidlServer; |
| |
| // We keep the protocol impl separate to clarify which methods are protocol impl. Sysmem serves |
| // CombinedBufferCollectionToken which is both a V1 and V2 token at the same time. This allows |
| // us to keep the V1 and V2 protocols separate from a client's point of view, while also avoiding |
| // any pointless token version conversions. This happens to make sense for BufferCollectionToken |
| // V1 and V2 since the token is logically the same in all stateful aspects; this approach being |
| // used here is not an implicit proposal / promise to use this same approach for any hypothetical |
| // V3. |
| struct CombinedTokenServer |
| : public fidl::Server<fuchsia_sysmem2_internal::CombinedBufferCollectionToken> { |
| explicit CombinedTokenServer(BufferCollectionToken& parent) : parent_(parent) {} |
| |
| // V1 |
| // |
| // FIDL "compose Node" "interface" (identical among BufferCollection, BufferCollectionToken, |
| // BufferCollectionTokenGroup) |
| void SyncV1(SyncV1Completer::Sync& completer) override; |
| void DeprecatedSyncV1(DeprecatedSyncV1Completer::Sync& completer) override; |
| void CloseV1(CloseV1Completer::Sync& completer) override; |
| void DeprecatedCloseV1(DeprecatedCloseV1Completer::Sync& completer) override; |
| void GetNodeRefV1(GetNodeRefV1Completer::Sync& completer) override; |
| void IsAlternateForV1(IsAlternateForV1Request& request, |
| IsAlternateForV1Completer::Sync& completer) override; |
| void SetNameV1(SetNameV1Request& request, SetNameV1Completer::Sync& completer) override; |
| void DeprecatedSetNameV1(DeprecatedSetNameV1Request& request, |
| DeprecatedSetNameV1Completer::Sync& completer) override; |
| void SetDebugClientInfoV1(SetDebugClientInfoV1Request& request, |
| SetDebugClientInfoV1Completer::Sync& completer) override; |
| void DeprecatedSetDebugClientInfoV1( |
| DeprecatedSetDebugClientInfoV1Request& request, |
| DeprecatedSetDebugClientInfoV1Completer::Sync& completer) override; |
| void SetDebugTimeoutLogDeadlineV1( |
| SetDebugTimeoutLogDeadlineV1Request& request, |
| SetDebugTimeoutLogDeadlineV1Completer::Sync& completer) override; |
| void DeprecatedSetDebugTimeoutLogDeadlineV1( |
| DeprecatedSetDebugTimeoutLogDeadlineV1Request& request, |
| DeprecatedSetDebugTimeoutLogDeadlineV1Completer::Sync& completer) override; |
| void SetVerboseLoggingV1(SetVerboseLoggingV1Completer::Sync& completer) override; |
| // fuchsia.sysmem.BufferCollectionToken interface methods (see also "compose Node" methods |
| // above) |
| void DuplicateSyncV1(DuplicateSyncV1Request& request, |
| DuplicateSyncV1Completer::Sync& completer) override; |
| void DuplicateV1(DuplicateV1Request& request, DuplicateV1Completer::Sync& completer) override; |
| void CreateBufferCollectionTokenGroupV1( |
| CreateBufferCollectionTokenGroupV1Request& request, |
| CreateBufferCollectionTokenGroupV1Completer::Sync& completer) override; |
| void SetDispensableV1(SetDispensableV1Completer::Sync& completer) override; |
| |
| // V2 |
| // |
| // FIDL "compose Node" "interface" (identical among BufferCollection, BufferCollectionToken, |
| // BufferCollectionTokenGroup) |
| void SyncV2(SyncV2Completer::Sync& completer) override; |
| void ReleaseV2(ReleaseV2Completer::Sync& completer) override; |
| void GetNodeRefV2(GetNodeRefV2Completer::Sync& completer) override; |
| void IsAlternateForV2(IsAlternateForV2Request& request, |
| IsAlternateForV2Completer::Sync& completer) override; |
| void GetBufferCollectionIdV2(GetBufferCollectionIdV2Completer::Sync& completer) override; |
| void SetWeakV2(SetWeakV2Completer::Sync& completer) override; |
| void SetWeakOkV2(SetWeakOkV2Request& request, SetWeakOkV2Completer::Sync& completer) override; |
| void SetNameV2(SetNameV2Request& request, SetNameV2Completer::Sync& completer) override; |
| void SetDebugClientInfoV2(SetDebugClientInfoV2Request& request, |
| SetDebugClientInfoV2Completer::Sync& completer) override; |
| void SetDebugTimeoutLogDeadlineV2( |
| SetDebugTimeoutLogDeadlineV2Request& request, |
| SetDebugTimeoutLogDeadlineV2Completer::Sync& completer) override; |
| void SetVerboseLoggingV2(SetVerboseLoggingV2Completer::Sync& completer) override; |
| // fuchsia.sysmem.BufferCollectionToken interface methods (see also "compose Node" methods |
| // above) |
| void DuplicateSyncV2(DuplicateSyncV2Request& request, |
| DuplicateSyncV2Completer::Sync& completer) override; |
| void DuplicateV2(DuplicateV2Request& request, DuplicateV2Completer::Sync& completer) override; |
| void CreateBufferCollectionTokenGroupV2( |
| CreateBufferCollectionTokenGroupV2Request& request, |
| CreateBufferCollectionTokenGroupV2Completer::Sync& completer) override; |
| void SetDispensableV2(SetDispensableV2Completer::Sync& completer) override; |
| |
| void handle_unknown_method( |
| fidl::UnknownMethodMetadata<fuchsia_sysmem2_internal::CombinedBufferCollectionToken> |
| metadata, |
| fidl::UnknownMethodCompleter::Sync& completer) override; |
| |
| BufferCollectionToken& parent_; |
| }; |
| |
| BufferCollectionToken(fbl::RefPtr<LogicalBufferCollection> parent, |
| NodeProperties* new_node_properties, const TokenServerEnd& server_end); |
| |
| void FailAsync(Location location, zx_status_t status, const char* format, ...); |
| |
| template <typename Completer> |
| bool CommonDuplicateStage1(uint32_t rights_attenuation_mask, ConnectionVersion version, |
| Completer& completer, NodeProperties** out_node_properties); |
| |
| template <typename Completer> |
| bool CommonCreateBufferCollectionTokenGroupStage1(ConnectionVersion version, Completer& completer, |
| NodeProperties** out_node_properties); |
| |
| std::optional<CombinedTokenServer> server_; |
| |
| std::optional<zx_status_t> async_failure_result_; |
| |
| std::optional<fidl::ServerBindingRef<fuchsia_sysmem2_internal::CombinedBufferCollectionToken>> |
| server_binding_; |
| ConnectionVersion last_seen_version_ = ConnectionVersion::kNoConnection; |
| |
| // This is set up to once during |
| // LogicalBufferCollection::BindSharedCollection(), and essentially curries |
| // the buffer_collection_request past the processing of any remaining |
| // inbound messages on the BufferCollectionToken before starting to serve |
| // the BufferCollection that the token was exchanged for. This way, inbound |
| // Duplicate() messages in the BufferCollectionToken are seen before any |
| // BufferCollection::SetConstraints() (which might otherwise try to allocate |
| // buffers too soon before all tokens are gone) |
| |
| std::optional<CollectionServerEnd> buffer_collection_request_; |
| |
| inspect::Node inspect_node_; |
| inspect::UintProperty debug_id_property_; |
| inspect::StringProperty debug_name_property_; |
| inspect::ValueList properties_; |
| }; |
| |
| } // namespace sysmem_driver |
| |
| #endif // SRC_DEVICES_SYSMEM_DRIVERS_SYSMEM_BUFFER_COLLECTION_TOKEN_H_ |