// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "components/webxr/mailbox_to_surface_bridge_impl.h"

#include <memory>
#include <string>
#include <utility>

#include "base/functional/bind.h"
#include "base/logging.h"
#include "base/system/sys_info.h"
#include "base/task/single_thread_task_runner.h"
#include "base/trace_event/trace_event.h"
#include "components/viz/common/gpu/context_provider.h"
#include "content/public/browser/android/compositor.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "gpu/GLES2/gl2extchromium.h"
#include "gpu/command_buffer/client/context_support.h"
#include "gpu/command_buffer/client/gles2_interface.h"
#include "gpu/command_buffer/client/shared_image_interface.h"
#include "gpu/command_buffer/common/gpu_memory_buffer_support.h"
#include "gpu/command_buffer/common/mailbox.h"
#include "gpu/command_buffer/common/mailbox_holder.h"
#include "gpu/ipc/client/gpu_channel_host.h"
#include "gpu/ipc/common/gpu_memory_buffer_impl_android_hardware_buffer.h"
#include "gpu/ipc/common/gpu_surface_tracker.h"
#include "services/viz/public/cpp/gpu/context_provider_command_buffer.h"
#include "ui/gfx/color_space.h"
#include "ui/gfx/geometry/transform.h"
#include "ui/gl/android/surface_texture.h"

#define VOID_OFFSET(x) reinterpret_cast<void*>(x)
#define SHADER(Src) #Src

namespace {

/* clang-format off */
const char kQuadCopyVertex[] = SHADER(
    precision mediump float;
    attribute vec4 a_Position;
    attribute vec2 a_TexCoordinate;
    varying highp vec2 v_TexCoordinate;
    uniform mat4 u_UvTransform;
    void main() {
      highp vec4 uv_in = vec4(a_TexCoordinate.x, a_TexCoordinate.y, 0, 1);
      v_TexCoordinate = (u_UvTransform * uv_in).xy;
      gl_Position = a_Position;
    }
);

const char kQuadCopyFragment[] = SHADER(
    precision highp float;
    uniform sampler2D u_Texture;
    varying vec2 v_TexCoordinate;
    void main() {
      gl_FragColor = texture2D(u_Texture, v_TexCoordinate);
    }
);

const float kQuadVertices[] = {
    // x     y    u,   v
    -1.f,  1.f, 0.f, 1.f,
    -1.f, -1.f, 0.f, 0.f,
     1.f, -1.f, 1.f, 0.f,
     1.f,  1.f, 1.f, 1.f};
/* clang-format on */

static constexpr int kQuadVerticesSize = sizeof(kQuadVertices);

GLuint CompileShader(gpu::gles2::GLES2Interface* gl,
                     GLenum shader_type,
                     const GLchar* shader_source) {
  GLuint shader_handle = gl->CreateShader(shader_type);
  if (shader_handle != 0) {
    // Pass in the shader source.
    GLint len = strlen(shader_source);
    gl->ShaderSource(shader_handle, 1, &shader_source, &len);
    // Compile the shader.
    gl->CompileShader(shader_handle);
    // Get the compilation status.
    GLint status = 0;
    gl->GetShaderiv(shader_handle, GL_COMPILE_STATUS, &status);
    if (status == GL_FALSE) {
      GLint info_log_length = 0;
      gl->GetShaderiv(shader_handle, GL_INFO_LOG_LENGTH, &info_log_length);
      auto str_info_log = std::make_unique<GLchar[]>(info_log_length + 1);
      gl->GetShaderInfoLog(shader_handle, info_log_length, nullptr,
                           str_info_log.get());
      DLOG(ERROR) << "Error compiling shader: " << str_info_log.get();
      gl->DeleteShader(shader_handle);
      shader_handle = 0;
    }
  }

  return shader_handle;
}

GLuint CreateAndLinkProgram(gpu::gles2::GLES2Interface* gl,
                            GLuint vertex_shader_handle,
                            GLuint fragment_shader_handle) {
  GLuint program_handle = gl->CreateProgram();

  if (program_handle != 0) {
    // Bind the vertex shader to the program.
    gl->AttachShader(program_handle, vertex_shader_handle);

    // Bind the fragment shader to the program.
    gl->AttachShader(program_handle, fragment_shader_handle);

    // Link the two shaders together into a program.
    gl->LinkProgram(program_handle);

    // Get the link status.
    GLint link_status = 0;
    gl->GetProgramiv(program_handle, GL_LINK_STATUS, &link_status);

    // If the link failed, delete the program.
    if (link_status == GL_FALSE) {
      GLint info_log_length;
      gl->GetProgramiv(program_handle, GL_INFO_LOG_LENGTH, &info_log_length);

      auto str_info_log = std::make_unique<GLchar[]>(info_log_length + 1);
      gl->GetProgramInfoLog(program_handle, info_log_length, nullptr,
                            str_info_log.get());
      DLOG(ERROR) << "Error compiling program: " << str_info_log.get();
      gl->DeleteProgram(program_handle);
      program_handle = 0;
    }
  }

  return program_handle;
}

GLuint ConsumeTexture(gpu::gles2::GLES2Interface* gl,
                      const gpu::MailboxHolder& mailbox) {
  TRACE_EVENT0("gpu", "MailboxToSurfaceBridgeImpl::ConsumeTexture");
  gl->WaitSyncTokenCHROMIUM(mailbox.sync_token.GetConstData());

  return gl->CreateAndTexStorage2DSharedImageCHROMIUM(mailbox.mailbox.name);
}

}  // namespace

