blob: cab116e7828f6c690db9b248f9507a6214161139 [file] [log] [blame]
// 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_H_
#define SRC_DEVICES_SYSMEM_DRIVERS_SYSMEM_BUFFER_COLLECTION_H_
#include <fuchsia/sysmem/c/fidl.h>
#include <fuchsia/sysmem/llcpp/fidl.h>
#include <fuchsia/sysmem2/llcpp/fidl.h>
#include <lib/fidl/internal.h>
#include <list>
#include "logging.h"
#include "logical_buffer_collection.h"
#include "node.h"
#include "src/devices/sysmem/drivers/sysmem/device.h"
namespace sysmem_driver {
class BufferCollection : public Node, public fidl::WireInterface<fuchsia_sysmem::BufferCollection> {
public:
// Use EmplaceInTree() instead of Create() (until we switch to llcpp when we can have a new
// Create() that does what EmplaceInTree() currently does). The returned reference is valid while
// this Node is in the tree under root_.
static BufferCollection& EmplaceInTree(
fbl::RefPtr<LogicalBufferCollection> logical_buffer_collection, BufferCollectionToken* token);
~BufferCollection() override;
void SetErrorHandler(fit::function<void(zx_status_t)> error_handler) {
error_handler_ = std::move(error_handler);
}
void Bind(zx::channel channel);
//
// fuchsia.sysmem.BufferCollection interface methods
//
void SetEventSink(
fidl::ClientEnd<fuchsia_sysmem::BufferCollectionEvents> buffer_collection_events_client,
SetEventSinkCompleter::Sync& completer) override;
void Sync(SyncCompleter::Sync& completer) override;
void SetConstraints(bool has_constraints,
fuchsia_sysmem::wire::BufferCollectionConstraints constraints,
SetConstraintsCompleter::Sync& completer) override;
void WaitForBuffersAllocated(WaitForBuffersAllocatedCompleter::Sync& completer) override;
void CheckBuffersAllocated(CheckBuffersAllocatedCompleter::Sync& completer) override;
void CloseSingleBuffer(uint64_t buffer_index,
CloseSingleBufferCompleter::Sync& completer) override;
void AllocateSingleBuffer(uint64_t buffer_index,
AllocateSingleBufferCompleter::Sync& completer) override;
void WaitForSingleBufferAllocated(
uint64_t buffer_index, WaitForSingleBufferAllocatedCompleter::Sync& completer) override;
void CheckSingleBufferAllocated(uint64_t buffer_index,
CheckSingleBufferAllocatedCompleter::Sync& completer) override;
void Close(CloseCompleter::Sync& completer) override;
void SetName(uint32_t priority, fidl::StringView name,
SetNameCompleter::Sync& completer) override;
void SetDebugClientInfo(fidl::StringView name, uint64_t id,
SetDebugClientInfoCompleter::Sync& completer) override;
void SetConstraintsAuxBuffers(
fuchsia_sysmem::wire::BufferCollectionConstraintsAuxBuffers constraints_aux_buffers,
SetConstraintsAuxBuffersCompleter::Sync& completer) override;
void GetAuxBuffers(GetAuxBuffersCompleter::Sync& completer) override;
void AttachToken(uint32_t rights_attenuation_mask,
fidl::ServerEnd<fuchsia_sysmem::BufferCollectionToken> token_request,
AttachTokenCompleter::Sync& completer) override;
void AttachLifetimeTracking(zx::eventpair server_end, uint32_t buffers_remaining,
AttachLifetimeTrackingCompleter::Sync& completer) override;
//
// LogicalBufferCollection uses these:
//
bool is_set_constraints_seen() const { return is_set_constraints_seen_; }
bool has_constraints();
// has_constraints() must be true to call this.
const fuchsia_sysmem2::wire::BufferCollectionConstraints& constraints();
// has_constraints() must be true to call this, and will stay true after calling this.
fuchsia_sysmem2::wire::BufferCollectionConstraints CloneConstraints();
fbl::RefPtr<LogicalBufferCollection> logical_buffer_collection_shared();
bool is_done() const;
bool should_propagate_failure_to_parent_node() const;
// Node interface
bool ReadyForAllocation() override;
void OnBuffersAllocated(const AllocationResult& allocation_result) override;
void Fail(zx_status_t epitaph) override;
BufferCollectionToken* buffer_collection_token() override;
const BufferCollectionToken* buffer_collection_token() const override;
BufferCollection* buffer_collection() override;
const BufferCollection* buffer_collection() const override;
OrphanedNode* orphaned_node() override;
const OrphanedNode* orphaned_node() const override;
bool is_connected() const override;
private:
using V1CBufferCollectionInfo = FidlStruct<fuchsia_sysmem_BufferCollectionInfo_2,
fuchsia_sysmem::wire::BufferCollectionInfo2>;
friend class FidlServer;
explicit BufferCollection(fbl::RefPtr<LogicalBufferCollection> logical_buffer_collection,
const BufferCollectionToken& token);
void CloseChannel(zx_status_t epitaph);
void SetDebugClientInfoInternal(std::string name, uint64_t id);
// The rights attenuation mask driven by usage, so that read-only usage
// doesn't get write, etc.
uint32_t GetUsageBasedRightsAttenuation();
uint32_t GetClientVmoRights();
uint32_t GetClientAuxVmoRights();
void MaybeCompleteWaitForBuffersAllocated();
void MaybeFlushPendingLifetimeTracking();
void FailAsync(Location location, zx_status_t status, const char* format, ...) __PRINTFLIKE(4, 5);
// FailSync must be used instead of FailAsync if the current method has a completer that needs a
// reply.
template <typename Completer>
void FailSync(Location location, Completer& completer, zx_status_t status, const char* format,
...) __PRINTFLIKE(5, 6);
fit::result<fuchsia_sysmem2::wire::BufferCollectionInfo> CloneResultForSendingV2(
const fuchsia_sysmem2::wire::BufferCollectionInfo& buffer_collection_info);
fit::result<fuchsia_sysmem::wire::BufferCollectionInfo2> CloneResultForSendingV1(
const fuchsia_sysmem2::wire::BufferCollectionInfo& buffer_collection_info);
fit::result<fuchsia_sysmem::wire::BufferCollectionInfo2> CloneAuxBuffersResultForSendingV1(
const fuchsia_sysmem2::wire::BufferCollectionInfo& buffer_collection_info);
static const fuchsia_sysmem_BufferCollection_ops_t kOps;
std::optional<zx_status_t> async_failure_result_;
fit::function<void(zx_status_t)> error_handler_;
// Cached from LogicalBufferCollection.
TableSet& table_set_;
// Client end of a BufferCollectionEvents channel, for the local server to
// send events to the remote client. All of the messages in this interface
// are one-way with no response, so sending an event doesn't block the
// server thread.
//
// This may remain non-set if SetEventSink() is never used by a client. A
// client may send SetEventSink() up to once.
//
std::optional<fidl::WireSyncClient<fuchsia_sysmem::BufferCollectionEvents>> events_;
// Temporarily holds fuchsia.sysmem.BufferCollectionConstraintsAuxBuffers until SetConstraints()
// arrives.
std::optional<TableHolder<fuchsia_sysmem::wire::BufferCollectionConstraintsAuxBuffers>>
constraints_aux_buffers_;
// FIDL protocol enforcement.
bool is_set_constraints_seen_ = false;
bool is_set_constraints_aux_buffers_seen_ = false;
std::list<std::pair</*async_id*/ uint64_t, WaitForBuffersAllocatedCompleter::Async>>
pending_wait_for_buffers_allocated_;
bool is_done_ = false;
std::optional<fidl::ServerBindingRef<fuchsia_sysmem::BufferCollection>> server_binding_;
// Becomes set when OnBuffersAllocated() is called, and stays set after that.
std::optional<AllocationResult> logical_allocation_result_;
struct PendingLifetimeTracking {
zx::eventpair server_end;
uint32_t buffers_remaining;
};
std::vector<PendingLifetimeTracking> pending_lifetime_tracking_;
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_H_