// 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 &&
        last_draw.draw_object->TryMerge(draw_object.get())) {
      last_draw.draw_bounds.Union(draw_bounds);
      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 &&
        last_draw.draw_object->TryMerge(draw_object.get())) {
      last_draw.draw_bounds.Union(draw_bounds);
      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_);

  // 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) {
        graphics_state->DisableBlend();
      } else if (draw->blend_type == kBlendSrcAlpha) {
        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(const 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[draw_pos];
    bool draw_uses_native_rasterizer = draw->blend_type != kBlendExternal;
    bool next_uses_native_rasterizer = draw_pos + 1 < draw_list.size() &&
        draw_list[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(const 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[draw_pos];
    bool draw_uses_native_rasterizer = draw->blend_type != kBlendExternal;
    bool next_uses_native_rasterizer = draw_pos + 1 < draw_list.size() &&
        draw_list[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);
  }
}

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