// Copyright 2021 The Chromium 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 "media/fuchsia/common/sysmem_client.h"

#include <lib/sys/cpp/component_context.h>
#include <zircon/rights.h>

#include <algorithm>

#include "base/bind.h"
#include "base/fuchsia/fuchsia_logging.h"
#include "base/fuchsia/process_context.h"
#include "base/process/process_handle.h"
#include "media/fuchsia/common/vmo_buffer.h"

namespace media {

SysmemCollectionClient::SysmemCollectionClient(
    fuchsia::sysmem::Allocator* allocator,
    fuchsia::sysmem::BufferCollectionTokenPtr collection_token)
    : allocator_(allocator), collection_token_(std::move(collection_token)) {
  DCHECK(allocator_);
  DCHECK(collection_token_);
}

SysmemCollectionClient::~SysmemCollectionClient() {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  if (collection_)
    collection_->Close();
}

void SysmemCollectionClient::Initialize(
    fuchsia::sysmem::BufferCollectionConstraints constraints,
    base::StringPiece name,
    uint32_t name_priority) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);

  writable_ = (constraints.usage.cpu & fuchsia::sysmem::cpuUsageWrite) ==
              fuchsia::sysmem::cpuUsageWrite;

  allocator_->BindSharedCollection(std::move(collection_token_),
                                   collection_.NewRequest());

  collection_.set_error_handler(
      fit::bind_member(this, &SysmemCollectionClient::OnError));
  collection_->SetName(name_priority, std::string(name));

  // If Sync() is not required then constraints can be set immediately.
  if (sync_completion_closures_.empty()) {
    collection_->SetConstraints(/*have_constraints=*/true,
                                std::move(constraints));
    return;
  }

  sync_completion_closures_.push_back(
      base::BindOnce(&fuchsia::sysmem::BufferCollection::SetConstraints,
                     base::Unretained(collection_.get()),
                     /*have_constraints=*/true, std::move(constraints)));
  collection_->Sync(
      fit::bind_member(this, &SysmemCollectionClient::OnSyncComplete));
}

void SysmemCollectionClient::CreateSharedToken(
    GetSharedTokenCB cb,
    base::StringPiece debug_client_name,
    uint64_t debug_client_id) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  DCHECK(collection_token_);

  fuchsia::sysmem::BufferCollectionTokenPtr token;
  collection_token_->Duplicate(ZX_RIGHT_SAME_RIGHTS, token.NewRequest());

  if (!debug_client_name.empty()) {
    token->SetDebugClientInfo(std::string(debug_client_name), debug_client_id);
  }

  sync_completion_closures_.push_back(
      base::BindOnce(std::move(cb), std::move(token)));
}

void SysmemCollectionClient::AcquireBuffers(AcquireBuffersCB cb) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  DCHECK(!collection_token_);

  if (!collection_) {
    std::move(cb).Run({}, {});
    return;
  }

  acquire_buffers_cb_ = std::move(cb);
  collection_->WaitForBuffersAllocated(
      fit::bind_member(this, &SysmemCollectionClient::OnBuffersAllocated));
}

void SysmemCollectionClient::OnSyncComplete() {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);

  std::vector<base::OnceClosure> sync_closures =
      std::move(sync_completion_closures_);
  for (auto& cb : sync_closures) {
    std::move(cb).Run();
  }
}

void SysmemCollectionClient::OnBuffersAllocated(
    zx_status_t status,
    fuchsia::sysmem::BufferCollectionInfo_2 buffer_collection_info) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);

  if (status != ZX_OK) {
    ZX_LOG(ERROR, status) << "Failed to allocate sysmem buffers.";
    OnError(status);
    return;
  }

  if (acquire_buffers_cb_) {
    auto buffers = VmoBuffer::CreateBuffersFromSysmemCollection(
        &buffer_collection_info, writable_);
    std::move(acquire_buffers_cb_)
        .Run(std::move(buffers), buffer_collection_info.settings);
  }
}

void SysmemCollectionClient::OnError(zx_status_t status) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  ZX_DLOG(ERROR, status) << "Connection to BufferCollection was disconnected.";
  collection_.Unbind();
  if (acquire_buffers_cb_)
    std::move(acquire_buffers_cb_).Run({}, {});
}

SysmemAllocatorClient::SysmemAllocatorClient(base::StringPiece client_name) {
  allocator_ = base::ComponentContextForProcess()
                   ->svc()
                   ->Connect<fuchsia::sysmem::Allocator>();

  allocator_->SetDebugClientInfo(std::string(client_name),
                                 base::GetCurrentProcId());

  allocator_.set_error_handler([](zx_status_t status) {
    // Just log a warning. We will handle BufferCollection the failure when
    // trying to create a new BufferCollection.
    ZX_DLOG(WARNING, status)
        << "The fuchsia.sysmem.Allocator channel was disconnected.";
  });
}

SysmemAllocatorClient::~SysmemAllocatorClient() = default;

fuchsia::sysmem::BufferCollectionTokenPtr
SysmemAllocatorClient::CreateNewToken() {
  fuchsia::sysmem::BufferCollectionTokenPtr collection_token;
  allocator_->AllocateSharedCollection(collection_token.NewRequest());
  return collection_token;
}

std::unique_ptr<SysmemCollectionClient>
SysmemAllocatorClient::AllocateNewCollection() {
  return std::make_unique<SysmemCollectionClient>(allocator_.get(),
                                                  CreateNewToken());
}

std::unique_ptr<SysmemCollectionClient>
SysmemAllocatorClient::BindSharedCollection(
    fuchsia::sysmem::BufferCollectionTokenPtr token) {
  return std::make_unique<SysmemCollectionClient>(allocator_.get(),
                                                  std::move(token));
}

}  // namespace media
