// 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)));
}

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.PassMessagePipe()))));

  factory_.Create(cc_id_);
  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();
  display_->Resize(frame_size);
  factory_.SubmitFrame(cc_id_,
                       pending_frame_.To<scoped_ptr<cc::CompositorFrame>>(),
                       base::Bind(&CallCallback, pending_callback_));
  scheduler_->SetNeedsDraw();
  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();
  factory_.Destroy(cc_id_);
  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
