// Copyright 2016 The Cobalt Authors. 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/blitter/hardware_rasterizer.h"

#include <memory>
#include <string>

#include "base/bind.h"
#include "base/threading/thread_checker.h"
#include "base/trace_event/trace_event.h"
#include "cobalt/configuration/configuration.h"
#include "cobalt/render_tree/resource_provider_stub.h"
#include "cobalt/renderer/backend/blitter/graphics_context.h"
#include "cobalt/renderer/backend/blitter/render_target.h"
#include "cobalt/renderer/rasterizer/blitter/cached_software_rasterizer.h"
#include "cobalt/renderer/rasterizer/blitter/render_state.h"
#include "cobalt/renderer/rasterizer/blitter/render_tree_node_visitor.h"
#include "cobalt/renderer/rasterizer/blitter/resource_provider.h"
#include "cobalt/renderer/rasterizer/skia/software_rasterizer.h"

#if defined(ENABLE_DEBUGGER)
#include "cobalt/debug/console/command_manager.h"
#endif

#if SB_API_VERSION < SB_BLITTER_DEPRECATED_VERSION && SB_HAS(BLITTER)

namespace cobalt {
namespace renderer {
namespace rasterizer {
namespace blitter {

class HardwareRasterizer::Impl {
 public:
  Impl(backend::GraphicsContext* graphics_context, int skia_atlas_width,
       int skia_atlas_height, int scratch_surface_size_in_bytes,
       int software_surface_cache_size_in_bytes,
       bool purge_skia_font_caches_on_destruction);
  ~Impl();

  void Submit(const scoped_refptr<render_tree::Node>& render_tree,
              const scoped_refptr<backend::RenderTarget>& render_target,
              const Options& options);

  void SubmitOffscreenToRenderTarget(
      const scoped_refptr<render_tree::Node>& render_tree,
      const scoped_refptr<backend::RenderTarget>& render_target);

  render_tree::ResourceProvider* GetResourceProvider();

 private:
#if defined(ENABLE_DEBUGGER)
  void OnToggleHighlightSoftwareDraws(const std::string& message);
#endif
  void SetupLastFrameSurface(int width, int height);
  THREAD_CHECKER(thread_checker_);

  backend::GraphicsContextBlitter* context_;

  std::unique_ptr<render_tree::ResourceProvider> resource_provider_;

  int64 submit_count_;

  // We maintain a "final results" surface that mirrors the display buffer.
  // This way, we can rerender only the dirty parts of the screen to this
  // |current_frame_| buffer and then blit that to the display.
  SbBlitterSurface current_frame_;

  ScratchSurfaceCache scratch_surface_cache_;

