// 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 "services/surfaces/display_impl.h"

#include "cc/output/compositor_frame.h"
#include "cc/surfaces/display.h"
#include "mojo/converters/geometry/geometry_type_converters.h"
#include "mojo/converters/surfaces/surfaces_type_converters.h"
#include "services/surfaces/context_provider_mojo.h"
#include "services/surfaces/surfaces_output_surface.h"
#include "services/surfaces/surfaces_scheduler.h"

namespace surfaces {
namespace {
void CallCallback(const mojo::Closure& callback, cc::SurfaceDrawStatus status) {
  callback.Run();
}
}

DisplayImpl::DisplayImpl(cc::SurfaceManager* manager,
                         cc::SurfaceId cc_id,
                         SurfacesScheduler* scheduler,
                         mojo::ContextProviderPtr context_provider,
                         mojo::ResourceReturnerPtr returner,
                         mojo::InterfaceRequest<mojo::Display> display_request)
    : manager_(manager),
      factory_(manager, this),
      cc_id_(cc_id),
      scheduler_(scheduler),
      context_provider_(context_provider.Pass()),
      returner_(returner.Pass()),
      viewport_param_binding_(this),
      display_binding_(this, display_request.Pass()) {
  mojo::ViewportParameterListenerPtr viewport_parameter_listener;
  viewport_param_binding_.Bind(GetProxy(&viewport_parameter_listener));
  context_provider_->Create(
      viewport_parameter_listener.Pass(),
      base::Bind(&DisplayImpl::OnContextCreated, base::Unretained(this)));
  factory_.Create(cc_id_);
}

void DisplayImpl::OnContextCreated(mojo::CommandBufferPtr gles2_client) {
  DCHECK(!display_);

  cc::RendererSettings settings;
  display_.reset(new cc::Display(this, manager_, nullptr, nullptr, settings));
  scheduler_->AddDisplay(display_.get());
  display_->Initialize(make_scoped_ptr(new mojo::DirectOutputSurface(
      new mojo::ContextProviderMojo(
          gles2_client.PassInterface().PassHandle()))));
  display_->Resize(last_submitted_frame_size_);

  display_->SetSurfaceId(cc_id_, 1.f);
  if (pending_frame_)
    Draw();
}

DisplayImpl::~DisplayImpl() {
  if (display_) {
    factory_.Destroy(cc_id_);
    scheduler_->RemoveDisplay(display_.get());
  }
}

void DisplayImpl::SubmitFrame(mojo::FramePtr frame,
                              const SubmitFrameCallback& callback) {
  DCHECK(pending_callback_.is_null());
  pending_frame_ = frame.Pass();
  pending_callback_ = callback;
  if (display_)
    Draw();
}

void DisplayImpl::Draw() {
  gfx::Size frame_size =
      pending_frame_->passes[0]->output_rect.To<gfx::Rect>().size();
  last_submitted_frame_size_ = frame_size;
  display_->Resize(frame_size);
  factory_.SubmitFrame(cc_id_,
                       pending_frame_.To<scoped_ptr<cc::CompositorFrame>>(),
                       base::Bind(&CallCallback, pending_callback_));
  scheduler_->SetNeedsDraw();
  pending_frame_.reset();
  pending_callback_.reset();
}

void DisplayImpl::DisplayDamaged() {
}

void DisplayImpl::DidSwapBuffers() {
}

void DisplayImpl::DidSwapBuffersComplete() {
}

void DisplayImpl::CommitVSyncParameters(base::TimeTicks timebase,
                                        base::TimeDelta interval) {
}

void DisplayImpl::OutputSurfaceLost() {
  // If our OutputSurface is lost we can't draw until we get a new one. For now,
  // destroy the display and create a new one when our ContextProvider provides
  // a new one.
  // TODO: This is more violent than necessary - we could simply remove this
  // display from the scheduler's set and pass a new context in to the
  // OutputSurface. It should be able to reinitialize properly.
  scheduler_->RemoveDisplay(display_.get());
  display_.reset();
  viewport_param_binding_.Close();
  mojo::ViewportParameterListenerPtr viewport_parameter_listener;
  viewport_param_binding_.Bind(GetProxy(&viewport_parameter_listener));
  context_provider_->Create(
      viewport_parameter_listener.Pass(),
      base::Bind(&DisplayImpl::OnContextCreated, base::Unretained(this)));
}

void DisplayImpl::OnVSyncParametersUpdated(int64_t timebase, int64_t interval) {
  scheduler_->OnVSyncParametersUpdated(
      base::TimeTicks::FromInternalValue(timebase),
      base::TimeDelta::FromInternalValue(interval));
}

void DisplayImpl::ReturnResources(const cc::ReturnedResourceArray& resources) {
  if (resources.empty())
    return;
  DCHECK(returner_);

  mojo::Array<mojo::ReturnedResourcePtr> ret(resources.size());
  for (size_t i = 0; i < resources.size(); ++i) {
    ret[i] = mojo::ReturnedResource::From(resources[i]);
  }
  returner_->ReturnResources(ret.Pass());
}

}  // namespace surfaces
