// Copyright 2017 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 "components/viz/host/host_gpu_memory_buffer_manager.h"

#include <utility>

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/run_loop.h"
#include "base/threading/thread.h"
#include "build/build_config.h"
#include "gpu/ipc/common/gpu_memory_buffer_support.h"
#include "gpu/ipc/host/gpu_memory_buffer_support.h"
#include "services/viz/privileged/interfaces/gl/gpu_service.mojom.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gfx/client_native_pixmap_factory.h"

#if defined(USE_OZONE)
#include "ui/ozone/public/ozone_platform.h"
#endif

#if defined(OS_ANDROID)
#include "base/android/android_hardware_buffer_compat.h"
#endif

namespace viz {

namespace {

class TestGpuService : public mojom::GpuService {
 public:
  TestGpuService() = default;
  ~TestGpuService() override = default;

  mojom::GpuService* GetGpuService(base::OnceClosure connection_error_handler) {
    DCHECK(!connection_error_handler_);
    connection_error_handler_ = std::move(connection_error_handler);
    return this;
  }

  void SimulateConnectionError() {
    if (connection_error_handler_)
      std::move(connection_error_handler_).Run();
  }

  int GetAllocationRequestsCount() const { return allocation_requests_.size(); }

  bool IsAllocationRequestAt(size_t index,
                             gfx::GpuMemoryBufferId id,
                             int client_id) const {
    DCHECK_LT(index, allocation_requests_.size());
    const auto& req = allocation_requests_[index];
    return req.id == id && req.client_id == client_id;
  }

  int GetDestructionRequestsCount() const {
    return destruction_requests_.size();
  }

  bool IsDestructionRequestAt(size_t index,
                              gfx::GpuMemoryBufferId id,
                              int client_id) const {
    DCHECK_LT(index, destruction_requests_.size());
    const auto& req = destruction_requests_[index];
    return req.id == id && req.client_id == client_id;
  }

  void SatisfyAllocationRequestAt(size_t index) {
    DCHECK_LT(index, allocation_requests_.size());
    auto& req = allocation_requests_[index];

    gfx::GpuMemoryBufferHandle handle;
    handle.id = req.id;
    handle.type = gfx::SHARED_MEMORY_BUFFER;

    DCHECK(req.callback);
    std::move(req.callback).Run(std::move(handle));
  }

  // mojom::GpuService:
  void EstablishGpuChannel(int32_t client_id,
                           uint64_t client_tracing_id,
                           bool is_gpu_host,
                           bool cache_shaders_on_disk,
                           EstablishGpuChannelCallback callback) override {}

  void CloseChannel(int32_t client_id) override {}
#if defined(OS_CHROMEOS)
  void CreateArcVideoDecodeAccelerator(
      arc::mojom::VideoDecodeAcceleratorRequest vda_request) override {}

  void CreateArcVideoEncodeAccelerator(
      arc::mojom::VideoEncodeAcceleratorRequest vea_request) override {}

  void CreateArcVideoProtectedBufferAllocator(
      arc::mojom::VideoProtectedBufferAllocatorRequest pba_request) override {}

  void CreateArcProtectedBufferManager(
      arc::mojom::ProtectedBufferManagerRequest pbm_request) override {}

  void CreateJpegDecodeAccelerator(
      chromeos_camera::mojom::MjpegDecodeAcceleratorRequest jda_request)
      override {}

  void CreateJpegEncodeAccelerator(
      chromeos_camera::mojom::JpegEncodeAcceleratorRequest jea_request)
      override {}
#endif  // defined(OS_CHROMEOS)

  void CreateVideoEncodeAcceleratorProvider(
      media::mojom::VideoEncodeAcceleratorProviderRequest request) override {}

  void CreateGpuMemoryBuffer(gfx::GpuMemoryBufferId id,
                             const gfx::Size& size,
                             gfx::BufferFormat format,
                             gfx::BufferUsage usage,
                             int client_id,
                             gpu::SurfaceHandle surface_handle,
                             CreateGpuMemoryBufferCallback callback) override {
    allocation_requests_.push_back({id, client_id, std::move(callback)});
  }

