// 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.

#include "allocator.h"

#include <lib/fidl-async-2/fidl_struct.h>
#include <lib/fidl-utils/bind.h>
#include <lib/fidl/internal.h>
#include <lib/zx/channel.h>
#include <lib/zx/event.h>
#include <zircon/fidl.h>

#include <ddk/trace/event.h>

#include "logical_buffer_collection.h"

namespace sysmem_driver {

namespace {

constexpr uint32_t kConcurrencyCap = 64;

}  // namespace

const fuchsia_sysmem_Allocator_ops_t Allocator::kOps = {
    fidl::Binder<Allocator>::BindMember<&Allocator::AllocateNonSharedCollection>,
    fidl::Binder<Allocator>::BindMember<&Allocator::AllocateSharedCollection>,
    fidl::Binder<Allocator>::BindMember<&Allocator::BindSharedCollection>,
    fidl::Binder<Allocator>::BindMember<&Allocator::ValidateBufferCollectionToken>,
    fidl::Binder<Allocator>::BindMember<&Allocator::SetDebugClientInfo>,
};

Allocator::Allocator(Device* parent_device)
    : FidlServer(parent_device->dispatcher(), "sysmem allocator", kConcurrencyCap),
      parent_device_(parent_device) {
  // nothing else to do here
}

Allocator::~Allocator() { LogInfo("~Allocator"); }

zx_status_t Allocator::AllocateNonSharedCollection(zx_handle_t buffer_collection_request_param) {
  TRACE_DURATION("gfx", "Allocator::AllocateNonSharedCollection");
  zx::channel buffer_collection_request(buffer_collection_request_param);

  // The AllocateCollection() message skips past the token stage because the
  // client is also the only participant (probably a temp/test client).  Real
  // clients are encouraged to use AllocateSharedCollection() instead, so that
  // the client can share the LogicalBufferCollection with other participants.
  //
  // Because this is a degenerate way to use sysmem, we implement this method
  // in terms of the non-degenerate way.
  //
  // This code is essentially the same as what a client would do if a client
  // wanted to skip the BufferCollectionToken stage without using
  // AllocateCollection().  Essentially, this code is here just so clients
  // that don't need to share their collection don't have to write this code,
  // and can share this code instead.

  // Create a local token.
  zx::channel token_client;
  zx::channel token_server;
  zx_status_t status = zx::channel::create(0, &token_client, &token_server);
  if (status != ZX_OK) {
    LogError(
        "Allocator::AllocateCollection() zx::channel::create() failed "
        "- status: %d",
        status);
    // ~buffer_collection_request
    //
    // Returning an error here causes the sysmem connection to drop also,
    // which seems like a good idea (more likely to recover overall) given
    // the nature of the error.
    return status;
  }

  // The server end of the local token goes to Create(), and the client end
  // goes to BindSharedCollection().  The BindSharedCollection() will figure
  // out which token we're talking about based on the koid(s), as usual.
  LogicalBufferCollection::Create(std::move(token_server), parent_device_);
  LogicalBufferCollection::BindSharedCollection(parent_device_, std::move(token_client),
                                                std::move(buffer_collection_request),
                                                client_info_ ? &*client_info_ : nullptr);

  // Now the client can SetConstraints() on the BufferCollection, etc.  The
  // client didn't have to hassle with the BufferCollectionToken, which is the
  // sole upside of the client using this message over
  // AllocateSharedCollection().
  return ZX_OK;
}

zx_status_t Allocator::AllocateSharedCollection(zx_handle_t token_request_param) {
  TRACE_DURATION("gfx", "Allocator::AllocateSharedCollection");
  zx::channel token_request(token_request_param);

  // The LogicalBufferCollection is self-owned / owned by all the channels it
  // serves.
  //
  // There's no channel served directly by the LogicalBufferCollection.
  // Instead LogicalBufferCollection owns all the FidlServer instances that
  // each own a channel.
  //
  // Initially there's only a channel to the first BufferCollectionToken.  We
  // go ahead and allocate the LogicalBufferCollection here since the
  // LogicalBufferCollection associates all the BufferCollectionToken and
  // BufferCollection bindings to the same LogicalBufferCollection.
  LogicalBufferCollection::Create(std::move(token_request), parent_device_);
  return ZX_OK;
}

zx_status_t Allocator::BindSharedCollection(zx_handle_t token_param,
                                            zx_handle_t buffer_collection_request_param) {
  TRACE_DURATION("gfx", "Allocator::BindSharedCollection");
  zx::channel token(token_param);
  zx::channel buffer_collection_request(buffer_collection_request_param);

  // The BindSharedCollection() message is about a supposed-to-be-pre-existing
  // logical BufferCollection, but the only association we have to that
  // BufferCollection is the client end of a BufferCollectionToken channel
  // being handed in via token_param.  To find any associated BufferCollection
  // we have to look it up by koid.  The koid table is held by
  // BufferCollection, so delegate over to BufferCollection for this request.
  LogicalBufferCollection::BindSharedCollection(parent_device_, std::move(token),
                                                std::move(buffer_collection_request),
                                                client_info_ ? &*client_info_ : nullptr);
  return ZX_OK;
}

zx_status_t Allocator::ValidateBufferCollectionToken(zx_koid_t token_server_koid, fidl_txn_t* txn) {
  BindingType::Txn::RecognizeTxn(txn);
  zx_status_t status =
      LogicalBufferCollection::ValidateBufferCollectionToken(parent_device_, token_server_koid);
  ZX_DEBUG_ASSERT(status == ZX_OK || status == ZX_ERR_NOT_FOUND);
  return fuchsia_sysmem_AllocatorValidateBufferCollectionToken_reply(txn, status == ZX_OK);
}

zx_status_t Allocator::SetDebugClientInfo(const char* name_data, size_t name_size, uint64_t id) {
  client_info_.emplace();
  client_info_->name = std::string(name_data, name_size);
  client_info_->id = id;
  return ZX_OK;
}

}  // namespace sysmem_driver
