// Copyright 2017 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "cobalt/renderer/rasterizer/egl/draw_object_manager.h"

#include <algorithm>

#include "base/debug/trace_event.h"
#include "base/logging.h"

namespace cobalt {
namespace renderer {
namespace rasterizer {
namespace egl {

DrawObjectManager::DrawObjectManager(
    const base::Closure& reset_external_rasterizer,
    const base::Closure& flush_external_offscreen_draws)
    : reset_external_rasterizer_(reset_external_rasterizer),
      flush_external_offscreen_draws_(flush_external_offscreen_draws),
      current_draw_id_(0) {}

uint32_t DrawObjectManager::AddBatchedExternalDraw(
    scoped_ptr<DrawObject> draw_object, base::TypeId draw_type,
    const backend::RenderTarget* render_target,
    const math::RectF& draw_bounds) {
  external_offscreen_draws_.emplace_back(draw_object.Pass(), draw_type,
      kBlendExternal, render_target, draw_bounds, ++current_draw_id_);
  return current_draw_id_;
}

uint32_t DrawObjectManager::AddOnscreenDraw(scoped_ptr<DrawObject> draw_object,
    BlendType blend_type, base::TypeId draw_type,
    const backend::RenderTarget* render_target,
    const math::RectF& draw_bounds) {
  // See if this draw object can be merged with the last one.
  if (!onscreen_draws_.empty()) {
    DrawInfo& last_draw = onscreen_draws_.back();
    if (last_draw.render_target == render_target &&
        last_draw.draw_type == draw_type &&
        (last_draw.blend_type & blend_type) != 0 &&
        last_draw.draw_object->TryMerge(draw_object.get())) {
      last_draw.draw_bounds.Union(draw_bounds);
      last_draw.blend_type =
          static_cast<BlendType>(last_draw.blend_type & blend_type);
      last_draw.draw_id = ++current_draw_id_;
      return current_draw_id_;
    }
  }

  onscreen_draws_.emplace_back(draw_object.Pass(), draw_type, blend_type,
      render_target, draw_bounds, ++current_draw_id_);
  return current_draw_id_;
}

uint32_t DrawObjectManager::AddOffscreenDraw(scoped_ptr<DrawObject> draw_object,
    BlendType blend_type, base::TypeId draw_type,
    const backend::RenderTarget* render_target,
    const math::RectF& draw_bounds) {
  // See if this draw object can be merged with the last one.
  if (!offscreen_draws_.empty()) {
    DrawInfo& last_draw = offscreen_draws_.back();
    if (last_draw.render_target == render_target &&
        last_draw.draw_type == draw_type &&
        (last_draw.blend_type & blend_type) != 0 &&
        last_draw.draw_object->TryMerge(draw_object.get())) {
      last_draw.draw_bounds.Union(draw_bounds);
      last_draw.blend_type =
          static_cast<BlendType>(last_draw.blend_type & blend_type);
      last_draw.draw_id = ++current_draw_id_;
      return current_draw_id_;
    }
  }

  offscreen_draws_.emplace_back(draw_object.Pass(), draw_type, blend_type,
      render_target, draw_bounds, ++current_draw_id_);
  return current_draw_id_;
}

void DrawObjectManager::RemoveDraws(uint32_t last_valid_draw_id) {
  TRACE_EVENT0("cobalt::renderer", "RemoveDraws");
  RemoveDraws(&onscreen_draws_, last_valid_draw_id);
  RemoveDraws(&offscreen_draws_, last_valid_draw_id);
  RemoveDraws(&external_offscreen_draws_, last_valid_draw_id);
}

void DrawObjectManager::RemoveDraws(DrawList* draw_list,
    uint32_t last_valid_draw_id) {
  // Objects in the draw list should have ascending draw IDs at this point.
  auto iter = draw_list->end();
  for (; iter != draw_list->begin(); --iter) {
    if ((iter - 1)->draw_id <= last_valid_draw_id) {
      break;
    }
  }
  if (iter != draw_list->end()) {
    draw_list->erase(iter, draw_list->end());
  }
}

void DrawObjectManager::AddRenderTargetDependency(
    const backend::RenderTarget* draw_target,
    const backend::RenderTarget* required_target) {
  // Check for circular dependencies.
  DCHECK(draw_target != required_target);

  // There should be very few unique render target dependencies, so just keep
  // them in a vector for simplicity.
  for (auto dep = draw_dependencies_.begin();; ++dep) {
    if (dep == draw_dependencies_.end()) {
      draw_dependencies_.emplace_back(draw_target, required_target);
      auto count = dependency_count_.find(draw_target->GetSerialNumber());
      if (count != dependency_count_.end()) {
        count->second += 1;
      } else {
        dependency_count_.emplace(draw_target->GetSerialNumber(), 1);
      }
      break;
    }
    if (dep->draw_target == draw_target &&
        dep->required_target == required_target) {
      return;
    }
  }

  // Propagate dependencies upward so that targets which depend on
  // |draw_target| will also depend on |required_target|.
  size_t count = draw_dependencies_.size();
  for (size_t index = 0; index < count; ++index) {
    if (draw_dependencies_[index].required_target == draw_target) {
      AddRenderTargetDependency(draw_dependencies_[index].draw_target,
                                required_target);
    }
  }
}

void DrawObjectManager::ExecuteOffscreenRasterize(GraphicsState* graphics_state,
    ShaderProgramManager* program_manager) {
  SortOffscreenDraws(&external_offscreen_draws_,
                     &sorted_external_offscreen_draws_);

  // Process draws handled by an external rasterizer.
  {
    TRACE_EVENT0("cobalt::renderer", "OffscreenExternalRasterizer");
    for (const DrawInfo* draw : sorted_external_offscreen_draws_) {
      // Batched external draws should not have any dependencies.
      DCHECK_EQ(draw->dependencies, 0);
      draw->draw_object->ExecuteRasterize(graphics_state, program_manager);
    }
    if (!flush_external_offscreen_draws_.is_null()) {
      flush_external_offscreen_draws_.Run();
    }
  }

  SortOffscreenDraws(&offscreen_draws_, &sorted_offscreen_draws_);
  SortOnscreenDraws(&onscreen_draws_, &sorted_onscreen_draws_);
  MergeSortedDraws(&sorted_offscreen_draws_);
  MergeSortedDraws(&sorted_onscreen_draws_);

  // Update the vertex buffer for all draws.
  {
    TRACE_EVENT0("cobalt::renderer", "UpdateVertexBuffer");
    ExecuteUpdateVertexBuffer(graphics_state, program_manager);
  }

  // Process the native offscreen draws.
  {
    TRACE_EVENT0("cobalt::renderer", "OffscreenNativeRasterizer");
    Rasterize(sorted_offscreen_draws_, graphics_state, program_manager);
  }
}

void DrawObjectManager::ExecuteUpdateVertexBuffer(
    GraphicsState* graphics_state, ShaderProgramManager* program_manager) {
  for (const DrawInfo* draw : sorted_offscreen_draws_) {
    draw->draw_object->ExecuteUpdateVertexBuffer(
        graphics_state, program_manager);
  }
  for (const DrawInfo* draw : sorted_onscreen_draws_) {
    draw->draw_object->ExecuteUpdateVertexBuffer(
        graphics_state, program_manager);
  }
  graphics_state->UpdateVertexBuffers();
}

void DrawObjectManager::ExecuteOnscreenRasterize(GraphicsState* graphics_state,
    ShaderProgramManager* program_manager) {
  Rasterize(sorted_onscreen_draws_, graphics_state, program_manager);
}

void DrawObjectManager::Rasterize(const SortedDrawList& sorted_draw_list,
    GraphicsState* graphics_state, ShaderProgramManager* program_manager) {
  const backend::RenderTarget* current_target = nullptr;
  bool using_native_rasterizer = true;

  // Starting from an unknown state.
  graphics_state->SetDirty();

  for (const DrawInfo* draw : sorted_draw_list) {
    bool draw_uses_native_rasterizer = draw->blend_type != kBlendExternal;

    if (draw_uses_native_rasterizer) {
      if (!using_native_rasterizer) {
        // Transitioning from external to native rasterizer. Set the native
        // rasterizer's state as dirty.
        graphics_state->SetDirty();
      }

      if (draw->render_target != current_target) {
        current_target = draw->render_target;
        graphics_state->BindFramebuffer(current_target);
        graphics_state->Viewport(0, 0,
                                 current_target->GetSize().width(),
                                 current_target->GetSize().height());
      }

      if ((draw->blend_type & kBlendNone) != 0) {
        graphics_state->DisableBlend();
      } else if ((draw->blend_type & kBlendSrcAlpha) != 0) {
        graphics_state->EnableBlend();
      } else {
        NOTREACHED() << "Unsupported blend type";
      }
    } else {
      if (using_native_rasterizer) {
        // Transitioning from native to external rasterizer. Set the external
        // rasterizer's state as dirty.
        if (!reset_external_rasterizer_.is_null()) {
          reset_external_rasterizer_.Run();
        }
      }
    }

    draw->draw_object->ExecuteRasterize(graphics_state, program_manager);
    using_native_rasterizer = draw_uses_native_rasterizer;
  }
}

void DrawObjectManager::SortOffscreenDraws(DrawList* draw_list,
    SortedDrawList* sorted_draw_list) {
  TRACE_EVENT0("cobalt::renderer", "SortOffscreenDraws");

  // Sort offscreen draws to minimize GPU state changes.
  sorted_draw_list->reserve(draw_list->size());
  for (size_t draw_pos = 0; draw_pos < draw_list->size(); ++draw_pos) {
    auto* draw = &draw_list->at(draw_pos);
    bool draw_uses_native_rasterizer = draw->blend_type != kBlendExternal;
    bool next_uses_native_rasterizer = draw_pos + 1 < draw_list->size() &&
        draw_list->at(draw_pos + 1).blend_type != kBlendExternal;
    auto dependencies =
        dependency_count_.find(draw->render_target->GetSerialNumber());
    draw->dependencies =
        dependencies != dependency_count_.end() ? dependencies->second : 0;

    // Find an appropriate sort position for the current draw.
    auto sort_pos = draw_pos;
    for (; sort_pos > 0; --sort_pos) {
      auto* prev_draw = sorted_draw_list->at(sort_pos - 1);

      // Unlike onscreen draws, offscreen draws should be grouped by render
      // target. Ensure that render targets with fewer dependencies are first
      // in the draw list.
      if (prev_draw->dependencies > draw->dependencies) {
        continue;
      } else if (prev_draw->dependencies < draw->dependencies) {
        break;
      }
      if (prev_draw->render_target > draw->render_target) {
        continue;
      } else if (prev_draw->render_target < draw->render_target) {
        break;
      }

      // The rest of the sorting logic is the same between onscreen and
      // offscreen draws.
      if (prev_draw->draw_bounds.Intersects(draw->draw_bounds)) {
        break;
      }

      // Group native vs. non-native draws together.
      bool prev_uses_native_rasterizer =
          prev_draw->blend_type != kBlendExternal;
      if (draw_uses_native_rasterizer != next_uses_native_rasterizer &&
          draw_uses_native_rasterizer != prev_uses_native_rasterizer) {
        next_uses_native_rasterizer = prev_uses_native_rasterizer;
        continue;
      }
      if (draw_uses_native_rasterizer == next_uses_native_rasterizer &&
          draw_uses_native_rasterizer != prev_uses_native_rasterizer) {
        break;
      }
      next_uses_native_rasterizer = prev_uses_native_rasterizer;

      if (prev_draw->draw_type > draw->draw_type) {
        continue;
      } else if (prev_draw->draw_type < draw->draw_type) {
        break;
      }

      if (prev_draw->blend_type <= draw->blend_type) {
        break;
      }
    }

    sorted_draw_list->insert(sorted_draw_list->begin() + sort_pos, draw);
  }
}

void DrawObjectManager::SortOnscreenDraws(DrawList* draw_list,
    SortedDrawList* sorted_draw_list) {
  TRACE_EVENT0("cobalt::renderer", "SortOnscreenDraws");

  // Sort onscreen draws to minimize GPU state changes.
  sorted_draw_list->reserve(draw_list->size());
  for (size_t draw_pos = 0; draw_pos < draw_list->size(); ++draw_pos) {
    auto* draw = &draw_list->at(draw_pos);
    bool draw_uses_native_rasterizer = draw->blend_type != kBlendExternal;
    bool next_uses_native_rasterizer = draw_pos + 1 < draw_list->size() &&
        draw_list->at(draw_pos + 1).blend_type != kBlendExternal;

    // Find an appropriate sort position for the current draw.
    auto sort_pos = draw_pos;
    for (; sort_pos > 0; --sort_pos) {
      auto* prev_draw = sorted_draw_list->at(sort_pos - 1);

      // Do not sort across different render targets since their contents may
      // be generated just before consumed by a subsequent draw.
      if (prev_draw->render_target != draw->render_target) {
        break;
      }

      // The rest of the sorting logic is the same between onscreen and
      // offscreen draws.
      if (prev_draw->draw_bounds.Intersects(draw->draw_bounds)) {
        break;
      }

      // Group native vs. non-native draws together.
      bool prev_uses_native_rasterizer =
          prev_draw->blend_type != kBlendExternal;
      if (draw_uses_native_rasterizer != next_uses_native_rasterizer &&
          draw_uses_native_rasterizer != prev_uses_native_rasterizer) {
        next_uses_native_rasterizer = prev_uses_native_rasterizer;
        continue;
      }
      if (draw_uses_native_rasterizer == next_uses_native_rasterizer &&
          draw_uses_native_rasterizer != prev_uses_native_rasterizer) {
        break;
      }
      next_uses_native_rasterizer = prev_uses_native_rasterizer;

      if (prev_draw->draw_type > draw->draw_type) {
        continue;
      } else if (prev_draw->draw_type < draw->draw_type) {
        break;
      }

      if (prev_draw->blend_type <= draw->blend_type) {
        break;
      }
    }

    sorted_draw_list->insert(sorted_draw_list->begin() + sort_pos, draw);
  }
}

void DrawObjectManager::MergeSortedDraws(SortedDrawList* sorted_draw_list) {
  if (sorted_draw_list->size() <= 1) {
    return;
  }

  SortedDrawList old_draw_list(std::move(*sorted_draw_list));
  sorted_draw_list->clear();
  sorted_draw_list->reserve(old_draw_list.size());

  sorted_draw_list->emplace_back(old_draw_list[0]);
  for (size_t i = 1; i < old_draw_list.size(); ++i) {
    DrawInfo* last_draw = sorted_draw_list->back();
    DrawInfo* next_draw = old_draw_list[i];
    if (last_draw->render_target == next_draw->render_target &&
        last_draw->draw_type == next_draw->draw_type &&
        (last_draw->blend_type & next_draw->blend_type) != 0 &&
        last_draw->draw_object->TryMerge(next_draw->draw_object.get())) {
      last_draw->blend_type =
          static_cast<BlendType>(last_draw->blend_type & next_draw->blend_type);
    } else {
      sorted_draw_list->emplace_back(next_draw);
    }
  }
}

}  // namespace egl
}  // namespace rasterizer
}  // namespace renderer
}  // namespace cobalt