namespace webxr {

MailboxToSurfaceBridgeImpl::MailboxToSurfaceBridgeImpl() {
  DVLOG(1) << __FUNCTION__;
}

MailboxToSurfaceBridgeImpl::~MailboxToSurfaceBridgeImpl() {
  if (surface_handle_) {
    // Unregister from the surface tracker to avoid a resource leak.
    gpu::GpuSurfaceTracker* tracker = gpu::GpuSurfaceTracker::Get();
    tracker->RemoveSurface(surface_handle_);
  }
  DestroyContext();
  DVLOG(1) << __FUNCTION__;
}

bool MailboxToSurfaceBridgeImpl::IsConnected() {
  return context_provider_ && gl_ && context_support_;
}

bool MailboxToSurfaceBridgeImpl::IsGpuWorkaroundEnabled(int32_t workaround) {
  DCHECK(IsConnected());

  return context_provider_->GetGpuFeatureInfo().IsWorkaroundEnabled(workaround);
}

void MailboxToSurfaceBridgeImpl::OnContextAvailableOnUiThread(
    scoped_refptr<viz::ContextProvider> provider) {
  DVLOG(1) << __FUNCTION__;
  // Must save a reference to the viz::ContextProvider to keep it alive,
  // otherwise the GL context created from it becomes invalid on its
  // destruction.
  context_provider_ = std::move(provider);

  DCHECK(on_context_bound_);
  gl_thread_task_runner_->PostTask(
      FROM_HERE,
      base::BindOnce(
          &MailboxToSurfaceBridgeImpl::BindContextProviderToCurrentThread,
          base::Unretained(this)));
}

void MailboxToSurfaceBridgeImpl::BindContextProviderToCurrentThread() {
  auto result = context_provider_->BindToCurrentSequence();
  if (result != gpu::ContextResult::kSuccess) {
    DLOG(ERROR) << "Failed to init viz::ContextProvider";
    return;
  }

  gl_ = context_provider_->ContextGL();
  context_support_ = context_provider_->ContextSupport();

  if (!gl_) {
    DLOG(ERROR) << "Did not get a GL context";
    return;
  }
  if (!context_support_) {
    DLOG(ERROR) << "Did not get a ContextSupport";
    return;
  }
  InitializeRenderer();

  DVLOG(1) << __FUNCTION__ << ": Context ready";
  if (on_context_bound_) {
    std::move(on_context_bound_).Run();
  }
}

void MailboxToSurfaceBridgeImpl::CreateSurface(
    gl::SurfaceTexture* surface_texture) {
  gpu::GpuSurfaceTracker* tracker = gpu::GpuSurfaceTracker::Get();
  surface_handle_ =
      tracker->AddSurfaceForNativeWidget(gpu::GpuSurfaceTracker::SurfaceRecord(
          gl::ScopedJavaSurface(surface_texture),
          false /* can_be_used_with_surface_control */));
  // Unregistering happens in the destructor.
}

void MailboxToSurfaceBridgeImpl::CreateAndBindContextProvider(
    base::OnceClosure on_bound_callback) {
  gl_thread_task_runner_ = base::SingleThreadTaskRunner::GetCurrentDefault();
  on_context_bound_ = std::move(on_bound_callback);

  // The callback to run in this thread. It is necessary to keep |surface| alive
  // until the context becomes available. So pass it on to the callback, so that
  // it stays alive, and is destroyed on the same thread once done.
  auto callback =
      base::BindOnce(&MailboxToSurfaceBridgeImpl::OnContextAvailableOnUiThread,
                     weak_ptr_factory_.GetWeakPtr());

  content::GetUIThreadTaskRunner({})->PostTask(
      FROM_HERE, base::BindOnce(
                     [](int surface_handle,
                        content::Compositor::ContextProviderCallback callback) {
                       // Our attributes must be compatible with the shared
                       // offscreen surface used by virtualized contexts,
                       // otherwise mailbox synchronization doesn't work
                       // properly - it assumes a shared underlying GL context.
                       // See GetCompositorContextAttributes in
                       // content/browser/renderer_host/compositor_impl_android.cc
                       // and https://crbug.com/699330.
                       gpu::ContextCreationAttribs attributes;
                       attributes.alpha_size = -1;
                       attributes.red_size = 8;
                       attributes.green_size = 8;
                       attributes.blue_size = 8;
                       attributes.stencil_size = 0;
                       attributes.depth_size = 0;
                       attributes.samples = 0;
                       attributes.sample_buffers = 0;
                       attributes.bind_generates_resource = false;
                       if (base::SysInfo::IsLowEndDevice()) {
                         attributes.alpha_size = 0;
                         attributes.red_size = 5;
                         attributes.green_size = 6;
                         attributes.blue_size = 5;
                       }
                       content::Compositor::CreateContextProvider(
                           surface_handle, attributes,
                           gpu::SharedMemoryLimits::ForMailboxContext(),
                           std::move(callback));
                     },
                     surface_handle_, std::move(callback)));
}

void MailboxToSurfaceBridgeImpl::ResizeSurface(int width, int height) {
  surface_width_ = width;
  surface_height_ = height;

  if (!IsConnected()) {
    // We're not initialized yet, save the requested size for later.
    needs_resize_ = true;
    return;
  }
  DVLOG(1) << __FUNCTION__ << ": resize Surface to " << surface_width_ << "x"
           << surface_height_;
  gfx::ColorSpace color_space = gfx::ColorSpace::CreateSRGB();
  gl_->ResizeCHROMIUM(surface_width_, surface_height_, 1.f,
                      color_space.AsGLColorSpace(), false);
  gl_->Viewport(0, 0, surface_width_, surface_height_);
}

bool MailboxToSurfaceBridgeImpl::CopyMailboxToSurfaceAndSwap(
    const gpu::MailboxHolder& mailbox) {
  return CopyMailboxToSurfaceAndSwap(mailbox, gfx::Transform());
}

bool MailboxToSurfaceBridgeImpl::CopyMailboxToSurfaceAndSwap(
    const gpu::MailboxHolder& mailbox,
    const gfx::Transform& uv_transform) {
  if (!IsConnected()) {
    // We may not have a context yet, i.e. due to surface initialization
    // being incomplete. This is not an error, but we obviously can't draw
    // yet. This affects the non-shared-buffer path on Android N (or
    // if UseSharedBuffer was forced to false due to GPU bug workarounds),
    // and may result in a couple of discarded images while waiting for
    // initialization which is generally harmless.
    return false;
  }

  TRACE_EVENT0("gpu", __FUNCTION__);

  if (needs_resize_) {
    ResizeSurface(surface_width_, surface_height_);
    needs_resize_ = false;
  }

  DCHECK(mailbox.mailbox.IsSharedImage());

  // While it's not an error to use a zero-sized Surface, it's not going to
  // produce any visible output. Show a debug mode warning in that case to avoid
  // another annoying debugging session.
  DLOG_IF(WARNING, !surface_width_ || !surface_height_)
      << "Surface is zero-sized. Missing call to ResizeSurface?";

  GLuint sourceTexture = ConsumeTexture(gl_, mailbox);
  gl_->BeginSharedImageAccessDirectCHROMIUM(
      sourceTexture, GL_SHARED_IMAGE_ACCESS_MODE_READ_CHROMIUM);
  DrawQuad(sourceTexture, uv_transform);
  gl_->EndSharedImageAccessDirectCHROMIUM(sourceTexture);
  gl_->DeleteTextures(1, &sourceTexture);
  gl_->SwapBuffers(swap_id_++);
  return true;
}

void MailboxToSurfaceBridgeImpl::GenSyncToken(gpu::SyncToken* out_sync_token) {
  TRACE_EVENT0("gpu", __FUNCTION__);
  DCHECK(IsConnected());
  gl_->GenSyncTokenCHROMIUM(out_sync_token->GetData());
}

void MailboxToSurfaceBridgeImpl::WaitSyncToken(
    const gpu::SyncToken& sync_token) {
  TRACE_EVENT0("gpu", __FUNCTION__);
  DCHECK(IsConnected());
  gl_->WaitSyncTokenCHROMIUM(sync_token.GetConstData());
}

void MailboxToSurfaceBridgeImpl::WaitForClientGpuFence(
    gfx::GpuFence& gpu_fence) {
  TRACE_EVENT0("gpu", __FUNCTION__);
  DCHECK(IsConnected());
  GLuint id = gl_->CreateClientGpuFenceCHROMIUM(gpu_fence.AsClientGpuFence());
  gl_->WaitGpuFenceCHROMIUM(id);
  gl_->DestroyGpuFenceCHROMIUM(id);
}

void MailboxToSurfaceBridgeImpl::CreateGpuFence(
    const gpu::SyncToken& sync_token,
    base::OnceCallback<void(std::unique_ptr<gfx::GpuFence>)> callback) {
  TRACE_EVENT0("gpu", __FUNCTION__);
  DCHECK(IsConnected());
  gl_->WaitSyncTokenCHROMIUM(sync_token.GetConstData());
  GLuint id = gl_->CreateGpuFenceCHROMIUM();
  context_support_->GetGpuFence(id, std::move(callback));
  gl_->DestroyGpuFenceCHROMIUM(id);
}

gpu::MailboxHolder MailboxToSurfaceBridgeImpl::CreateSharedImage(
    gpu::GpuMemoryBufferImplAndroidHardwareBuffer* buffer,
    const gfx::ColorSpace& color_space,
    uint32_t usage) {
  TRACE_EVENT0("gpu", __FUNCTION__);
  DCHECK(IsConnected());

  auto* sii = context_provider_->SharedImageInterface();
  DCHECK(sii);

  gpu::MailboxHolder mailbox_holder;
  mailbox_holder.mailbox = sii->CreateSharedImage(
      buffer, nullptr, color_space, kTopLeft_GrSurfaceOrigin,
      kPremul_SkAlphaType, usage, "WebXrMailboxToSurfaceBridge");
  mailbox_holder.sync_token = sii->GenVerifiedSyncToken();
  DCHECK(!gpu::NativeBufferNeedsPlatformSpecificTextureTarget(
      buffer->GetFormat()));
  mailbox_holder.texture_target = GL_TEXTURE_2D;
  return mailbox_holder;
}

void MailboxToSurfaceBridgeImpl::DestroySharedImage(
    const gpu::MailboxHolder& mailbox_holder) {
  TRACE_EVENT0("gpu", __FUNCTION__);
  DCHECK(IsConnected());

  auto* sii = context_provider_->SharedImageInterface();
  DCHECK(sii);
  sii->DestroySharedImage(mailbox_holder.sync_token, mailbox_holder.mailbox);
}

void MailboxToSurfaceBridgeImpl::DestroyContext() {
  gl_ = nullptr;
  context_provider_ = nullptr;
}

void MailboxToSurfaceBridgeImpl::InitializeRenderer() {
  GLuint vertex_shader_handle =
      CompileShader(gl_, GL_VERTEX_SHADER, kQuadCopyVertex);
  if (!vertex_shader_handle) {
    DestroyContext();
    return;
  }

  GLuint fragment_shader_handle =
      CompileShader(gl_, GL_FRAGMENT_SHADER, kQuadCopyFragment);
  if (!fragment_shader_handle) {
    DestroyContext();
    return;
  }

  GLuint program_handle =
      CreateAndLinkProgram(gl_, vertex_shader_handle, fragment_shader_handle);
  if (!program_handle) {
    DestroyContext();
    return;
  }

  // Once the program is linked the shader objects are no longer needed
  gl_->DeleteShader(vertex_shader_handle);
  gl_->DeleteShader(fragment_shader_handle);

  GLuint position_handle = gl_->GetAttribLocation(program_handle, "a_Position");
  GLuint texCoord_handle =
      gl_->GetAttribLocation(program_handle, "a_TexCoordinate");
  GLuint texUniform_handle =
      gl_->GetUniformLocation(program_handle, "u_Texture");
  uniform_uv_transform_handle_ =
      gl_->GetUniformLocation(program_handle, "u_UvTransform");

  GLuint vertexBuffer = 0;
  gl_->GenBuffers(1, &vertexBuffer);
  gl_->BindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
  gl_->BufferData(GL_ARRAY_BUFFER, kQuadVerticesSize, kQuadVertices,
                  GL_STATIC_DRAW);

  // Set state once only, we assume that nobody else modifies GL state in a way
  // that would interfere with our operations.
  gl_->Disable(GL_CULL_FACE);
  gl_->DepthMask(GL_FALSE);
  gl_->Disable(GL_DEPTH_TEST);
  gl_->Disable(GL_SCISSOR_TEST);
  gl_->Disable(GL_BLEND);
  gl_->Disable(GL_POLYGON_OFFSET_FILL);

  // Not using gl_->Viewport, we assume that it defaults to the whole
  // surface and gets updated by ResizeSurface externally as
  // appropriate.

  gl_->UseProgram(program_handle);

  // Bind vertex attributes
  gl_->BindBuffer(GL_ARRAY_BUFFER, vertexBuffer);

  gl_->EnableVertexAttribArray(position_handle);
  gl_->EnableVertexAttribArray(texCoord_handle);

  static constexpr size_t VERTEX_STRIDE = sizeof(float) * 4;
  static constexpr size_t POSITION_ELEMENTS = 2;
  static constexpr size_t TEXCOORD_ELEMENTS = 2;
  static constexpr size_t POSITION_OFFSET = 0;
  static constexpr size_t TEXCOORD_OFFSET = sizeof(float) * 2;

  gl_->VertexAttribPointer(position_handle, POSITION_ELEMENTS, GL_FLOAT, false,
                           VERTEX_STRIDE, VOID_OFFSET(POSITION_OFFSET));
  gl_->VertexAttribPointer(texCoord_handle, TEXCOORD_ELEMENTS, GL_FLOAT, false,
                           VERTEX_STRIDE, VOID_OFFSET(TEXCOORD_OFFSET));

  gl_->ActiveTexture(GL_TEXTURE0);
  gl_->Uniform1i(texUniform_handle, 0);
}

void MailboxToSurfaceBridgeImpl::DrawQuad(unsigned int texture_handle,
                                          const gfx::Transform& uv_transform) {
  DCHECK(IsConnected());

  // We're redrawing over the entire viewport, but it's generally more
  // efficient on mobile tiling GPUs to clear anyway as a hint that
  // we're done with the old content.
  gl_->Clear(GL_COLOR_BUFFER_BIT);

  float uv_transform_floats[16];
  uv_transform.GetColMajorF(uv_transform_floats);
  gl_->UniformMatrix4fv(uniform_uv_transform_handle_, 1, GL_FALSE,
                        &uv_transform_floats[0]);

  // Configure texture. This is a 1:1 pixel copy since the surface
  // size is resized to match the source canvas, so we can use
  // GL_NEAREST.
  gl_->BindTexture(GL_TEXTURE_2D, texture_handle);
  gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  if (uv_transform.IsIdentity()) {
    gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  } else {
    gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  }
  gl_->DrawArrays(GL_TRIANGLE_FAN, 0, 4);
}

std::unique_ptr<device::MailboxToSurfaceBridge>
MailboxToSurfaceBridgeFactoryImpl::Create() const {
  return std::make_unique<MailboxToSurfaceBridgeImpl>();
}

}  // namespace webxr
