// Copyright 2015 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/android/synchronous_compositor_proxy.h"

#include "base/auto_reset.h"
#include "base/command_line.h"
#include "base/memory/shared_memory.h"
#include "content/common/android/sync_compositor_statics.h"
#include "content/common/input/sync_compositor_messages.h"
#include "content/public/common/content_switches.h"
#include "ipc/ipc_message.h"
#include "ipc/ipc_sender.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkImageInfo.h"
#include "third_party/skia/include/core/SkRegion.h"
#include "ui/gfx/skia_util.h"

namespace content {

SynchronousCompositorProxy::SynchronousCompositorProxy(
    ui::SynchronousInputHandlerProxy* input_handler_proxy)
    : input_handler_proxy_(input_handler_proxy),
      binding_(this),
      use_in_process_zero_copy_software_draw_(
          base::CommandLine::ForCurrentProcess()->HasSwitch(
              switches::kSingleProcess)),
      page_scale_factor_(0.f),
      min_page_scale_factor_(0.f),
      max_page_scale_factor_(0.f),
      need_animate_scroll_(false),
      need_invalidate_count_(0u),
      invalidate_needs_draw_(false),
      did_activate_pending_tree_count_(0u) {
  DCHECK(input_handler_proxy_);
}

SynchronousCompositorProxy::~SynchronousCompositorProxy() {
  // The LayerTreeFrameSink is destroyed/removed by the compositor before
  // shutting down everything.
  DCHECK_EQ(layer_tree_frame_sink_, nullptr);
  input_handler_proxy_->SetOnlySynchronouslyAnimateRootFlings(nullptr);
}

void SynchronousCompositorProxy::Init() {
  input_handler_proxy_->SetOnlySynchronouslyAnimateRootFlings(this);
}

void SynchronousCompositorProxy::SetLayerTreeFrameSink(
    SynchronousLayerTreeFrameSink* layer_tree_frame_sink) {
  DCHECK_NE(layer_tree_frame_sink_, layer_tree_frame_sink);
  DCHECK(layer_tree_frame_sink);
  if (layer_tree_frame_sink_) {
    layer_tree_frame_sink_->SetSyncClient(nullptr);
  }
  layer_tree_frame_sink_ = layer_tree_frame_sink;
  layer_tree_frame_sink_->SetSyncClient(this);
  LayerTreeFrameSinkCreated();
  if (begin_frame_paused_)
    layer_tree_frame_sink_->SetBeginFrameSourcePaused(true);
}

void SynchronousCompositorProxy::SetNeedsSynchronousAnimateInput() {
  if (compute_scroll_called_via_ipc_) {
    needs_begin_frame_for_animate_input_ = true;
    SendSetNeedsBeginFramesIfNeeded();
  } else {
    need_animate_scroll_ = true;
    Invalidate(true);
  }
}

void SynchronousCompositorProxy::UpdateRootLayerState(
    const gfx::ScrollOffset& total_scroll_offset,
    const gfx::ScrollOffset& max_scroll_offset,
    const gfx::SizeF& scrollable_size,
    float page_scale_factor,
    float min_page_scale_factor,
    float max_page_scale_factor) {
  if (total_scroll_offset_ != total_scroll_offset ||
      max_scroll_offset_ != max_scroll_offset ||
      scrollable_size_ != scrollable_size ||
      page_scale_factor_ != page_scale_factor ||
      min_page_scale_factor_ != min_page_scale_factor ||
      max_page_scale_factor_ != max_page_scale_factor) {
    total_scroll_offset_ = total_scroll_offset;
    max_scroll_offset_ = max_scroll_offset;
    scrollable_size_ = scrollable_size;
    page_scale_factor_ = page_scale_factor;
    min_page_scale_factor_ = min_page_scale_factor;
    max_page_scale_factor_ = max_page_scale_factor;

    SendAsyncRendererStateIfNeeded();
  }
}

void SynchronousCompositorProxy::Invalidate(bool needs_draw) {
  ++need_invalidate_count_;
  invalidate_needs_draw_ |= needs_draw;
  SendAsyncRendererStateIfNeeded();
}

void SynchronousCompositorProxy::DidActivatePendingTree() {
  ++did_activate_pending_tree_count_;
  SendAsyncRendererStateIfNeeded();
}

void SynchronousCompositorProxy::PopulateCommonParams(
    SyncCompositorCommonRendererParams* params) {
  params->version = ++version_;
  params->total_scroll_offset = total_scroll_offset_;
  params->max_scroll_offset = max_scroll_offset_;
  params->scrollable_size = scrollable_size_;
  params->page_scale_factor = page_scale_factor_;
  params->min_page_scale_factor = min_page_scale_factor_;
  params->max_page_scale_factor = max_page_scale_factor_;
  params->need_invalidate_count = need_invalidate_count_;
  params->invalidate_needs_draw = invalidate_needs_draw_;
  params->did_activate_pending_tree_count = did_activate_pending_tree_count_;
  if (!compute_scroll_called_via_ipc_)
    params->need_animate_scroll = need_animate_scroll_;
}

void SynchronousCompositorProxy::DemandDrawHwAsync(
    const SyncCompositorDemandDrawHwParams& params) {
  DemandDrawHw(
      params,
      base::BindOnce(&SynchronousCompositorProxy::SendDemandDrawHwAsyncReply,
                     base::Unretained(this)));
}

void SynchronousCompositorProxy::DemandDrawHw(
    const SyncCompositorDemandDrawHwParams& params,
    DemandDrawHwCallback callback) {
  invalidate_needs_draw_ = false;
  hardware_draw_reply_ = std::move(callback);

  if (layer_tree_frame_sink_) {
    layer_tree_frame_sink_->DemandDrawHw(params.viewport_size,
                                         params.viewport_rect_for_tile_priority,
                                         params.transform_for_tile_priority);
  }

  // Ensure that a response is always sent even if the reply hasn't
  // generated a compostior frame.
  if (hardware_draw_reply_) {
    SyncCompositorCommonRendererParams common_renderer_params;
    PopulateCommonParams(&common_renderer_params);
    // Did not swap.
    std::move(hardware_draw_reply_)
        .Run(common_renderer_params, 0u, 0u, base::nullopt);
  }
}

void SynchronousCompositorProxy::WillSkipDraw() {
  layer_tree_frame_sink_->WillSkipDraw();
}

struct SynchronousCompositorProxy::SharedMemoryWithSize {
  base::SharedMemory shm;
  const size_t buffer_size;
  bool zeroed;

