// Copyright 2013 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 "content/renderer/media/renderer_gpu_video_accelerator_factories.h"

#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>

#include "base/bind.h"
#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h"
#include "base/unguessable_token.h"
#include "cc/output/context_provider.h"
#include "content/child/child_thread_impl.h"
#include "content/renderer/render_thread_impl.h"
#include "gpu/command_buffer/client/gles2_interface.h"
#include "gpu/command_buffer/client/gpu_memory_buffer_manager.h"
#include "gpu/ipc/client/gpu_channel_host.h"
#include "media/gpu/gpu_video_accelerator_util.h"
#include "media/gpu/ipc/client/gpu_video_decode_accelerator_host.h"
#include "media/gpu/ipc/client/gpu_video_encode_accelerator_host.h"
#include "media/gpu/ipc/common/media_messages.h"
#include "media/video/video_decode_accelerator.h"
#include "media/video/video_encode_accelerator.h"
#include "services/ui/public/cpp/gpu/context_provider_command_buffer.h"

namespace content {

namespace {

// This enum values match ContextProviderPhase in histograms.xml
enum ContextProviderPhase {
  CONTEXT_PROVIDER_ACQUIRED = 0,
  CONTEXT_PROVIDER_RELEASED = 1,
  CONTEXT_PROVIDER_RELEASED_MAX_VALUE = CONTEXT_PROVIDER_RELEASED,
};

void RecordContextProviderPhaseUmaEnum(const ContextProviderPhase phase) {
  UMA_HISTOGRAM_ENUMERATION("Media.GPU.HasEverLostContext", phase,
                            CONTEXT_PROVIDER_RELEASED_MAX_VALUE + 1);
}

}  // namespace

// static
std::unique_ptr<RendererGpuVideoAcceleratorFactories>
RendererGpuVideoAcceleratorFactories::Create(
    scoped_refptr<gpu::GpuChannelHost> gpu_channel_host,
    const scoped_refptr<base::SingleThreadTaskRunner>& main_thread_task_runner,
    const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
    const scoped_refptr<ui::ContextProviderCommandBuffer>& context_provider,
    bool enable_gpu_memory_buffer_video_frames,
    const cc::BufferToTextureTargetMap& image_texture_targets,
    bool enable_video_accelerator) {
  RecordContextProviderPhaseUmaEnum(
      ContextProviderPhase::CONTEXT_PROVIDER_ACQUIRED);
  return base::WrapUnique(new RendererGpuVideoAcceleratorFactories(
      std::move(gpu_channel_host), main_thread_task_runner, task_runner,
      context_provider, enable_gpu_memory_buffer_video_frames,
      image_texture_targets, enable_video_accelerator));
}

RendererGpuVideoAcceleratorFactories::RendererGpuVideoAcceleratorFactories(
    scoped_refptr<gpu::GpuChannelHost> gpu_channel_host,
    const scoped_refptr<base::SingleThreadTaskRunner>& main_thread_task_runner,
    const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
    const scoped_refptr<ui::ContextProviderCommandBuffer>& context_provider,
    bool enable_gpu_memory_buffer_video_frames,
    const cc::BufferToTextureTargetMap& image_texture_targets,
    bool enable_video_accelerator)
    : main_thread_task_runner_(main_thread_task_runner),
      task_runner_(task_runner),
      gpu_channel_host_(std::move(gpu_channel_host)),
      context_provider_refptr_(context_provider),
      context_provider_(context_provider.get()),
      enable_gpu_memory_buffer_video_frames_(
          enable_gpu_memory_buffer_video_frames),
      image_texture_targets_(image_texture_targets),
      video_accelerator_enabled_(enable_video_accelerator),
      gpu_memory_buffer_manager_(
          RenderThreadImpl::current()->GetGpuMemoryBufferManager()),
      thread_safe_sender_(ChildThreadImpl::current()->thread_safe_sender()) {
  DCHECK(main_thread_task_runner_);
  DCHECK(gpu_channel_host_);
}

RendererGpuVideoAcceleratorFactories::~RendererGpuVideoAcceleratorFactories() {}

bool RendererGpuVideoAcceleratorFactories::CheckContextLost() {
  DCHECK(task_runner_->BelongsToCurrentThread());
  if (context_provider_) {
    bool release_context_provider = false;
    {
      cc::ContextProvider::ScopedContextLock lock(context_provider_);
      if (lock.ContextGL()->GetGraphicsResetStatusKHR() != GL_NO_ERROR) {
        context_provider_ = nullptr;
        release_context_provider = true;
      }
    }
    if (release_context_provider) {
      // Drop the reference on the main thread.
      main_thread_task_runner_->PostTask(
          FROM_HERE,
          base::Bind(
              &RendererGpuVideoAcceleratorFactories::ReleaseContextProvider,
              base::Unretained(this)));
    }
  }
  return !context_provider_;
}

bool RendererGpuVideoAcceleratorFactories::IsGpuVideoAcceleratorEnabled() {
  return video_accelerator_enabled_;
}

base::UnguessableToken RendererGpuVideoAcceleratorFactories::GetChannelToken() {
  DCHECK(task_runner_->BelongsToCurrentThread());
  if (CheckContextLost())
    return base::UnguessableToken();

  if (channel_token_.is_empty()) {
    context_provider_->GetCommandBufferProxy()->channel()->Send(
        new GpuCommandBufferMsg_GetChannelToken(&channel_token_));
  }

  return channel_token_;
}

int32_t RendererGpuVideoAcceleratorFactories::GetCommandBufferRouteId() {
  DCHECK(task_runner_->BelongsToCurrentThread());
  if (CheckContextLost())
    return 0;
  return context_provider_->GetCommandBufferProxy()->route_id();
}

std::unique_ptr<media::VideoDecodeAccelerator>
RendererGpuVideoAcceleratorFactories::CreateVideoDecodeAccelerator() {
  DCHECK(video_accelerator_enabled_);
  DCHECK(task_runner_->BelongsToCurrentThread());
  if (CheckContextLost())
    return nullptr;

  return std::unique_ptr<media::VideoDecodeAccelerator>(
      new media::GpuVideoDecodeAcceleratorHost(
          context_provider_->GetCommandBufferProxy()));
}

std::unique_ptr<media::VideoEncodeAccelerator>
RendererGpuVideoAcceleratorFactories::CreateVideoEncodeAccelerator() {
  DCHECK(video_accelerator_enabled_);
  DCHECK(task_runner_->BelongsToCurrentThread());
  if (CheckContextLost())
    return nullptr;

  return std::unique_ptr<media::VideoEncodeAccelerator>(
      new media::GpuVideoEncodeAcceleratorHost(
          context_provider_->GetCommandBufferProxy()));
}

bool RendererGpuVideoAcceleratorFactories::CreateTextures(
    int32_t count,
    const gfx::Size& size,
    std::vector<uint32_t>* texture_ids,
    std::vector<gpu::Mailbox>* texture_mailboxes,
    uint32_t texture_target) {
  DCHECK(task_runner_->BelongsToCurrentThread());
  DCHECK(texture_target);

  if (CheckContextLost())
    return false;
  cc::ContextProvider::ScopedContextLock lock(context_provider_);
  gpu::gles2::GLES2Interface* gles2 = lock.ContextGL();
  texture_ids->resize(count);
  texture_mailboxes->resize(count);
  gles2->GenTextures(count, &texture_ids->at(0));
  for (int i = 0; i < count; ++i) {
    gles2->ActiveTexture(GL_TEXTURE0);
    uint32_t texture_id = texture_ids->at(i);
    gles2->BindTexture(texture_target, texture_id);
    gles2->TexParameteri(texture_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    gles2->TexParameteri(texture_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    gles2->TexParameteri(texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    gles2->TexParameteri(texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    if (texture_target == GL_TEXTURE_2D) {
      gles2->TexImage2D(texture_target,
                        0,
                        GL_RGBA,
                        size.width(),
                        size.height(),
                        0,
                        GL_RGBA,
                        GL_UNSIGNED_BYTE,
                        NULL);
    }
    gles2->GenMailboxCHROMIUM(texture_mailboxes->at(i).name);
    gles2->ProduceTextureCHROMIUM(texture_target,
                                  texture_mailboxes->at(i).name);
  }

  // We need ShallowFlushCHROMIUM() here to order the command buffer commands
  // with respect to IPC to the GPU process, to guarantee that the decoder in
  // the GPU process can use these textures as soon as it receives IPC
  // notification of them.
  gles2->ShallowFlushCHROMIUM();
  DCHECK_EQ(gles2->GetError(), static_cast<GLenum>(GL_NO_ERROR));
  return true;
}

void RendererGpuVideoAcceleratorFactories::DeleteTexture(uint32_t texture_id) {
  DCHECK(task_runner_->BelongsToCurrentThread());
  if (CheckContextLost())
    return;

  cc::ContextProvider::ScopedContextLock lock(context_provider_);
  gpu::gles2::GLES2Interface* gles2 = lock.ContextGL();
  gles2->DeleteTextures(1, &texture_id);
  DCHECK_EQ(gles2->GetError(), static_cast<GLenum>(GL_NO_ERROR));
}

gpu::SyncToken RendererGpuVideoAcceleratorFactories::CreateSyncToken() {
  cc::ContextProvider::ScopedContextLock lock(context_provider_);
  gpu::gles2::GLES2Interface* gl = lock.ContextGL();
  gpu::SyncToken sync_token;
  const GLuint64 fence_sync = gl->InsertFenceSyncCHROMIUM();
  gl->ShallowFlushCHROMIUM();
  gl->GenSyncTokenCHROMIUM(fence_sync, sync_token.GetData());
  return sync_token;
}

void RendererGpuVideoAcceleratorFactories::WaitSyncToken(
    const gpu::SyncToken& sync_token) {
  DCHECK(task_runner_->BelongsToCurrentThread());
  if (CheckContextLost())
    return;

  cc::ContextProvider::ScopedContextLock lock(context_provider_);
  gpu::gles2::GLES2Interface* gles2 = lock.ContextGL();
  gles2->WaitSyncTokenCHROMIUM(sync_token.GetConstData());

  // Callers expect the WaitSyncToken to affect the next IPCs. Make sure to
  // flush the command buffers to ensure that.
  gles2->ShallowFlushCHROMIUM();
}

std::unique_ptr<gfx::GpuMemoryBuffer>
RendererGpuVideoAcceleratorFactories::CreateGpuMemoryBuffer(
    const gfx::Size& size,
    gfx::BufferFormat format,
    gfx::BufferUsage usage) {
  std::unique_ptr<gfx::GpuMemoryBuffer> buffer =
      gpu_memory_buffer_manager_->CreateGpuMemoryBuffer(
          size, format, usage, gpu::kNullSurfaceHandle);
  return buffer;
}
bool RendererGpuVideoAcceleratorFactories::
    ShouldUseGpuMemoryBuffersForVideoFrames() const {
  return enable_gpu_memory_buffer_video_frames_;
}

unsigned RendererGpuVideoAcceleratorFactories::ImageTextureTarget(
    gfx::BufferFormat format) {
  auto found = image_texture_targets_.find(cc::BufferToTextureTargetKey(
      gfx::BufferUsage::GPU_READ_CPU_READ_WRITE, format));
  DCHECK(found != image_texture_targets_.end());
  return found->second;
}

media::GpuVideoAcceleratorFactories::OutputFormat
RendererGpuVideoAcceleratorFactories::VideoFrameOutputFormat() {
  DCHECK(task_runner_->BelongsToCurrentThread());
  if (CheckContextLost())
    return media::GpuVideoAcceleratorFactories::OutputFormat::UNDEFINED;
  cc::ContextProvider::ScopedContextLock lock(context_provider_);
  auto capabilities = context_provider_->ContextCapabilities();
  if (capabilities.image_ycbcr_420v)
    return media::GpuVideoAcceleratorFactories::OutputFormat::NV12_SINGLE_GMB;
  if (capabilities.image_ycbcr_422)
    return media::GpuVideoAcceleratorFactories::OutputFormat::UYVY;
  if (capabilities.texture_rg)
    return media::GpuVideoAcceleratorFactories::OutputFormat::NV12_DUAL_GMB;
  return media::GpuVideoAcceleratorFactories::OutputFormat::UNDEFINED;
}

namespace {
class ScopedGLContextLockImpl
    : public media::GpuVideoAcceleratorFactories::ScopedGLContextLock {
 public:
  ScopedGLContextLockImpl(cc::ContextProvider* context_provider)
      : lock_(context_provider) {}
  gpu::gles2::GLES2Interface* ContextGL() override { return lock_.ContextGL(); }

 private:
  cc::ContextProvider::ScopedContextLock lock_;
};
}  // namespace

std::unique_ptr<media::GpuVideoAcceleratorFactories::ScopedGLContextLock>
RendererGpuVideoAcceleratorFactories::GetGLContextLock() {
  if (CheckContextLost())
    return nullptr;
  return base::MakeUnique<ScopedGLContextLockImpl>(context_provider_);
}

std::unique_ptr<base::SharedMemory>
RendererGpuVideoAcceleratorFactories::CreateSharedMemory(size_t size) {
  std::unique_ptr<base::SharedMemory> mem(
      ChildThreadImpl::AllocateSharedMemory(size));
  if (mem && !mem->Map(size))
    return nullptr;
  return mem;
}

scoped_refptr<base::SingleThreadTaskRunner>
RendererGpuVideoAcceleratorFactories::GetTaskRunner() {
  return task_runner_;
}

media::VideoDecodeAccelerator::Capabilities
RendererGpuVideoAcceleratorFactories::GetVideoDecodeAcceleratorCapabilities() {
  return media::GpuVideoAcceleratorUtil::ConvertGpuToMediaDecodeCapabilities(
      gpu_channel_host_->gpu_info().video_decode_accelerator_capabilities);
}

media::VideoEncodeAccelerator::SupportedProfiles
RendererGpuVideoAcceleratorFactories::
    GetVideoEncodeAcceleratorSupportedProfiles() {
  return media::GpuVideoAcceleratorUtil::ConvertGpuToMediaEncodeProfiles(
      gpu_channel_host_->gpu_info()
          .video_encode_accelerator_supported_profiles);
}

void RendererGpuVideoAcceleratorFactories::ReleaseContextProvider() {
  DCHECK(main_thread_task_runner_->BelongsToCurrentThread());
  RecordContextProviderPhaseUmaEnum(
      ContextProviderPhase::CONTEXT_PROVIDER_RELEASED);
  context_provider_refptr_ = nullptr;
}

scoped_refptr<ui::ContextProviderCommandBuffer>
RendererGpuVideoAcceleratorFactories::ContextProviderMainThread() {
  DCHECK(main_thread_task_runner_->BelongsToCurrentThread());
  return context_provider_refptr_;
}

}  // namespace content
