// Copyright 2018 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/gpu/ipc/service/picture_buffer_manager.h"

#include <map>
#include <set>
#include <utility>

#include "base/bind.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/synchronization/lock.h"
#include "base/thread_annotations.h"
#include "components/viz/common/resources/resource_format_utils.h"
#include "gpu/command_buffer/common/mailbox_holder.h"

namespace media {

namespace {

// Generates nonnegative picture buffer IDs, which are assumed to be unique.
int32_t NextID(int32_t* counter) {
  int32_t value = *counter;
  *counter = (*counter + 1) & 0x3FFFFFFF;
  return value;
}

class PictureBufferManagerImpl : public PictureBufferManager {
 public:
  explicit PictureBufferManagerImpl(
      ReusePictureBufferCB reuse_picture_buffer_cb)
      : reuse_picture_buffer_cb_(std::move(reuse_picture_buffer_cb)) {
    DVLOG(1) << __func__;
  }
  PictureBufferManagerImpl(const PictureBufferManagerImpl&) = delete;
  PictureBufferManagerImpl& operator=(const PictureBufferManagerImpl&) = delete;

  void Initialize(
      scoped_refptr<base::SingleThreadTaskRunner> gpu_task_runner,
      scoped_refptr<CommandBufferHelper> command_buffer_helper) override {
    DVLOG(1) << __func__;
    DCHECK(!gpu_task_runner_);

    gpu_task_runner_ = std::move(gpu_task_runner);
    command_buffer_helper_ = std::move(command_buffer_helper);
  }

  bool CanReadWithoutStalling() override {
    DVLOG(3) << __func__;

    base::AutoLock lock(picture_buffers_lock_);

    // If at least one picture buffer is not in use, predict that the VDA can
    // use it to output another picture.
    bool has_assigned_picture_buffer = false;
    for (const auto& it : picture_buffers_) {
      if (!it.second.dismissed) {
        // Note: If a picture buffer is waiting for SyncToken release, that
        // release is already in some command buffer (or the wait is invalid).
        // The wait will complete without further interaction from the client.
        if (it.second.output_count == 0)
          return true;
        has_assigned_picture_buffer = true;
      }
    }

    // If there are no assigned picture buffers, predict that the VDA will
    // request some.
    return !has_assigned_picture_buffer;
  }

  std::vector<PictureBuffer> CreatePictureBuffers(
      uint32_t count,
      VideoPixelFormat pixel_format,
      uint32_t planes,
      gfx::Size texture_size,
      uint32_t texture_target,
      VideoDecodeAccelerator::TextureAllocationMode mode) override {
    DVLOG(2) << __func__;
    DCHECK(gpu_task_runner_);
    DCHECK(gpu_task_runner_->BelongsToCurrentThread());
    DCHECK(count);
    DCHECK(planes);
    DCHECK_LE(planes, static_cast<uint32_t>(VideoFrame::kMaxPlanes));

    // TODO(sandersd): Consider requiring that CreatePictureBuffers() is
    // called with the context current.
    if (mode ==
        VideoDecodeAccelerator::TextureAllocationMode::kAllocateGLTextures) {
      if (!command_buffer_helper_->MakeContextCurrent()) {
        DVLOG(1) << "Failed to make context current";
        return std::vector<PictureBuffer>();
      }
    }

    std::vector<PictureBuffer> picture_buffers;
    for (uint32_t i = 0; i < count; i++) {
      PictureBufferData picture_data = {pixel_format, texture_size};
      if (mode ==
          VideoDecodeAccelerator::TextureAllocationMode::kAllocateGLTextures) {
        for (uint32_t j = 0; j < planes; j++) {
          // Use the plane size for texture-backed shared and non-shared images.
          // Adjust the size by the subsampling factor.
          const size_t width =
              VideoFrame::Columns(j, pixel_format, texture_size.width());
          const size_t height =
              VideoFrame::Rows(j, pixel_format, texture_size.height());

          picture_data.texture_sizes.emplace_back(width, height);

          // Create a texture for this plane.
          // When using shared images, the VDA might not require GL textures to
          // exist.
          // TODO(crbug.com/1011555): Do not allocate GL textures when unused.
          GLuint service_id = command_buffer_helper_->CreateTexture(
              texture_target, GL_RGBA, width, height, GL_RGBA,
              GL_UNSIGNED_BYTE);
          DCHECK(service_id);
          picture_data.service_ids.push_back(service_id);

          // The texture is not cleared yet, but it will be before the VDA
          // outputs it. Rather than requiring output to happen on the GPU
          // thread, mark the texture as cleared immediately.
          command_buffer_helper_->SetCleared(service_id);

          // Generate a mailbox while we are still on the GPU thread.
          picture_data.mailbox_holders[j] = gpu::MailboxHolder(
              command_buffer_helper_->CreateMailbox(service_id),
              gpu::SyncToken(), texture_target);
        }
      }

      // Generate a picture buffer ID and record the picture buffer.
      int32_t picture_buffer_id = NextID(&picture_buffer_id_);
      {
        base::AutoLock lock(picture_buffers_lock_);
        DCHECK(!picture_buffers_.count(picture_buffer_id));
        picture_buffers_[picture_buffer_id] = picture_data;
      }

      // Since our textures have no client IDs, we reuse the service IDs as
      // convenient unique identifiers.
      //
      // TODO(sandersd): Refactor the bind image callback to use service IDs so
      // that we can get rid of the client IDs altogether.
      picture_buffers.emplace_back(
          picture_buffer_id, texture_size, picture_data.texture_sizes,
          picture_data.service_ids, picture_data.service_ids, texture_target,
          pixel_format);
    }
    return picture_buffers;
  }