  void DestroyGpuMemoryBuffer(gfx::GpuMemoryBufferId id,
                              int client_id,
                              const gpu::SyncToken& sync_token) override {
    destruction_requests_.push_back({id, client_id});
  }

  void GetVideoMemoryUsageStats(
      GetVideoMemoryUsageStatsCallback callback) override {}

#if defined(OS_WIN)
  void RequestCompleteGpuInfo(
      RequestCompleteGpuInfoCallback callback) override {}

  void GetGpuSupportedRuntimeVersion(
      GetGpuSupportedRuntimeVersionCallback callback) override {}
#endif

  void RequestHDRStatus(RequestHDRStatusCallback callback) override {}

  void LoadedShader(int32_t client_id,
                    const std::string& key,
                    const std::string& data) override {}

  void WakeUpGpu() override {}

  void GpuSwitched() override {}

  void DestroyAllChannels() override {}

  void OnBackgroundCleanup() override {}

  void OnBackgrounded() override {}

  void OnForegrounded() override {}

#if defined(OS_MACOSX)
  void BeginCATransaction() override {}

  void CommitCATransaction(CommitCATransactionCallback callback) override {}
#endif

  void Crash() override {}

  void Hang() override {}

  void ThrowJavaException() override {}

  void Stop(StopCallback callback) override {}

 private:
  base::OnceClosure connection_error_handler_;

  struct AllocationRequest {
    gfx::GpuMemoryBufferId id;
    int client_id;
    CreateGpuMemoryBufferCallback callback;
  };
  std::vector<AllocationRequest> allocation_requests_;

  struct DestructionRequest {
    const gfx::GpuMemoryBufferId id;
    const int client_id;
  };
  std::vector<DestructionRequest> destruction_requests_;

  DISALLOW_COPY_AND_ASSIGN(TestGpuService);
};

}  // namespace

class HostGpuMemoryBufferManagerTest : public ::testing::Test {
 public:
  HostGpuMemoryBufferManagerTest() = default;
  ~HostGpuMemoryBufferManagerTest() override = default;

  void SetUp() override {
    gpu_service_ = std::make_unique<TestGpuService>();
    auto gpu_service_provider = base::BindRepeating(
        &TestGpuService::GetGpuService, base::Unretained(gpu_service_.get()));
    auto gpu_memory_buffer_support =
        std::make_unique<gpu::GpuMemoryBufferSupport>();
    gpu_memory_buffer_manager_ = std::make_unique<HostGpuMemoryBufferManager>(
        std::move(gpu_service_provider), 1,
        std::move(gpu_memory_buffer_support),
        base::ThreadTaskRunnerHandle::Get());
  }

  // Not all platforms support native configurations (currently only Windows,
  // Mac and some Ozone platforms). Abort the test in those platforms.
  bool IsNativePixmapConfigSupported() {
    bool native_pixmap_supported = false;
#if defined(USE_OZONE)
    native_pixmap_supported =
        ui::OzonePlatform::GetInstance()->IsNativePixmapConfigSupported(
            gfx::BufferFormat::RGBA_8888, gfx::BufferUsage::GPU_READ);
#elif defined(OS_ANDROID)
    native_pixmap_supported =
        base::AndroidHardwareBufferCompat::IsSupportAvailable();
#elif defined(OS_MACOSX) || defined(OS_WIN)
    native_pixmap_supported = true;
#endif

    if (native_pixmap_supported)
      return true;

    gpu::GpuMemoryBufferSupport support;
    DCHECK(gpu::GetNativeGpuMemoryBufferConfigurations(&support).empty());
    return false;
  }

  std::unique_ptr<gfx::GpuMemoryBuffer> AllocateGpuMemoryBufferSync() {
    base::Thread diff_thread("TestThread");
    diff_thread.Start();
    std::unique_ptr<gfx::GpuMemoryBuffer> buffer;
    base::RunLoop run_loop;
    diff_thread.task_runner()->PostTask(
        FROM_HERE, base::BindOnce(
                       [](HostGpuMemoryBufferManager* manager,
                          std::unique_ptr<gfx::GpuMemoryBuffer>* out_buffer,
                          base::OnceClosure callback) {
                         *out_buffer = manager->CreateGpuMemoryBuffer(
                             gfx::Size(64, 64), gfx::BufferFormat::YVU_420,
                             gfx::BufferUsage::GPU_READ,
                             gpu::kNullSurfaceHandle);
                         std::move(callback).Run();
                       },
                       gpu_memory_buffer_manager_.get(), &buffer,
                       run_loop.QuitClosure()));
    run_loop.Run();
    return buffer;
  }