  CachedSoftwareRasterizer software_surface_cache_;
  LinearGradientCache linear_gradient_cache_;

#if defined(ENABLE_DEBUGGER)
  // Debug command to toggle cache highlights to help visualize which nodes
  // are being cached.
  bool toggle_highlight_software_draws_;
  debug::console::ConsoleCommandManager::CommandHandler
      toggle_highlight_software_draws_command_handler_;
#endif
};

HardwareRasterizer::Impl::Impl(backend::GraphicsContext* graphics_context,
                               int skia_atlas_width, int skia_atlas_height,
                               int scratch_surface_size_in_bytes,
                               int software_surface_cache_size_in_bytes,
                               bool purge_skia_font_caches_on_destruction)
    : context_(base::polymorphic_downcast<backend::GraphicsContextBlitter*>(
          graphics_context)),
      submit_count_(0),
      current_frame_(kSbBlitterInvalidSurface),
      scratch_surface_cache_(context_->GetSbBlitterDevice(),
                             context_->GetSbBlitterContext(),
                             scratch_surface_size_in_bytes),
      software_surface_cache_(context_->GetSbBlitterDevice(),
                              context_->GetSbBlitterContext(),
                              software_surface_cache_size_in_bytes,
                              purge_skia_font_caches_on_destruction)
#if defined(ENABLE_DEBUGGER)
      ,
      toggle_highlight_software_draws_(false),
      toggle_highlight_software_draws_command_handler_(
          "toggle_highlight_software_draws",
          base::Bind(&HardwareRasterizer::Impl::OnToggleHighlightSoftwareDraws,
                     base::Unretained(this)),
          "Highlights regions where software rasterization is occurring.",
          "Toggles whether all software rasterized elements will appear as a "
          "green rectangle or not.  This can be used to identify where in a "
          "scene software rasterization is occurring.")
#endif  // defined(ENABLE_DEBUGGER)
{
  resource_provider_ =
      std::unique_ptr<render_tree::ResourceProvider>(new ResourceProvider(
          context_->GetSbBlitterDevice(),
          software_surface_cache_.GetResourceProvider(),
          base::Bind(&HardwareRasterizer::Impl::SubmitOffscreenToRenderTarget,
                     base::Unretained(this))));
}

HardwareRasterizer::Impl::~Impl() {
  if (SbBlitterIsSurfaceValid(current_frame_)) {
    SbBlitterDestroySurface(current_frame_);
  }
}

#if defined(ENABLE_DEBUGGER)
void HardwareRasterizer::Impl::OnToggleHighlightSoftwareDraws(
    const std::string& message) {
  SB_UNREFERENCED_PARAMETER(message);
  toggle_highlight_software_draws_ = !toggle_highlight_software_draws_;
}
#endif

void HardwareRasterizer::Impl::Submit(
    const scoped_refptr<render_tree::Node>& render_tree,
    const scoped_refptr<backend::RenderTarget>& render_target,
    const Options& options) {
  TRACE_EVENT0("cobalt::renderer", "Rasterizer::Submit()");
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);

  int width = render_target->GetSize().width();
  int height = render_target->GetSize().height();

  SbBlitterContext context = context_->GetSbBlitterContext();

  backend::RenderTargetBlitter* render_target_blitter =
      base::polymorphic_downcast<backend::RenderTargetBlitter*>(
          render_target.get());

  if (configuration::Configuration::GetInstance()
          ->CobaltRenderDirtyRegionOnly()) {
    if (!SbBlitterIsSurfaceValid(current_frame_)) {
      SetupLastFrameSurface(width, height);
    }
  }

  SbBlitterRenderTarget visitor_render_target = kSbBlitterInvalidRenderTarget;
  if (SbBlitterIsSurfaceValid(current_frame_)) {
    visitor_render_target = SbBlitterGetRenderTargetFromSurface(current_frame_);
  } else {
    visitor_render_target = render_target_blitter->GetSbRenderTarget();
  }
  CHECK(SbBlitterSetRenderTarget(context, visitor_render_target));

  software_surface_cache_.OnStartNewFrame();

  // Clear the background before proceeding if the clear option is set.
  // We also clear if this is one of the first 3 submits.  This is for security
  // purposes, so that despite the Blitter API implementation, we ensure that
  // if the output buffer is not completely rendered to, data from a previous
  // process cannot leak in.
  bool cleared = false;
  if (options.flags & Rasterizer::kSubmitFlags_Clear || submit_count_ < 3) {
    cleared = true;
    CHECK(SbBlitterSetBlending(context, false));
    CHECK(SbBlitterSetColor(context, SbBlitterColorFromRGBA(0, 0, 0, 0)));
    CHECK(SbBlitterFillRect(context, SbBlitterMakeRect(0, 0, width, height)));
  }

  {
    TRACE_EVENT0("cobalt::renderer", "VisitRenderTree");

    // Visit the render tree with our Blitter API visitor.
    BoundsStack start_bounds(context_->GetSbBlitterContext(),
                             math::Rect(render_target_blitter->GetSize()));

    if (SbBlitterIsSurfaceValid(current_frame_) && options.dirty && !cleared) {
      // If a dirty rectangle was specified, limit our redrawing to within it.
      start_bounds.Push(*options.dirty);
    }

    RenderState initial_render_state(visitor_render_target, Transform(),
                                     start_bounds);

#if defined(ENABLE_DEBUGGER)
    initial_render_state.highlight_software_draws =
        toggle_highlight_software_draws_;
#endif  // defined(ENABLE_DEBUGGER)
    RenderTreeNodeVisitor visitor(
        context_->GetSbBlitterDevice(), context_->GetSbBlitterContext(),
        initial_render_state, &scratch_surface_cache_, &software_surface_cache_,
        &linear_gradient_cache_);
    render_tree->Accept(&visitor);
  }

