// 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/gfx/compositor/compositor_engine.h"

#include <algorithm>
#include <sstream>
#include <utility>

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/time/time.h"
#include "mojo/services/gfx/composition/cpp/formatting.h"
#include "services/gfx/compositor/backend/gpu_output.h"
#include "services/gfx/compositor/graph/snapshot.h"
#include "services/gfx/compositor/render/render_frame.h"
#include "services/gfx/compositor/renderer_impl.h"
#include "services/gfx/compositor/scene_impl.h"

namespace compositor {
namespace {
// TODO(jeffbrown): Determine and document a more appropriate size limit
// for viewports somewhere.  May be limited by the renderer output.
const int32_t kMaxViewportWidth = 65536;
const int32_t kMaxViewportHeight = 65536;

std::string SanitizeLabel(const mojo::String& label) {
  return label.get().substr(0, mojo::gfx::composition::kLabelMaxLength);
}
}  // namespace

CompositorEngine::CompositorEngine() : weak_factory_(this) {}

CompositorEngine::~CompositorEngine() {}

mojo::gfx::composition::SceneTokenPtr CompositorEngine::CreateScene(
    mojo::InterfaceRequest<mojo::gfx::composition::Scene> scene_request,
    const mojo::String& label) {
  auto scene_token = mojo::gfx::composition::SceneToken::New();
  scene_token->value = next_scene_token_value_++;
  CHECK(scene_token->value);
  CHECK(!FindScene(scene_token->value));

  // Create the state and bind implementation to it.
  SceneState* scene_state =
      new SceneState(scene_token.Pass(), SanitizeLabel(label));
  SceneImpl* scene_impl =
      new SceneImpl(this, scene_state, scene_request.Pass());
  scene_state->set_scene_impl(scene_impl);
  base::Closure error_handler =
      base::Bind(&CompositorEngine::OnSceneConnectionError,
                 base::Unretained(this), scene_state);
  scene_impl->set_connection_error_handler(error_handler);

  // Add to registry.
  scenes_by_token_.insert({scene_state->scene_token()->value, scene_state});
  DVLOG(1) << "CreateScene: scene=" << scene_state;
  return scene_state->scene_token()->Clone();
}

void CompositorEngine::OnSceneConnectionError(SceneState* scene_state) {
  DCHECK(IsSceneStateRegisteredDebug(scene_state));
  DVLOG(1) << "OnSceneConnectionError: scene=" << scene_state;

  DestroyScene(scene_state);
}

void CompositorEngine::DestroyScene(SceneState* scene_state) {
  DCHECK(IsSceneStateRegisteredDebug(scene_state));
  DVLOG(1) << "DestroyScene: scene=" << scene_state;

  // Unlink from other scenes.
  for (auto& pair : scenes_by_token_) {
    SceneState* other_scene_state = pair.second;
    other_scene_state->scene_def()->UnlinkReferencedScene(
        scene_state->scene_def(),
        base::Bind(&CompositorEngine::SendResourceUnavailable,
                   base::Unretained(this),
                   base::Unretained(other_scene_state)));
  }

  // Destroy any renderers using this scene.
  for (auto& renderer : renderers_) {
    if (renderer->root_scene() == scene_state) {
      LOG(ERROR) << "Destroying renderer whose root scene has become "
                    "unavailable: renderer="
                 << renderer;
      DestroyRenderer(renderer);
    }
  }

  // Destroy.
  InvalidateScene(scene_state);

  // Remove from registry.
  scenes_by_token_.erase(scene_state->scene_token()->value);
  delete scene_state;
}

void CompositorEngine::CreateRenderer(
    mojo::InterfaceHandle<mojo::ContextProvider> context_provider,
    mojo::InterfaceRequest<mojo::gfx::composition::Renderer> renderer_request,
    const mojo::String& label) {
  DCHECK(context_provider);
  uint32_t renderer_id = next_renderer_id_++;

  // Create the state and bind implementation to it.
  RendererState* renderer_state =
      new RendererState(renderer_id, SanitizeLabel(label));
  RendererImpl* renderer_impl =
      new RendererImpl(this, renderer_state, renderer_request.Pass());
  renderer_state->set_renderer_impl(renderer_impl);
  renderer_impl->set_connection_error_handler(
      base::Bind(&CompositorEngine::OnRendererConnectionError,
                 base::Unretained(this), renderer_state));

  // Create the renderer.
  SchedulerCallbacks scheduler_callbacks(
      base::Bind(&CompositorEngine::OnOutputUpdateRequest,
                 weak_factory_.GetWeakPtr(), renderer_state->GetWeakPtr()),
      base::Bind(&CompositorEngine::OnOutputSnapshotRequest,
                 weak_factory_.GetWeakPtr(), renderer_state->GetWeakPtr()));
  std::unique_ptr<Output> output(new GpuOutput(
      context_provider.Pass(), scheduler_callbacks,
      base::Bind(&CompositorEngine::OnOutputError, weak_factory_.GetWeakPtr(),
                 renderer_state->GetWeakPtr())));
  renderer_state->set_output(std::move(output));

  // Add to registry.
  renderers_.push_back(renderer_state);
  DVLOG(1) << "CreateRenderer: " << renderer_state;
}

void CompositorEngine::OnRendererConnectionError(
    RendererState* renderer_state) {
  DCHECK(IsRendererStateRegisteredDebug(renderer_state));
  DVLOG(1) << "OnRendererConnectionError: renderer=" << renderer_state;

  DestroyRenderer(renderer_state);
}

void CompositorEngine::DestroyRenderer(RendererState* renderer_state) {
  DCHECK(IsRendererStateRegisteredDebug(renderer_state));
  DVLOG(1) << "DestroyRenderer: renderer=" << renderer_state;

  // Remove from registry.
  renderers_.erase(
      std::find(renderers_.begin(), renderers_.end(), renderer_state));
  delete renderer_state;
}

void CompositorEngine::SetListener(
    SceneState* scene_state,
    mojo::gfx::composition::SceneListenerPtr listener) {
  DCHECK(IsSceneStateRegisteredDebug(scene_state));
  DVLOG(1) << "SetSceneListener: scene=" << scene_state;

  scene_state->set_scene_listener(listener.Pass());
}

void CompositorEngine::Update(SceneState* scene_state,
                              mojo::gfx::composition::SceneUpdatePtr update) {
  DCHECK(IsSceneStateRegisteredDebug(scene_state));
  DVLOG(1) << "Update: scene=" << scene_state << ", update=" << update;

  scene_state->scene_def()->EnqueueUpdate(update.Pass());
}

void CompositorEngine::Publish(
    SceneState* scene_state,
    mojo::gfx::composition::SceneMetadataPtr metadata) {
  DCHECK(IsSceneStateRegisteredDebug(scene_state));
  DVLOG(1) << "Publish: scene=" << scene_state << ", metadata=" << metadata;

  if (!metadata)
    metadata = mojo::gfx::composition::SceneMetadata::New();
  int64_t presentation_time = metadata->presentation_time;
  scene_state->scene_def()->EnqueuePublish(metadata.Pass());

  // Implicitly schedule fresh snapshots.
  InvalidateScene(scene_state);

  // Ensure that the scene will be presented eventually, even if it is
  // not associated with any renderer.  Note that this is only a backstop
  // in case the scene does not get presented sooner as part of snapshotting
  // a renderer.  Note that scenes which are actually visible will be
  // snapshotted by the renderer when it comes time to draw the next frame,
  // so this special case is only designed to help with scenes that are
  // not visible to ensure that we will still apply pending updates which
  // might have side-effects on the client's state (such as closing the
  // connection due to an error or releasing resources).
  MojoTimeTicks now = MojoGetTimeTicksNow();
  DCHECK(now >= 0);
  if (presentation_time <= now) {
    SceneDef::Disposition disposition = PresentScene(scene_state, now);
    if (disposition == SceneDef::Disposition::kFailed)
      DestroyScene(scene_state);
  } else {
    base::MessageLoop::current()->PostDelayedTask(
        FROM_HERE, base::Bind(&CompositorEngine::OnPresentScene,
                              weak_factory_.GetWeakPtr(),
                              scene_state->GetWeakPtr(), presentation_time),
        base::TimeDelta::FromMicroseconds(presentation_time - now));
  }
}

void CompositorEngine::ScheduleFrame(SceneState* scene_state,
                                     const SceneFrameCallback& callback) {
  DCHECK(IsSceneStateRegisteredDebug(scene_state));

  scene_state->AddSceneFrameCallback(callback);

  // TODO(jeffbrown): Be more selective and do this work only for scenes
  // which are strongly associated with the renderer so it doesn't receive
  // conflicting timing signals coming from multiple renderers.
  for (auto& renderer : renderers_) {
    ScheduleFrameForRenderer(renderer,
                             Scheduler::SchedulingMode::kUpdateAndSnapshot);
  }
}

void CompositorEngine::SetRootScene(
    RendererState* renderer_state,
    mojo::gfx::composition::SceneTokenPtr scene_token,
    uint32 scene_version,
    mojo::RectPtr viewport) {
  DCHECK(IsRendererStateRegisteredDebug(renderer_state));
  DCHECK(scene_token);
  DCHECK(viewport);
  DVLOG(1) << "SetRootScene: renderer=" << renderer_state
           << ", scene_token=" << scene_token
           << ", scene_version=" << scene_version << ", viewport=" << viewport;

  if (viewport->width <= 0 || viewport->width > kMaxViewportWidth ||
      viewport->height <= 0 || viewport->height > kMaxViewportHeight) {
    LOG(ERROR) << "Invalid viewport size: " << viewport;
    DestroyRenderer(renderer_state);
    return;
  }

  // Find the scene.
  SceneState* scene_state = FindScene(scene_token->value);
  if (!scene_state) {
    LOG(ERROR) << "Could not set the renderer's root scene, scene not found: "
                  "scene_token="
               << scene_token;
    DestroyRenderer(renderer_state);
    return;
  }

  // Update the root.
  if (renderer_state->SetRootScene(scene_state, scene_version, *viewport)) {
    ScheduleFrameForRenderer(renderer_state,
                             Scheduler::SchedulingMode::kSnapshot);
  }
}

void CompositorEngine::HitTest(
    RendererState* renderer_state,
    mojo::PointPtr point,
    const mojo::gfx::composition::HitTester::HitTestCallback& callback) {
  DCHECK(IsRendererStateRegisteredDebug(renderer_state));
  DCHECK(point);
  DVLOG(1) << "HitTest: renderer=" << renderer_state << ", point=" << point;

  mojo::gfx::composition::HitTestResultPtr result;
  if (renderer_state->frame()) {
    result =
        renderer_state->frame()->HitTest(SkPoint::Make(point->x, point->y));
  }
  if (!result) {
    result = mojo::gfx::composition::HitTestResult::New();
    result->hits.resize(0u);
  }

  callback.Run(result.Pass());
}

SceneDef* CompositorEngine::ResolveSceneReference(
    mojo::gfx::composition::SceneToken* scene_token) {
  SceneState* scene_state = FindScene(scene_token->value);
  return scene_state ? scene_state->scene_def() : nullptr;
}

void CompositorEngine::SendResourceUnavailable(SceneState* scene_state,
                                               uint32_t resource_id) {
  DCHECK(IsSceneStateRegisteredDebug(scene_state));
  DVLOG(2) << "SendResourceUnavailable: resource_id=" << resource_id;

  // TODO: Detect ANRs
  if (scene_state->scene_listener()) {
    scene_state->scene_listener()->OnResourceUnavailable(
        resource_id, base::Bind(&base::DoNothing));
  }
}

SceneState* CompositorEngine::FindScene(uint32_t scene_token) {
  auto it = scenes_by_token_.find(scene_token);
  return it != scenes_by_token_.end() ? it->second : nullptr;
}

void CompositorEngine::InvalidateScene(SceneState* scene_state) {
  DCHECK(IsSceneStateRegisteredDebug(scene_state));
  DVLOG(2) << "InvalidateScene: scene=" << scene_state;

  for (auto& renderer : renderers_) {
    if (renderer->snapshot() &&
        renderer->snapshot()->InvalidateScene(scene_state->scene_def())) {
      ScheduleFrameForRenderer(renderer, Scheduler::SchedulingMode::kSnapshot);
    }
  }
}

SceneDef::Disposition CompositorEngine::PresentScene(
    SceneState* scene_state,
    int64_t presentation_time) {
  DCHECK(IsSceneStateRegisteredDebug(scene_state));
  DVLOG(2) << "PresentScene: scene=" << scene_state;

  std::ostringstream errs;
  SceneDef::Disposition disposition = scene_state->scene_def()->Present(
      presentation_time, base::Bind(&CompositorEngine::ResolveSceneReference,
                                    base::Unretained(this)),
      base::Bind(&CompositorEngine::SendResourceUnavailable,
                 base::Unretained(this), base::Unretained(scene_state)),
      errs);
  if (disposition == SceneDef::Disposition::kFailed) {
    LOG(ERROR) << "Scene published invalid updates: scene=" << scene_state;
    LOG(ERROR) << errs.str();
    // Caller is responsible for destroying the scene.
  }
  return disposition;
}

void CompositorEngine::PresentRenderer(RendererState* renderer_state,
                                       int64_t presentation_time) {
  DCHECK(IsRendererStateRegisteredDebug(renderer_state));
  DVLOG(2) << "PresentRenderer: renderer_state=" << renderer_state;

  // TODO(jeffbrown): Be more selective and do this work only for scenes
  // associated with the renderer that actually have pending updates.
  std::vector<SceneState*> dead_scenes;
  for (auto& pair : scenes_by_token_) {
    SceneState* scene_state = pair.second;
    SceneDef::Disposition disposition =
        PresentScene(scene_state, presentation_time);
    if (disposition == SceneDef::Disposition::kFailed)
      dead_scenes.push_back(scene_state);
  }
  for (SceneState* scene_state : dead_scenes)
    DestroyScene(scene_state);
}

void CompositorEngine::SnapshotRenderer(
    RendererState* renderer_state,
    const mojo::gfx::composition::FrameInfo& frame_info) {
  DCHECK(IsRendererStateRegisteredDebug(renderer_state));
  DVLOG(2) << "SnapshotRenderer: renderer_state=" << renderer_state;

  if (VLOG_IS_ON(2)) {
    std::ostringstream block_log;
    SnapshotRendererInner(renderer_state, frame_info, &block_log);
    if (!renderer_state->valid()) {
      DVLOG(2) << "Rendering completely blocked: " << block_log.str();
    } else if (!block_log.str().empty()) {
      DVLOG(2) << "Rendering partially blocked: " << block_log.str();
    } else {
      DVLOG(2) << "Rendering unblocked";
    }
  } else {
    SnapshotRendererInner(renderer_state, frame_info, nullptr);
  }
}

void CompositorEngine::SnapshotRendererInner(
    RendererState* renderer_state,
    const mojo::gfx::composition::FrameInfo& frame_info,
    std::ostream* block_log) {
  if (!renderer_state->root_scene()) {
    if (block_log)
      *block_log << "No root scene" << std::endl;
    renderer_state->SetSnapshot(nullptr);
    return;
  }

  SnapshotBuilder builder(block_log);
  renderer_state->SetSnapshot(
      builder.Build(renderer_state->root_scene()->scene_def(),
                    renderer_state->root_scene_viewport(), frame_info));

  if (renderer_state->valid())
    renderer_state->output()->SubmitFrame(renderer_state->frame());
}

void CompositorEngine::ScheduleFrameForRenderer(
    RendererState* renderer_state,
    Scheduler::SchedulingMode scheduling_mode) {
  DCHECK(IsRendererStateRegisteredDebug(renderer_state));
  renderer_state->output()->GetScheduler()->ScheduleFrame(scheduling_mode);
}

void CompositorEngine::OnOutputError(
    const base::WeakPtr<RendererState>& renderer_state_weak) {
  RendererState* renderer_state = renderer_state_weak.get();
  if (!renderer_state)
    return;
  DCHECK(IsRendererStateRegisteredDebug(renderer_state));

  LOG(ERROR) << "Renderer encountered a fatal error: renderer="
             << renderer_state;

  DestroyRenderer(renderer_state);
}

void CompositorEngine::OnOutputUpdateRequest(
    const base::WeakPtr<RendererState>& renderer_state_weak,
    const mojo::gfx::composition::FrameInfo& frame_info) {
  RendererState* renderer_state = renderer_state_weak.get();
  if (!renderer_state)
    return;
  DCHECK(IsRendererStateRegisteredDebug(renderer_state));

  // TODO(jeffbrown): Be more selective and do this work only for scenes
  // associated with the renderer.
  for (auto& pair : scenes_by_token_) {
    pair.second->DispatchSceneFrameCallbacks(frame_info);
  }
}

void CompositorEngine::OnOutputSnapshotRequest(
    const base::WeakPtr<RendererState>& renderer_state_weak,
    const mojo::gfx::composition::FrameInfo& frame_info) {
  RendererState* renderer_state = renderer_state_weak.get();
  if (!renderer_state)
    return;
  DCHECK(IsRendererStateRegisteredDebug(renderer_state));

  PresentRenderer(renderer_state, frame_info.presentation_time);
  SnapshotRenderer(renderer_state, frame_info);
}

void CompositorEngine::OnPresentScene(
    const base::WeakPtr<SceneState>& scene_state_weak,
    int64_t presentation_time) {
  SceneState* scene_state = scene_state_weak.get();
  if (!scene_state)
    return;
  DCHECK(IsSceneStateRegisteredDebug(scene_state));

  SceneDef::Disposition disposition =
      PresentScene(scene_state, presentation_time);
  if (disposition == SceneDef::Disposition::kFailed)
    DestroyScene(scene_state);
  else if (disposition == SceneDef::Disposition::kSucceeded)
    InvalidateScene(scene_state);
}

}  // namespace compositor