  bool DismissPictureBuffer(int32_t picture_buffer_id) override {
    DVLOG(2) << __func__ << "(" << picture_buffer_id << ")";

    base::AutoLock lock(picture_buffers_lock_);

    const auto& it = picture_buffers_.find(picture_buffer_id);
    if (it == picture_buffers_.end() || it->second.dismissed) {
      DVLOG(1) << "Unknown picture buffer " << picture_buffer_id;
      return false;
    }

    it->second.dismissed = true;

    // If the picture buffer is not in use, it should be destroyed immediately.
    if (!it->second.IsInUse()) {
      gpu_task_runner_->PostTask(
          FROM_HERE,
          base::BindOnce(&PictureBufferManagerImpl::DestroyPictureBuffer, this,
                         picture_buffer_id));
    }

    return true;
  }

  void DismissAllPictureBuffers() override {
    DVLOG(2) << __func__;

    std::vector<int32_t> assigned_picture_buffer_ids;
    {
      base::AutoLock lock(picture_buffers_lock_);

      for (const auto& it : picture_buffers_) {
        if (!it.second.dismissed)
          assigned_picture_buffer_ids.push_back(it.first);
      }
    }

    for (int32_t picture_buffer_id : assigned_picture_buffer_ids)
      DismissPictureBuffer(picture_buffer_id);
  }

  scoped_refptr<VideoFrame> CreateVideoFrame(Picture picture,
                                             base::TimeDelta timestamp,
                                             gfx::Rect visible_rect,
                                             gfx::Size natural_size) override {
    DVLOG(2) << __func__ << "(" << picture.picture_buffer_id() << ")";
    DCHECK(!picture.size_changed());
    DCHECK(!picture.texture_owner());
    DCHECK(!picture.wants_promotion_hint());

    base::AutoLock lock(picture_buffers_lock_);

    int32_t picture_buffer_id = picture.picture_buffer_id();

    // Verify that the picture buffer is available.
    const auto& it = picture_buffers_.find(picture_buffer_id);
    if (it == picture_buffers_.end() || it->second.dismissed) {
      DVLOG(1) << "Unknown picture buffer " << picture_buffer_id;
      return nullptr;
    }

    // Ensure that the picture buffer is large enough.
    PictureBufferData& picture_buffer_data = it->second;
    if (!gfx::Rect(picture_buffer_data.texture_size).Contains(visible_rect)) {
      DLOG(WARNING) << "visible_rect " << visible_rect.ToString()
                    << " exceeds coded_size "
                    << picture_buffer_data.texture_size.ToString();
      visible_rect.Intersect(gfx::Rect(picture_buffer_data.texture_size));
    }

    // Record the output.
    picture_buffer_data.output_count++;

    // If this |picture| has a SharedImage, then keep a reference to the
    // SharedImage in |picture_buffer_data| and update the gpu::MailboxHolder.
    for (int i = 0; i < VideoFrame::kMaxPlanes; i++) {
      auto image = picture.scoped_shared_image(i);
      if (image)
        picture_buffer_data.mailbox_holders[i] = image->GetMailboxHolder();
      picture_buffer_data.scoped_shared_images[i] = std::move(image);
    }

    // Create and return a VideoFrame for the picture buffer.
    scoped_refptr<VideoFrame> frame = VideoFrame::WrapNativeTextures(
        picture_buffer_data.pixel_format, picture_buffer_data.mailbox_holders,
        base::BindOnce(&PictureBufferManagerImpl::OnVideoFrameDestroyed, this,
                       picture_buffer_id),
        picture_buffer_data.texture_size, visible_rect, natural_size,
        timestamp);

    frame->set_color_space(picture.color_space());

    frame->metadata().allow_overlay = picture.allow_overlay();
    frame->metadata().read_lock_fences_enabled =
        picture.read_lock_fences_enabled();

    // TODO(sandersd): Provide an API for VDAs to control this.
    frame->metadata().power_efficient = true;

    return frame;
  }

 private:
  ~PictureBufferManagerImpl() override {
    DVLOG(1) << __func__;
    DCHECK(picture_buffers_.empty() || !command_buffer_helper_->HasStub());
  }

