// Copyright 2014 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/child_frame_compositing_helper.h"

#include "cc/layers/delegated_frame_provider.h"
#include "cc/layers/delegated_frame_resource_collection.h"
#include "cc/layers/delegated_renderer_layer.h"
#include "cc/layers/solid_color_layer.h"
#include "cc/layers/texture_layer.h"
#include "cc/output/context_provider.h"
#include "cc/output/copy_output_request.h"
#include "cc/output/copy_output_result.h"
#include "cc/resources/single_release_callback.h"
#include "content/common/browser_plugin/browser_plugin_messages.h"
#include "content/common/frame_messages.h"
#include "content/common/gpu/client/context_provider_command_buffer.h"
#include "content/renderer/browser_plugin/browser_plugin.h"
#include "content/renderer/browser_plugin/browser_plugin_manager.h"
#include "content/renderer/compositor_bindings/web_layer_impl.h"
#include "content/renderer/render_frame_impl.h"
#include "content/renderer/render_frame_proxy.h"
#include "content/renderer/render_thread_impl.h"
#include "skia/ext/image_operations.h"
#include "third_party/WebKit/public/platform/WebGraphicsContext3D.h"
#include "third_party/WebKit/public/web/WebFrame.h"
#include "third_party/WebKit/public/web/WebPluginContainer.h"
#include "third_party/khronos/GLES2/gl2.h"
#include "ui/gfx/size_conversions.h"
#include "ui/gfx/skia_util.h"