  SharedMemoryWithSize(base::SharedMemoryHandle shm_handle, size_t buffer_size)
      : shm(shm_handle, false), buffer_size(buffer_size), zeroed(true) {}
};

void SynchronousCompositorProxy::ZeroSharedMemory() {
  // It is possible for this to get called twice, eg. if draw is called before
  // the LayerTreeFrameSink is ready. Just ignore duplicated calls rather than
  // inventing a complicated system to avoid it.
  if (software_draw_shm_->zeroed)
    return;

  memset(software_draw_shm_->shm.memory(), 0, software_draw_shm_->buffer_size);
  software_draw_shm_->zeroed = true;
}

void SynchronousCompositorProxy::DemandDrawSw(
    const SyncCompositorDemandDrawSwParams& params,
    DemandDrawSwCallback callback) {
  invalidate_needs_draw_ = false;
  software_draw_reply_ = std::move(callback);
  if (layer_tree_frame_sink_) {
    SkCanvas* sk_canvas_for_draw = SynchronousCompositorGetSkCanvas();
    if (use_in_process_zero_copy_software_draw_) {
      DCHECK(sk_canvas_for_draw);
      layer_tree_frame_sink_->DemandDrawSw(sk_canvas_for_draw);
    } else {
      DCHECK(!sk_canvas_for_draw);
      DoDemandDrawSw(params);
    }
  }

  // Ensure that a response is always sent even if the reply hasn't
  // generated a compostior frame.
  if (software_draw_reply_) {
    SyncCompositorCommonRendererParams common_renderer_params;
    PopulateCommonParams(&common_renderer_params);
    // Did not swap.
    std::move(software_draw_reply_)
        .Run(common_renderer_params, 0u, base::nullopt);
  }
}

void SynchronousCompositorProxy::DoDemandDrawSw(
    const SyncCompositorDemandDrawSwParams& params) {
  DCHECK(layer_tree_frame_sink_);
  DCHECK(software_draw_shm_->zeroed);
  software_draw_shm_->zeroed = false;

  SkImageInfo info =
      SkImageInfo::MakeN32Premul(params.size.width(), params.size.height());
  size_t stride = info.minRowBytes();
  size_t buffer_size = info.computeByteSize(stride);
  DCHECK_EQ(software_draw_shm_->buffer_size, buffer_size);

  SkBitmap bitmap;
  if (!bitmap.installPixels(info, software_draw_shm_->shm.memory(), stride))
    return;
  SkCanvas canvas(bitmap);
  canvas.clipRect(gfx::RectToSkRect(params.clip));
  canvas.concat(params.transform.matrix());

  layer_tree_frame_sink_->DemandDrawSw(&canvas);
}

void SynchronousCompositorProxy::SubmitCompositorFrame(
    uint32_t layer_tree_frame_sink_id,
    viz::CompositorFrame frame) {
  // Verify that exactly one of these is true.
  DCHECK(hardware_draw_reply_.is_null() ^ software_draw_reply_.is_null());
  SyncCompositorCommonRendererParams common_renderer_params;
  PopulateCommonParams(&common_renderer_params);

  if (hardware_draw_reply_) {
    std::move(hardware_draw_reply_)
        .Run(common_renderer_params, layer_tree_frame_sink_id,
             NextMetadataVersion(), std::move(frame));
  } else if (software_draw_reply_) {
    std::move(software_draw_reply_)
        .Run(common_renderer_params, NextMetadataVersion(),
             std::move(frame.metadata));
  } else {
    NOTREACHED();
  }
}

void SynchronousCompositorProxy::SendSetNeedsBeginFramesIfNeeded() {
  bool needs_begin_frames =
      needs_begin_frame_for_frame_sink_ || needs_begin_frame_for_animate_input_;
  if (browser_needs_begin_frame_state_ != needs_begin_frames)
    SendSetNeedsBeginFrames(needs_begin_frames);
  browser_needs_begin_frame_state_ = needs_begin_frames;
}

void SynchronousCompositorProxy::SetNeedsBeginFrames(bool needs_begin_frames) {
  needs_begin_frame_for_frame_sink_ = needs_begin_frames;
  SendSetNeedsBeginFramesIfNeeded();
}

void SynchronousCompositorProxy::SinkDestroyed() {
  layer_tree_frame_sink_ = nullptr;
}

void SynchronousCompositorProxy::ComputeScroll(base::TimeTicks animation_time) {
  compute_scroll_called_via_ipc_ = true;

  if (need_animate_scroll_) {
    need_animate_scroll_ = false;
    input_handler_proxy_->SynchronouslyAnimate(animation_time);
  }
}

void SynchronousCompositorProxy::SetBeginFrameSourcePaused(bool paused) {
  begin_frame_paused_ = paused;
  if (layer_tree_frame_sink_)
    layer_tree_frame_sink_->SetBeginFrameSourcePaused(paused);
}

void SynchronousCompositorProxy::BeginFrame(const viz::BeginFrameArgs& args) {
  if (needs_begin_frame_for_animate_input_) {
    needs_begin_frame_for_animate_input_ = false;
    input_handler_proxy_->SynchronouslyAnimate(args.frame_time);
  }
  if (needs_begin_frame_for_frame_sink_ && layer_tree_frame_sink_)
    layer_tree_frame_sink_->BeginFrame(args);

  SyncCompositorCommonRendererParams param;
  PopulateCommonParams(&param);
  SendBeginFrameResponse(param);
}

void SynchronousCompositorProxy::SetScroll(
    const gfx::ScrollOffset& new_total_scroll_offset) {
  if (total_scroll_offset_ == new_total_scroll_offset)
    return;
  total_scroll_offset_ = new_total_scroll_offset;
  input_handler_proxy_->SynchronouslySetRootScrollOffset(total_scroll_offset_);
}

void SynchronousCompositorProxy::SetMemoryPolicy(uint32_t bytes_limit) {
  if (!layer_tree_frame_sink_)
    return;
  layer_tree_frame_sink_->SetMemoryPolicy(bytes_limit);
}

void SynchronousCompositorProxy::ReclaimResources(
    uint32_t layer_tree_frame_sink_id,
    const std::vector<viz::ReturnedResource>& resources) {
  if (!layer_tree_frame_sink_)
    return;
  layer_tree_frame_sink_->ReclaimResources(layer_tree_frame_sink_id, resources);
}

void SynchronousCompositorProxy::SetSharedMemory(
    const SyncCompositorSetSharedMemoryParams& params,
    SetSharedMemoryCallback callback) {
  bool success = false;
  SyncCompositorCommonRendererParams common_renderer_params;
  if (base::SharedMemory::IsHandleValid(params.shm_handle)) {
    software_draw_shm_.reset(
        new SharedMemoryWithSize(params.shm_handle, params.buffer_size));
    if (software_draw_shm_->shm.Map(params.buffer_size)) {
      DCHECK(software_draw_shm_->shm.memory());
      PopulateCommonParams(&common_renderer_params);
      success = true;
    }
  }
  std::move(callback).Run(success, common_renderer_params);
}

void SynchronousCompositorProxy::ZoomBy(float zoom_delta,
                                        const gfx::Point& anchor,
                                        ZoomByCallback callback) {
  zoom_by_reply_ = std::move(callback);
  input_handler_proxy_->SynchronouslyZoomBy(zoom_delta, anchor);
  SyncCompositorCommonRendererParams common_renderer_params;
  PopulateCommonParams(&common_renderer_params);
  std::move(zoom_by_reply_).Run(common_renderer_params);
}

uint32_t SynchronousCompositorProxy::NextMetadataVersion() {
  return ++metadata_version_;
}

void SynchronousCompositorProxy::SendDemandDrawHwAsyncReply(
    const content::SyncCompositorCommonRendererParams&,
    uint32_t layer_tree_frame_sink_id,
    uint32_t metadata_version,
    base::Optional<viz::CompositorFrame> frame) {
  control_host_->ReturnFrame(layer_tree_frame_sink_id, metadata_version,
                             std::move(frame));
}

void SynchronousCompositorProxy::SendBeginFrameResponse(
    const content::SyncCompositorCommonRendererParams& param) {
  control_host_->BeginFrameResponse(param);
}

void SynchronousCompositorProxy::SendAsyncRendererStateIfNeeded() {
  if (hardware_draw_reply_ || software_draw_reply_ || zoom_by_reply_ || !host_)
    return;

  SyncCompositorCommonRendererParams params;
  PopulateCommonParams(&params);
  host_->UpdateState(params);
}

void SynchronousCompositorProxy::SendSetNeedsBeginFrames(
    bool needs_begin_frames) {
  needs_begin_frame_ = needs_begin_frames;
  if (host_)
    host_->SetNeedsBeginFrames(needs_begin_frames);
}

void SynchronousCompositorProxy::LayerTreeFrameSinkCreated() {
  DCHECK(layer_tree_frame_sink_);
  if (host_)
    host_->LayerTreeFrameSinkCreated();
}

void SynchronousCompositorProxy::BindChannel(
    mojom::SynchronousCompositorControlHostPtr control_host,
    mojom::SynchronousCompositorHostAssociatedPtrInfo host,
    mojom::SynchronousCompositorAssociatedRequest compositor_request) {
  control_host_ = std::move(control_host);
  host_.Bind(std::move(host));
  binding_.Bind(std::move(compositor_request));

  if (layer_tree_frame_sink_)
    LayerTreeFrameSinkCreated();

  if (needs_begin_frame_)
    host_->SetNeedsBeginFrames(true);
}

}  // namespace content