  if (SbBlitterIsSurfaceValid(current_frame_)) {
    // Finally flip the surface to make visible the rendered results.
    CHECK(SbBlitterSetRenderTarget(context,
                                   render_target_blitter->GetSbRenderTarget()));
    CHECK(SbBlitterSetBlending(context, false));
    CHECK(SbBlitterSetModulateBlitsWithColor(context, false));
    CHECK(SbBlitterBlitRectToRect(context, current_frame_,
                                  SbBlitterMakeRect(0, 0, width, height),
                                  SbBlitterMakeRect(0, 0, width, height)));
  }

  CHECK(SbBlitterFlushContext(context));
  render_target_blitter->Flip();

  ++submit_count_;
}

void HardwareRasterizer::Impl::SubmitOffscreenToRenderTarget(
    const scoped_refptr<render_tree::Node>& render_tree,
    const scoped_refptr<backend::RenderTarget>& render_target) {
  TRACE_EVENT0("cobalt::renderer",
               "Rasterizer::SubmitOffscreenToRenderTarget()");
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);

  SbBlitterContext context = context_->GetSbBlitterContext();

  backend::RenderTargetBlitter* render_target_blitter =
      base::polymorphic_downcast<backend::RenderTargetBlitter*>(
          render_target.get());

  SbBlitterRenderTarget visitor_render_target =
      render_target_blitter->GetSbRenderTarget();
  CHECK(SbBlitterSetRenderTarget(context, visitor_render_target));

  math::Size size(render_target_blitter->GetSize());
  BoundsStack start_bounds(context, math::Rect(size));

  RenderState initial_render_state(visitor_render_target, Transform(),
                                   start_bounds);

  CHECK(SbBlitterSetBlending(context, false));
  CHECK(SbBlitterSetColor(context, SbBlitterColorFromRGBA(0, 0, 0, 0)));
  CHECK(SbBlitterFillRect(
      context, SbBlitterMakeRect(0, 0, size.width(), size.height())));

  RenderTreeNodeVisitor visitor(context_->GetSbBlitterDevice(), context,
                                initial_render_state, &scratch_surface_cache_,
                                &software_surface_cache_,
                                &linear_gradient_cache_);
  render_tree->Accept(&visitor);

  CHECK(SbBlitterFlushContext(context));
}

render_tree::ResourceProvider* HardwareRasterizer::Impl::GetResourceProvider() {
  return resource_provider_.get();
}

void HardwareRasterizer::Impl::SetupLastFrameSurface(int width, int height) {
  current_frame_ =
      SbBlitterCreateRenderTargetSurface(context_->GetSbBlitterDevice(), width,
                                         height, kSbBlitterSurfaceFormatRGBA8);
}

HardwareRasterizer::HardwareRasterizer(
    backend::GraphicsContext* graphics_context, int skia_atlas_width,
    int skia_atlas_height, int scratch_surface_size_in_bytes,
    int software_surface_cache_size_in_bytes,
    bool purge_skia_font_caches_on_destruction)
    : impl_(new Impl(graphics_context, skia_atlas_width, skia_atlas_height,
                     scratch_surface_size_in_bytes,
                     software_surface_cache_size_in_bytes,
                     purge_skia_font_caches_on_destruction)) {}

HardwareRasterizer::~HardwareRasterizer() {}

void HardwareRasterizer::Submit(
    const scoped_refptr<render_tree::Node>& render_tree,
    const scoped_refptr<backend::RenderTarget>& render_target,
    const Options& options) {
  return impl_->Submit(render_tree, render_target, options);
}

render_tree::ResourceProvider* HardwareRasterizer::GetResourceProvider() {
  return impl_->GetResourceProvider();
}

}  // namespace blitter
}  // namespace rasterizer
}  // namespace renderer
}  // namespace cobalt

#endif  // SB_API_VERSION < SB_BLITTER_DEPRECATED_VERSION && SB_HAS(BLITTER)