  TestGpuService* gpu_service() const { return gpu_service_.get(); }

  HostGpuMemoryBufferManager* gpu_memory_buffer_manager() const {
    return gpu_memory_buffer_manager_.get();
  }

 private:
  std::unique_ptr<TestGpuService> gpu_service_;
  std::unique_ptr<HostGpuMemoryBufferManager> gpu_memory_buffer_manager_;

  DISALLOW_COPY_AND_ASSIGN(HostGpuMemoryBufferManagerTest);
};

// Tests that allocation requests from a client that goes away before allocation
// completes are cleaned up correctly.
TEST_F(HostGpuMemoryBufferManagerTest, AllocationRequestsForDestroyedClient) {
  if (!IsNativePixmapConfigSupported())
    return;

  // Note: HostGpuMemoryBufferManager normally operates on a mojom::GpuService
  // implementation over mojo. Which means the communication from HGMBManager to
  // GpuService is asynchronous. In this test, the mojom::GpuService is not
  // bound to a mojo pipe, which means those calls are all synchronous.

  const auto buffer_id = static_cast<gfx::GpuMemoryBufferId>(1);
  const int client_id = 2;
  const gfx::Size size(10, 20);
  const gfx::BufferFormat format = gfx::BufferFormat::RGBA_8888;
  const gfx::BufferUsage usage = gfx::BufferUsage::GPU_READ;
  gpu_memory_buffer_manager()->AllocateGpuMemoryBuffer(
      buffer_id, client_id, size, format, usage, gpu::kNullSurfaceHandle,
      base::DoNothing());
  EXPECT_EQ(1, gpu_service()->GetAllocationRequestsCount());
  EXPECT_TRUE(gpu_service()->IsAllocationRequestAt(0, buffer_id, client_id));
  EXPECT_EQ(0, gpu_service()->GetDestructionRequestsCount());

  // Destroy the client. Since no memory has been allocated yet, there will be
  // no request for freeing memory.
  gpu_memory_buffer_manager()->DestroyAllGpuMemoryBufferForClient(client_id);
  EXPECT_EQ(1, gpu_service()->GetAllocationRequestsCount());
  EXPECT_EQ(0, gpu_service()->GetDestructionRequestsCount());

  // When the host receives the allocated memory for the destroyed client, it
  // should request the allocated memory to be freed.
  gpu_service()->SatisfyAllocationRequestAt(0);
  EXPECT_EQ(1, gpu_service()->GetAllocationRequestsCount());
  EXPECT_EQ(1, gpu_service()->GetDestructionRequestsCount());
  EXPECT_TRUE(gpu_service()->IsDestructionRequestAt(0, buffer_id, client_id));
}

TEST_F(HostGpuMemoryBufferManagerTest, RequestsFromUntrustedClientsValidated) {
  const auto buffer_id = static_cast<gfx::GpuMemoryBufferId>(1);
  const int client_id = 2;
  // SCANOUT cannot be used if native gpu memory buffer is not supported.
  struct {
    gfx::BufferUsage usage;
    gfx::BufferFormat format;
    gfx::Size size;
    bool expect_null_handle;
  } configs[] = {
      {gfx::BufferUsage::SCANOUT, gfx::BufferFormat::YVU_420, {10, 20}, true},
      {gfx::BufferUsage::GPU_READ, gfx::BufferFormat::YVU_420, {64, 64}, false},
  };
  for (const auto& config : configs) {
    gfx::GpuMemoryBufferHandle allocated_handle;
    base::RunLoop runloop;
    gpu_memory_buffer_manager()->AllocateGpuMemoryBuffer(
        buffer_id, client_id, config.size, config.format, config.usage,
        gpu::kNullSurfaceHandle,
        base::BindOnce(
            [](gfx::GpuMemoryBufferHandle* allocated_handle,
               base::OnceClosure callback, gfx::GpuMemoryBufferHandle handle) {
              *allocated_handle = std::move(handle);
              std::move(callback).Run();
            },
            &allocated_handle, runloop.QuitClosure()));
    // Since native gpu memory buffers are not supported, the mojom.GpuService
    // should not receive any allocation requests.
    EXPECT_EQ(0, gpu_service()->GetAllocationRequestsCount());
    runloop.Run();
    if (config.expect_null_handle) {
      EXPECT_TRUE(allocated_handle.is_null());
    } else {
      EXPECT_FALSE(allocated_handle.is_null());
      EXPECT_EQ(gfx::GpuMemoryBufferType::SHARED_MEMORY_BUFFER,
                allocated_handle.type);
    }
  }
}

TEST_F(HostGpuMemoryBufferManagerTest, GpuMemoryBufferDestroyed) {
  auto buffer = AllocateGpuMemoryBufferSync();
  EXPECT_TRUE(buffer);
  buffer.reset();
}

TEST_F(HostGpuMemoryBufferManagerTest,
       GpuMemoryBufferDestroyedOnDifferentThread) {
  auto buffer = AllocateGpuMemoryBufferSync();
  EXPECT_TRUE(buffer);
  // Destroy the buffer in a different thread.
  base::Thread diff_thread("DestroyThread");
  ASSERT_TRUE(diff_thread.Start());
  diff_thread.task_runner()->DeleteSoon(FROM_HERE, std::move(buffer));
  diff_thread.Stop();
}

// Tests that if an allocated buffer is received after the gpu service issuing
// it has died, HGMBManager retries the allocation request properly.
TEST_F(HostGpuMemoryBufferManagerTest, AllocationRequestFromDeadGpuService) {
  if (!IsNativePixmapConfigSupported())
    return;

  // Request allocation. No allocation should happen yet.
  gfx::GpuMemoryBufferHandle allocated_handle;
  const auto buffer_id = static_cast<gfx::GpuMemoryBufferId>(1);
  const int client_id = 2;
  const gfx::Size size(10, 20);
  const gfx::BufferFormat format = gfx::BufferFormat::RGBA_8888;
  const gfx::BufferUsage usage = gfx::BufferUsage::GPU_READ;
  gpu_memory_buffer_manager()->AllocateGpuMemoryBuffer(
      buffer_id, client_id, size, format, usage, gpu::kNullSurfaceHandle,
      base::BindOnce(
          [](gfx::GpuMemoryBufferHandle* allocated_handle,
             gfx::GpuMemoryBufferHandle handle) {
            *allocated_handle = std::move(handle);
          },
          &allocated_handle));
  EXPECT_EQ(1, gpu_service()->GetAllocationRequestsCount());
  EXPECT_TRUE(gpu_service()->IsAllocationRequestAt(0, buffer_id, client_id));
  EXPECT_TRUE(allocated_handle.is_null());

  // Simulate a connection error from gpu. HGMBManager should retry allocation
  // request.
  gpu_service()->SimulateConnectionError();
  EXPECT_EQ(2, gpu_service()->GetAllocationRequestsCount());
  EXPECT_TRUE(gpu_service()->IsAllocationRequestAt(1, buffer_id, client_id));
  EXPECT_TRUE(allocated_handle.is_null());

  // Send an allocated buffer corresponding to the first request on the old gpu.
  // This should not result in a buffer handle.
  gpu_service()->SatisfyAllocationRequestAt(0);
  EXPECT_EQ(2, gpu_service()->GetAllocationRequestsCount());
  EXPECT_TRUE(allocated_handle.is_null());

  // Send an allocated buffer corresponding to the retried request on the new
  // gpu. This should result in a buffer handle.
  gpu_service()->SatisfyAllocationRequestAt(1);
  EXPECT_EQ(2, gpu_service()->GetAllocationRequestsCount());
  EXPECT_FALSE(allocated_handle.is_null());
}

}  // namespace viz