  void OnVideoFrameDestroyed(int32_t picture_buffer_id,
                             const gpu::SyncToken& sync_token) {
    DVLOG(3) << __func__ << "(" << picture_buffer_id << ")";

    base::AutoLock lock(picture_buffers_lock_);

    // Record the picture buffer as waiting for SyncToken release (even if it
    // has been dismissed already).
    const auto& it = picture_buffers_.find(picture_buffer_id);
    DCHECK(it != picture_buffers_.end());
    DCHECK_GT(it->second.output_count, 0);
    it->second.output_count--;
    it->second.waiting_for_synctoken_count++;

    // Wait for the SyncToken release.
    gpu_task_runner_->PostTask(
        FROM_HERE,
        base::BindOnce(
            &CommandBufferHelper::WaitForSyncToken, command_buffer_helper_,
            sync_token,
            base::BindOnce(&PictureBufferManagerImpl::OnSyncTokenReleased, this,
                           picture_buffer_id)));
  }

  void OnSyncTokenReleased(int32_t picture_buffer_id) {
    DVLOG(3) << __func__ << "(" << picture_buffer_id << ")";
    DCHECK(gpu_task_runner_);
    DCHECK(gpu_task_runner_->BelongsToCurrentThread());

    // Remove the pending wait.
    bool is_assigned = false;
    bool is_in_use = true;
    {
      base::AutoLock lock(picture_buffers_lock_);
      const auto& it = picture_buffers_.find(picture_buffer_id);
      DCHECK(it != picture_buffers_.end());

      DCHECK_GT(it->second.waiting_for_synctoken_count, 0);
      it->second.waiting_for_synctoken_count--;

      is_assigned = !it->second.dismissed;
      is_in_use = it->second.IsInUse();
    }

    // If the picture buffer is still assigned, it is ready to be reused.
    // Otherwise it should be destroyed if it is no longer in use. Neither of
    // these operations should be done while holding the lock.
    if (is_assigned) {
      // The callback is called even if the picture buffer is still in use; the
      // client is expected to wait for all copies of a picture buffer to be
      // returned before reusing any textures.
      reuse_picture_buffer_cb_.Run(picture_buffer_id);
    } else if (!is_in_use) {
      DestroyPictureBuffer(picture_buffer_id);
    }
  }

  void DestroyPictureBuffer(int32_t picture_buffer_id) {
    DVLOG(3) << __func__ << "(" << picture_buffer_id << ")";
    DCHECK(gpu_task_runner_);
    DCHECK(gpu_task_runner_->BelongsToCurrentThread());

    std::vector<GLuint> service_ids;
    std::array<scoped_refptr<Picture::ScopedSharedImage>,
               VideoFrame::kMaxPlanes>
        scoped_shared_images;
    {
      base::AutoLock lock(picture_buffers_lock_);
      const auto& it = picture_buffers_.find(picture_buffer_id);
      DCHECK(it != picture_buffers_.end());
      DCHECK(it->second.dismissed);
      DCHECK(!it->second.IsInUse());
      service_ids = std::move(it->second.service_ids);
      scoped_shared_images = std::move(it->second.scoped_shared_images);
      picture_buffers_.erase(it);
    }

    if (service_ids.empty())
      return;

    if (!command_buffer_helper_->MakeContextCurrent())
      return;

    for (GLuint service_id : service_ids)
      command_buffer_helper_->DestroyTexture(service_id);
  }

  ReusePictureBufferCB reuse_picture_buffer_cb_;

  scoped_refptr<base::SingleThreadTaskRunner> gpu_task_runner_;
  scoped_refptr<CommandBufferHelper> command_buffer_helper_;

  int32_t picture_buffer_id_ = 0;

  struct PictureBufferData {
    VideoPixelFormat pixel_format;
    gfx::Size texture_size;
    std::vector<GLuint> service_ids;
    gpu::MailboxHolder mailbox_holders[VideoFrame::kMaxPlanes];
    std::vector<gfx::Size> texture_sizes;
    std::array<scoped_refptr<Picture::ScopedSharedImage>,
               VideoFrame::kMaxPlanes>
        scoped_shared_images;
    bool dismissed = false;

    // The same picture buffer can be output from the VDA multiple times
    // concurrently, so the state is tracked using counts.
    //   |output_count|: Number of VideoFrames this picture buffer is bound to.
    //   |waiting_for_synctoken_count|: Number of returned frames that are
    //       waiting for SyncToken release.
    int output_count = 0;
    int waiting_for_synctoken_count = 0;

    bool IsInUse() const {
      return output_count > 0 || waiting_for_synctoken_count > 0;
    }
  };

  base::Lock picture_buffers_lock_;
  std::map<int32_t, PictureBufferData> picture_buffers_
      GUARDED_BY(picture_buffers_lock_);
};

}  // namespace

// static
scoped_refptr<PictureBufferManager> PictureBufferManager::Create(
    ReusePictureBufferCB reuse_picture_buffer_cb) {
  return base::MakeRefCounted<PictureBufferManagerImpl>(
      std::move(reuse_picture_buffer_cb));
}

}  // namespace media