namespace content {

ChildFrameCompositingHelper::SwapBuffersInfo::SwapBuffersInfo()
    : route_id(0),
      output_surface_id(0),
      host_id(0),
      software_frame_id(0),
      shared_memory(NULL) {}

ChildFrameCompositingHelper*
ChildFrameCompositingHelper::CreateForBrowserPlugin(
    const base::WeakPtr<BrowserPlugin>& browser_plugin) {
  return new ChildFrameCompositingHelper(
      browser_plugin, NULL, NULL, browser_plugin->render_view_routing_id());
}

ChildFrameCompositingHelper*
ChildFrameCompositingHelper::CreateForRenderFrameProxy(
    RenderFrameProxy* render_frame_proxy) {
  return new ChildFrameCompositingHelper(base::WeakPtr<BrowserPlugin>(),
                                         render_frame_proxy->web_frame(),
                                         render_frame_proxy,
                                         render_frame_proxy->routing_id());
}

ChildFrameCompositingHelper::ChildFrameCompositingHelper(
    const base::WeakPtr<BrowserPlugin>& browser_plugin,
    blink::WebFrame* frame,
    RenderFrameProxy* render_frame_proxy,
    int host_routing_id)
    : host_routing_id_(host_routing_id),
      last_route_id_(0),
      last_output_surface_id_(0),
      last_host_id_(0),
      last_mailbox_valid_(false),
      ack_pending_(true),
      software_ack_pending_(false),
      opaque_(true),
      browser_plugin_(browser_plugin),
      render_frame_proxy_(render_frame_proxy),
      frame_(frame) {}

ChildFrameCompositingHelper::~ChildFrameCompositingHelper() {}

BrowserPluginManager* ChildFrameCompositingHelper::GetBrowserPluginManager() {
  if (!browser_plugin_)
    return NULL;

  return browser_plugin_->browser_plugin_manager();
}

blink::WebPluginContainer* ChildFrameCompositingHelper::GetContainer() {
  if (!browser_plugin_)
    return NULL;

  return browser_plugin_->container();
}

int ChildFrameCompositingHelper::GetInstanceID() {
  if (!browser_plugin_)
    return 0;

  return browser_plugin_->guest_instance_id();
}

void ChildFrameCompositingHelper::SendCompositorFrameSwappedACKToBrowser(
    FrameHostMsg_CompositorFrameSwappedACK_Params& params) {
  // This function will be removed when BrowserPluginManager is removed and
  // BrowserPlugin is modified to use a RenderFrame.
  if (GetBrowserPluginManager()) {
    GetBrowserPluginManager()->Send(
        new BrowserPluginHostMsg_CompositorFrameSwappedACK(
            host_routing_id_, GetInstanceID(), params));
  } else if (render_frame_proxy_) {
    render_frame_proxy_->Send(
        new FrameHostMsg_CompositorFrameSwappedACK(host_routing_id_, params));
  }
}

void ChildFrameCompositingHelper::SendBuffersSwappedACKToBrowser(
    FrameHostMsg_BuffersSwappedACK_Params& params) {
  // This function will be removed when BrowserPluginManager is removed and
  // BrowserPlugin is modified to use a RenderFrame.
  if (GetBrowserPluginManager()) {
    GetBrowserPluginManager()->Send(new BrowserPluginHostMsg_BuffersSwappedACK(
        host_routing_id_, params));
  } else if (render_frame_proxy_) {
    render_frame_proxy_->Send(
        new FrameHostMsg_BuffersSwappedACK(host_routing_id_, params));
  }
}

void ChildFrameCompositingHelper::SendReclaimCompositorResourcesToBrowser(
    FrameHostMsg_ReclaimCompositorResources_Params& params) {
  // This function will be removed when BrowserPluginManager is removed and
  // BrowserPlugin is modified to use a RenderFrame.
  if (GetBrowserPluginManager()) {
    GetBrowserPluginManager()->Send(
        new BrowserPluginHostMsg_ReclaimCompositorResources(
            host_routing_id_, GetInstanceID(), params));
  } else if (render_frame_proxy_) {
    render_frame_proxy_->Send(
        new FrameHostMsg_ReclaimCompositorResources(host_routing_id_, params));
  }
}

void ChildFrameCompositingHelper::CopyFromCompositingSurface(
    int request_id,
    gfx::Rect source_rect,
    gfx::Size dest_size) {
  CHECK(background_layer_);
  scoped_ptr<cc::CopyOutputRequest> request =
      cc::CopyOutputRequest::CreateBitmapRequest(base::Bind(
          &ChildFrameCompositingHelper::CopyFromCompositingSurfaceHasResult,
          this,
          request_id,
          dest_size));
  request->set_area(source_rect);
  background_layer_->RequestCopyOfOutput(request.Pass());
}

void ChildFrameCompositingHelper::DidCommitCompositorFrame() {
  if (software_ack_pending_) {
    FrameHostMsg_CompositorFrameSwappedACK_Params params;
    params.producing_host_id = last_host_id_;
    params.producing_route_id = last_route_id_;
    params.output_surface_id = last_output_surface_id_;
    if (!unacked_software_frames_.empty()) {
      params.ack.last_software_frame_id = unacked_software_frames_.back();
      unacked_software_frames_.pop_back();
    }

    SendCompositorFrameSwappedACKToBrowser(params);

    software_ack_pending_ = false;
  }
  if (!resource_collection_.get() || !ack_pending_)
    return;

  FrameHostMsg_CompositorFrameSwappedACK_Params params;
  params.producing_host_id = last_host_id_;
  params.producing_route_id = last_route_id_;
  params.output_surface_id = last_output_surface_id_;
  resource_collection_->TakeUnusedResourcesForChildCompositor(
      &params.ack.resources);

  SendCompositorFrameSwappedACKToBrowser(params);

  ack_pending_ = false;
}

void ChildFrameCompositingHelper::EnableCompositing(bool enable) {
  if (enable && !background_layer_.get()) {
    background_layer_ = cc::SolidColorLayer::Create();
    background_layer_->SetMasksToBounds(true);
    background_layer_->SetBackgroundColor(
        SkColorSetARGBInline(255, 255, 255, 255));
    web_layer_.reset(new WebLayerImpl(background_layer_));
  }

  if (GetContainer()) {
    GetContainer()->setWebLayer(enable ? web_layer_.get() : NULL);
  } else if (frame_) {
    frame_->setRemoteWebLayer(enable ? web_layer_.get() : NULL);
  }
}

void ChildFrameCompositingHelper::CheckSizeAndAdjustLayerProperties(
    const gfx::Size& new_size,
    float device_scale_factor,
    cc::Layer* layer) {
  if (buffer_size_ != new_size) {
    buffer_size_ = new_size;
    // The container size is in DIP, so is the layer size.
    // Buffer size is in physical pixels, so we need to adjust
    // it by the device scale factor.
    gfx::Size device_scale_adjusted_size = gfx::ToFlooredSize(
        gfx::ScaleSize(buffer_size_, 1.0f / device_scale_factor));
    layer->SetBounds(device_scale_adjusted_size);
  }

  // Manually manage background layer for transparent webview.
  if (!opaque_)
    background_layer_->SetIsDrawable(false);
}

void ChildFrameCompositingHelper::MailboxReleased(SwapBuffersInfo mailbox,
                                                  uint32 sync_point,
                                                  bool lost_resource) {
  if (mailbox.type == SOFTWARE_COMPOSITOR_FRAME) {
    delete mailbox.shared_memory;
    mailbox.shared_memory = NULL;
  } else if (lost_resource) {
    // Reset mailbox's name if the resource was lost.
    mailbox.name.SetZero();
  }

  // This means the GPU process crashed or guest crashed.
  if (last_host_id_ != mailbox.host_id ||
      last_output_surface_id_ != mailbox.output_surface_id ||
      last_route_id_ != mailbox.route_id)
    return;

  if (mailbox.type == SOFTWARE_COMPOSITOR_FRAME)
    unacked_software_frames_.push_back(mailbox.software_frame_id);

  // We need to send an ACK to for every buffer sent to us.
  // However, if a buffer is freed up from
  // the compositor in cases like switching back to SW mode without a new
  // buffer arriving, no ACK is needed.
  if (!ack_pending_) {
    last_mailbox_valid_ = false;
    return;
  }
  ack_pending_ = false;
  switch (mailbox.type) {
    case TEXTURE_IMAGE_TRANSPORT: {
      FrameHostMsg_BuffersSwappedACK_Params params;
      params.gpu_host_id = mailbox.host_id;
      params.gpu_route_id = mailbox.route_id;
      params.mailbox = mailbox.name;
      params.sync_point = sync_point;
      SendBuffersSwappedACKToBrowser(params);
      break;
    }
    case GL_COMPOSITOR_FRAME: {
      FrameHostMsg_CompositorFrameSwappedACK_Params params;
      params.producing_host_id = mailbox.host_id;
      params.producing_route_id = mailbox.route_id;
      params.output_surface_id = mailbox.output_surface_id;
      params.ack.gl_frame_data.reset(new cc::GLFrameData());
      params.ack.gl_frame_data->mailbox = mailbox.name;
      params.ack.gl_frame_data->size = mailbox.size;
      params.ack.gl_frame_data->sync_point = sync_point;
      SendCompositorFrameSwappedACKToBrowser(params);
      break;
    }
    case SOFTWARE_COMPOSITOR_FRAME:
      break;
  }
}

void ChildFrameCompositingHelper::OnContainerDestroy() {
  if (GetContainer())
    GetContainer()->setWebLayer(NULL);

  if (resource_collection_)
    resource_collection_->SetClient(NULL);

  ack_pending_ = false;
  software_ack_pending_ = false;
  resource_collection_ = NULL;
  frame_provider_ = NULL;
  texture_layer_ = NULL;
  delegated_layer_ = NULL;
  background_layer_ = NULL;
  web_layer_.reset();
}

void ChildFrameCompositingHelper::ChildFrameGone() {
  background_layer_->SetBackgroundColor(SkColorSetARGBInline(255, 0, 128, 0));
  background_layer_->RemoveAllChildren();
  background_layer_->SetIsDrawable(true);
  background_layer_->SetContentsOpaque(true);
}

void ChildFrameCompositingHelper::OnBuffersSwappedPrivate(
    const SwapBuffersInfo& mailbox,
    uint32 sync_point,
    float device_scale_factor) {
  DCHECK(!delegated_layer_.get());
  // If these mismatch, we are either just starting up, GPU process crashed or
  // guest renderer crashed.
  // In this case, we are communicating with a new image transport
  // surface and must ACK with the new ID's and an empty mailbox.
  if (last_route_id_ != mailbox.route_id ||
      last_output_surface_id_ != mailbox.output_surface_id ||
      last_host_id_ != mailbox.host_id)
    last_mailbox_valid_ = false;

  last_route_id_ = mailbox.route_id;
  last_output_surface_id_ = mailbox.output_surface_id;
  last_host_id_ = mailbox.host_id;

  ack_pending_ = true;
  // Browser plugin getting destroyed, do a fast ACK.
  if (!background_layer_.get()) {
    MailboxReleased(mailbox, sync_point, false);
    return;
  }

  if (!texture_layer_.get()) {
    texture_layer_ = cc::TextureLayer::CreateForMailbox(NULL);
    texture_layer_->SetIsDrawable(true);
    SetContentsOpaque(opaque_);

    background_layer_->AddChild(texture_layer_);
  }

  // The size of browser plugin container is not always equal to the size
  // of the buffer that arrives here. This could be for a number of reasons,
  // including autosize and a resize in progress.
  // During resize, the container size changes first and then some time
  // later, a new buffer with updated size will arrive. During this process,
  // we need to make sure that things are still displayed pixel perfect.
  // We accomplish this by modifying bounds of the texture layer only
  // when a new buffer arrives.
  // Visually, this will either display a smaller part of the buffer
  // or introduce a gutter around it.
  CheckSizeAndAdjustLayerProperties(
      mailbox.size, device_scale_factor, texture_layer_.get());

  bool is_software_frame = mailbox.type == SOFTWARE_COMPOSITOR_FRAME;
  bool current_mailbox_valid = is_software_frame ? mailbox.shared_memory != NULL
                                                 : !mailbox.name.IsZero();
  if (!is_software_frame && !last_mailbox_valid_) {
    SwapBuffersInfo empty_info = mailbox;
    empty_info.name.SetZero();
    MailboxReleased(empty_info, 0, false);
    if (!current_mailbox_valid)
      return;
  }

  cc::TextureMailbox texture_mailbox;
  scoped_ptr<cc::SingleReleaseCallback> release_callback;
  if (current_mailbox_valid) {
    release_callback =
        cc::SingleReleaseCallback::Create(
            base::Bind(&ChildFrameCompositingHelper::MailboxReleased,
                       scoped_refptr<ChildFrameCompositingHelper>(this),
                       mailbox)).Pass();
    if (is_software_frame) {
      texture_mailbox = cc::TextureMailbox(mailbox.shared_memory, mailbox.size);
    } else {
      texture_mailbox =
          cc::TextureMailbox(mailbox.name, GL_TEXTURE_2D, sync_point);
    }
  }

  texture_layer_->SetFlipped(!is_software_frame);
  texture_layer_->SetTextureMailbox(texture_mailbox, release_callback.Pass());
  texture_layer_->SetNeedsDisplay();
  last_mailbox_valid_ = current_mailbox_valid;
}

void ChildFrameCompositingHelper::OnBuffersSwapped(
    const gfx::Size& size,
    const gpu::Mailbox& mailbox,
    int gpu_route_id,
    int gpu_host_id,
    float device_scale_factor) {
  SwapBuffersInfo swap_info;
  swap_info.name = mailbox;
  swap_info.type = TEXTURE_IMAGE_TRANSPORT;
  swap_info.size = size;
  swap_info.route_id = gpu_route_id;
  swap_info.output_surface_id = 0;
  swap_info.host_id = gpu_host_id;
  OnBuffersSwappedPrivate(swap_info, 0, device_scale_factor);
}

void ChildFrameCompositingHelper::OnCompositorFrameSwapped(
    scoped_ptr<cc::CompositorFrame> frame,
    int route_id,
    uint32 output_surface_id,
    int host_id,
    base::SharedMemoryHandle handle) {

  if (frame->gl_frame_data) {
    SwapBuffersInfo swap_info;
    swap_info.name = frame->gl_frame_data->mailbox;
    swap_info.type = GL_COMPOSITOR_FRAME;
    swap_info.size = frame->gl_frame_data->size;
    swap_info.route_id = route_id;
    swap_info.output_surface_id = output_surface_id;
    swap_info.host_id = host_id;
    OnBuffersSwappedPrivate(swap_info,
                            frame->gl_frame_data->sync_point,
                            frame->metadata.device_scale_factor);
    return;
  }

  if (frame->software_frame_data) {
    cc::SoftwareFrameData* frame_data = frame->software_frame_data.get();

    SwapBuffersInfo swap_info;
    swap_info.type = SOFTWARE_COMPOSITOR_FRAME;
    swap_info.size = frame_data->size;
    swap_info.route_id = route_id;
    swap_info.output_surface_id = output_surface_id;
    swap_info.host_id = host_id;
    swap_info.software_frame_id = frame_data->id;

    scoped_ptr<base::SharedMemory> shared_memory(
        new base::SharedMemory(handle, true));
    const size_t size_in_bytes = 4 * frame_data->size.GetArea();
    if (!shared_memory->Map(size_in_bytes)) {
      LOG(ERROR) << "Failed to map shared memory of size " << size_in_bytes;
      // Send ACK right away.
      software_ack_pending_ = true;
      MailboxReleased(swap_info, 0, false);
      DidCommitCompositorFrame();
      return;
    }

    swap_info.shared_memory = shared_memory.release();
    OnBuffersSwappedPrivate(swap_info, 0, frame->metadata.device_scale_factor);
    software_ack_pending_ = true;
    last_route_id_ = route_id;
    last_output_surface_id_ = output_surface_id;
    last_host_id_ = host_id;
    return;
  }

  DCHECK(!texture_layer_.get());

  cc::DelegatedFrameData* frame_data = frame->delegated_frame_data.get();
  // Do nothing if we are getting destroyed or have no frame data.
  if (!frame_data || !background_layer_)
    return;

  DCHECK(!frame_data->render_pass_list.empty());
  cc::RenderPass* root_pass = frame_data->render_pass_list.back();
  gfx::Size frame_size = root_pass->output_rect.size();

  if (last_route_id_ != route_id ||
      last_output_surface_id_ != output_surface_id ||
      last_host_id_ != host_id) {
    // Resource ids are scoped by the output surface.
    // If the originating output surface doesn't match the last one, it
    // indicates the guest's output surface may have been recreated, in which
    // case we should recreate the DelegatedRendererLayer, to avoid matching
    // resources from the old one with resources from the new one which would
    // have the same id.
    frame_provider_ = NULL;

    // Drop the cc::DelegatedFrameResourceCollection so that we will not return
    // any resources from the old output surface with the new output surface id.
    if (resource_collection_) {
      resource_collection_->SetClient(NULL);

      if (resource_collection_->LoseAllResources())
        SendReturnedDelegatedResources();
      resource_collection_ = NULL;
    }
    last_output_surface_id_ = output_surface_id;
    last_route_id_ = route_id;
    last_host_id_ = host_id;
  }
  if (!resource_collection_) {
    resource_collection_ = new cc::DelegatedFrameResourceCollection;
    resource_collection_->SetClient(this);
  }
  if (!frame_provider_.get() || frame_provider_->frame_size() != frame_size) {
    frame_provider_ = new cc::DelegatedFrameProvider(
        resource_collection_.get(), frame->delegated_frame_data.Pass());
    if (delegated_layer_.get())
      delegated_layer_->RemoveFromParent();
    delegated_layer_ =
        cc::DelegatedRendererLayer::Create(frame_provider_.get());
    delegated_layer_->SetIsDrawable(true);
    SetContentsOpaque(opaque_);
    background_layer_->AddChild(delegated_layer_);
  } else {
    frame_provider_->SetFrameData(frame->delegated_frame_data.Pass());
  }

  CheckSizeAndAdjustLayerProperties(
      frame_data->render_pass_list.back()->output_rect.size(),
      frame->metadata.device_scale_factor,
      delegated_layer_.get());

  ack_pending_ = true;
}

void ChildFrameCompositingHelper::UpdateVisibility(bool visible) {
  if (texture_layer_.get())
    texture_layer_->SetIsDrawable(visible);
  if (delegated_layer_.get())
    delegated_layer_->SetIsDrawable(visible);
}

void ChildFrameCompositingHelper::UnusedResourcesAreAvailable() {
  if (ack_pending_)
    return;

  SendReturnedDelegatedResources();
}

void ChildFrameCompositingHelper::SendReturnedDelegatedResources() {
  FrameHostMsg_ReclaimCompositorResources_Params params;
  if (resource_collection_)
    resource_collection_->TakeUnusedResourcesForChildCompositor(
        &params.ack.resources);
  DCHECK(!params.ack.resources.empty());

  params.route_id = last_route_id_;
  params.output_surface_id = last_output_surface_id_;
  params.renderer_host_id = last_host_id_;
  SendReclaimCompositorResourcesToBrowser(params);
}

void ChildFrameCompositingHelper::SetContentsOpaque(bool opaque) {
  opaque_ = opaque;

  if (texture_layer_.get())
    texture_layer_->SetContentsOpaque(opaque_);
  if (delegated_layer_.get())
    delegated_layer_->SetContentsOpaque(opaque_);
}

void ChildFrameCompositingHelper::CopyFromCompositingSurfaceHasResult(
    int request_id,
    gfx::Size dest_size,
    scoped_ptr<cc::CopyOutputResult> result) {
  scoped_ptr<SkBitmap> bitmap;
  if (result && result->HasBitmap() && !result->size().IsEmpty())
    bitmap = result->TakeBitmap();

  SkBitmap resized_bitmap;
  if (bitmap) {
    resized_bitmap =
        skia::ImageOperations::Resize(*bitmap,
                                      skia::ImageOperations::RESIZE_BEST,
                                      dest_size.width(),
                                      dest_size.height());
  }
  if (GetBrowserPluginManager()) {
    GetBrowserPluginManager()->Send(
        new BrowserPluginHostMsg_CopyFromCompositingSurfaceAck(
            host_routing_id_, GetInstanceID(), request_id, resized_bitmap));
  }
}

}  // namespace content
