// 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 <memory>

#include "cobalt/renderer/rasterizer/blitter/render_tree_node_visitor.h"

#include "base/bind.h"
#include "base/trace_event/trace_event.h"
#include "cobalt/base/polymorphic_downcast.h"
#include "cobalt/math/matrix3_f.h"
#include "cobalt/math/rect.h"
#include "cobalt/math/rect_f.h"
#include "cobalt/math/size.h"
#include "cobalt/math/transform_2d.h"
#include "cobalt/math/vector2d_f.h"
#include "cobalt/renderer/rasterizer/blitter/cobalt_blitter_conversions.h"
#include "cobalt/renderer/rasterizer/blitter/image.h"
#include "cobalt/renderer/rasterizer/blitter/linear_gradient.h"
#include "cobalt/renderer/rasterizer/blitter/skia_blitter_conversions.h"
#include "cobalt/renderer/rasterizer/common/offscreen_render_coordinate_mapping.h"
#include "cobalt/renderer/rasterizer/common/utils.h"
#include "starboard/blitter.h"

#if SB_HAS(BLITTER)

// This define exists so that developers can quickly toggle it temporarily and
// obtain trace results for the render tree visit process here.  In general
// though it slows down tracing too much to leave it enabled.
#define ENABLE_RENDER_TREE_VISITOR_TRACING 0

#if ENABLE_RENDER_TREE_VISITOR_TRACING
#define TRACE_EVENT0_IF_ENABLED(x) TRACE_EVENT0("cobalt::renderer", x)
#else
#define TRACE_EVENT0_IF_ENABLED(x)
#endif

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

using common::utils::IsOpaque;
using common::utils::IsTransparent;
using math::Matrix3F;
using math::Rect;
using math::RectF;
using math::Size;
using math::Vector2dF;
using render_tree::Border;
using render_tree::Brush;
using render_tree::ColorRGBA;
using render_tree::ColorStop;
using render_tree::ColorStopList;
using render_tree::LinearGradientBrush;
using render_tree::SolidColorBrush;
using render_tree::ViewportFilter;

RenderTreeNodeVisitor::RenderTreeNodeVisitor(
    SbBlitterDevice device, SbBlitterContext context,
    const RenderState& render_state, ScratchSurfaceCache* scratch_surface_cache,
    CachedSoftwareRasterizer* software_surface_cache,
    LinearGradientCache* linear_gradient_cache)
    : device_(device),
      context_(context),
      render_state_(render_state),
      scratch_surface_cache_(scratch_surface_cache),
      software_surface_cache_(software_surface_cache),
      linear_gradient_cache_(linear_gradient_cache) {}

namespace {
void DrawClearRect(SbBlitterContext context, SbBlitterRect rect,
                   SbBlitterColor color) {
  SbBlitterSetColor(context, color);
  SbBlitterSetBlending(context, false);
  SbBlitterFillRect(context, rect);
}

SbBlitterColor RenderTreeToBlitterColor(const ColorRGBA& color) {
  return SbBlitterColorFromRGBA(color.r() * 255, color.g() * 255,
                                color.b() * 255, color.a() * 255);
}
}  // namespace

void RenderTreeNodeVisitor::Visit(render_tree::ClearRectNode* clear_rect_node) {
  TRACE_EVENT0_IF_ENABLED("Visit(ClearRectNode)");
  SbBlitterRect blitter_rect = RectFToBlitterRect(
      render_state_.transform.TransformRect(clear_rect_node->data().rect));

  DrawClearRect(context_, blitter_rect,
                RenderTreeToBlitterColor(clear_rect_node->data().color));
}

void RenderTreeNodeVisitor::Visit(
    render_tree::CompositionNode* composition_node) {
  TRACE_EVENT0_IF_ENABLED("Visit(CompositionNode)");

  const render_tree::CompositionNode::Children& children =
      composition_node->data().children();

  if (children.empty()) {
    return;
  }

  render_state_.transform.ApplyOffset(composition_node->data().offset());
  for (render_tree::CompositionNode::Children::const_iterator iter =
           children.begin();
       iter != children.end(); ++iter) {
    if (render_state_.transform.TransformRect((*iter)->GetBounds())
            .Intersects(RectF(render_state_.bounds_stack.Top()))) {
      (*iter)->Accept(this);
    }
  }
  render_state_.transform.ApplyOffset(-composition_node->data().offset());
}

void RenderTreeNodeVisitor::Visit(render_tree::FilterNode* filter_node) {
  TRACE_EVENT0_IF_ENABLED("Visit(FilterNode)");

  if (filter_node->data().blur_filter) {
    // The Starboard Blitter API does not support blur filters, so we fallback
    // to software for this.
    RenderWithSoftwareRenderer(filter_node);
    return;
  }

  render_tree::Node* source = filter_node->data().source.get();

  // Will be made active if a viewport filter is set.
  base::Optional<BoundsStack::ScopedPush> scoped_push;

  if (filter_node->data().viewport_filter) {
    const ViewportFilter& viewport_filter =
        *filter_node->data().viewport_filter;

    if (viewport_filter.has_rounded_corners()) {
      RenderWithSoftwareRenderer(filter_node);
      return;
    }

    scoped_push.emplace(
        &render_state_.bounds_stack,
        cobalt::math::Rect::RoundFromRectF(
            render_state_.transform.TransformRect(viewport_filter.viewport())));
  }

  if (!filter_node->data().opacity_filter ||
      IsOpaque(filter_node->data().opacity_filter->opacity())) {
    source->Accept(this);
  } else if (!IsTransparent(filter_node->data().opacity_filter->opacity())) {
    // If the opacity is set to 0, the contents are invisible and we are
    // trivially done.  However, if we made it into this branch, then
    // we know that opacity is in the range (0, 1), exclusive.
    float opacity = filter_node->data().opacity_filter->opacity();

    if (common::utils::NodeCanRenderWithOpacity(source)) {
      float original_opacity = render_state_.opacity;
      render_state_.opacity *= opacity;

      source->Accept(this);

      render_state_.opacity = original_opacity;
      return;
    }

    // Render our source subtree to an offscreen surface, and then we will
    // re-render it to our main render target with an alpha value applied to it.
    std::unique_ptr<OffscreenRender> offscreen_render =
        RenderToOffscreenSurface(source);
    if (!offscreen_render) {
      // This can happen if the output area of the source node is 0, in which
      // case we're trivially done.
      return;
    }

    SbBlitterSurface offscreen_surface =
        offscreen_render->scratch_surface->GetSurface();

    // Now blit our offscreen surface to our main render target with opacity
    // applied.
    SbBlitterSetBlending(context_, true);
    SbBlitterSetModulateBlitsWithColor(context_, true);
    SbBlitterSetColor(
        context_,
        SbBlitterColorFromRGBA(255, 255, 255, static_cast<int>(255 * opacity)));
    SbBlitterBlitRectToRect(
        context_, offscreen_surface,
        SbBlitterMakeRect(0, 0, offscreen_render->destination_rect.width(),
                          offscreen_render->destination_rect.height()),
        RectFToBlitterRect(offscreen_render->destination_rect));
  }
}

void RenderTreeNodeVisitor::Visit(render_tree::ImageNode* image_node) {
  TRACE_EVENT0_IF_ENABLED("Visit(ImageNode)");
  // The image_node may contain nothing. For example, when it represents a video
  // or other kind of animated image element before any frame is decoded.
  if (!image_node->data().source) {
    return;
  }

  // All Blitter API images derive from skia::Image (so that they can be
  // compatible with the Skia software renderer), so we start here by casting
  // to skia::Image.
  skia::Image* skia_image =
      base::polymorphic_downcast<skia::Image*>(image_node->data().source.get());
  const Size& image_size = skia_image->GetSize();

  if (skia_image->GetTypeId() == base::GetTypeId<skia::MultiPlaneImage>()) {
    // Let software Skia deal with multiplane (e.g. YUV) image rendering.
    RenderWithSoftwareRenderer(image_node);
    return;
  }

  const Matrix3F& local_matrix = image_node->data().local_transform;
  if (local_matrix.Get(1, 0) != 0 || local_matrix.Get(0, 1) != 0) {
    // The Starboard Blitter API does not support local texture transforms that
    // involve rotations or shears, so we must fallback to software to perform
    // these.
    RenderWithSoftwareRenderer(image_node);
    return;
  }

  // All single-plane images are guaranteed to be of type SinglePlaneImage.
  SinglePlaneImage* blitter_image =
      base::polymorphic_downcast<SinglePlaneImage*>(skia_image);

  // Ensure any required backend processing is done to create the necessary
  // GPU resource.
  if (blitter_image->EnsureInitialized()) {
    // Restore the original render target, since it is possible that rendering
    // took place to another render target in this call.
    SbBlitterSetRenderTarget(context_, render_state_.render_target);
  }

  // Apply the local image coordinate transform to the source rectangle.  Note
  // that the render tree local transform matrix is normalized, but the Blitter
  // API source rectangle is specified in pixel units, so we must multiply the
  // offset by |image_size| in order to get the correct values.
  Transform local_transform;
  local_transform.ApplyScale(
      Vector2dF(1.0f / local_matrix.Get(0, 0), 1.0f / local_matrix.Get(1, 1)));
  local_transform.ApplyOffset(
      Vector2dF(-local_matrix.Get(0, 2) * image_size.width(),
                -local_matrix.Get(1, 2) * image_size.height()));

  // Render the image.
  if (!IsOpaque(render_state_.opacity)) {
    SbBlitterSetBlending(context_, true);
    SbBlitterSetModulateBlitsWithColor(context_, true);
    SbBlitterSetColor(
        context_,
        SbBlitterColorFromRGBA(255, 255, 255,
                               static_cast<int>(255 * render_state_.opacity)));
  } else {
    SbBlitterSetBlending(context_, !skia_image->IsOpaque());
    SbBlitterSetModulateBlitsWithColor(context_, false);
  }

  SbBlitterBlitRectToRectTiled(
      context_, blitter_image->surface(),
      RectFToBlitterRect(local_transform.TransformRect(RectF(image_size))),
      RectFToBlitterRect(render_state_.transform.TransformRect(
          image_node->data().destination_rect)));
}

void RenderTreeNodeVisitor::Visit(
    render_tree::MatrixTransform3DNode* matrix_transform_3d_node) {
  TRACE_EVENT0_IF_ENABLED("Visit(MatrixTransform3DNode)");
  // Ignore the 3D transform matrix, it cannot be implemented within the Blitter
  // API.
  matrix_transform_3d_node->data().source->Accept(this);
}

void RenderTreeNodeVisitor::Visit(
    render_tree::MatrixTransformNode* matrix_transform_node) {
  TRACE_EVENT0_IF_ENABLED("Visit(MatrixTransformNode)");

  const Matrix3F& transform = matrix_transform_node->data().transform;

  if (transform.Get(1, 0) != 0 || transform.Get(0, 1) != 0 ||
      transform.Get(0, 0) < 0 || transform.Get(1, 1) < 0) {
    // The Starboard Blitter API does not support rotations/shears/flips, so we
    // must fallback to software in order to render the entire subtree.
    RenderWithSoftwareRenderer(matrix_transform_node);
    return;
  }

  Transform old_transform(render_state_.transform);

  render_state_.transform.ApplyOffset(
      Vector2dF(transform.Get(0, 2), transform.Get(1, 2)));
  render_state_.transform.ApplyScale(
      Vector2dF(transform.Get(0, 0), transform.Get(1, 1)));

  matrix_transform_node->data().source->Accept(this);

  render_state_.transform = old_transform;
}

void RenderTreeNodeVisitor::Visit(
    render_tree::PunchThroughVideoNode* punch_through_video_node) {
  TRACE_EVENT0_IF_ENABLED("Visit(PunchThroughVideoNode)");

  SbBlitterRect blitter_rect =
      RectFToBlitterRect(render_state_.transform.TransformRect(
          punch_through_video_node->data().rect));

  punch_through_video_node->data().set_bounds_cb.Run(math::Rect(
      blitter_rect.x, blitter_rect.y, blitter_rect.width, blitter_rect.height));

  DrawClearRect(context_, blitter_rect, SbBlitterColorFromRGBA(0, 0, 0, 0));
}

namespace {
bool AllBorderSidesHaveSameColorAndStyle(const Border& border) {
  return border.left.style == border.right.style &&
         border.left.style == border.top.style &&
         border.left.style == border.bottom.style &&
         border.left.color == border.right.color &&
         border.left.color == border.top.color &&
         border.left.color == border.bottom.color;
}

void RenderRectNodeBorder(SbBlitterContext context, ColorRGBA color, float left,
                          float right, float top, float bottom,
                          const RectF& rect) {
  SbBlitterColor blitter_color = RenderTreeToBlitterColor(color);
  SbBlitterSetColor(context, blitter_color);
  SbBlitterSetBlending(context, !IsOpaque(color.a()));

  // We draw four rectangles, one for each border edge.  They have the following
  // layout:
  //
  //  -------------
  //  | |   T     |
  //  | |---------|
  //  | |       | |
  //  |L|       |R|
  //  | |       | |
  //  |---------| |
  //  |     B   | |
  //  -------------

  // Left
  SbBlitterFillRect(context, RectFToBlitterRect(RectF(rect.x(), rect.y(), left,
                                                      rect.height() - bottom)));
  // Bottom
  SbBlitterFillRect(context,
                    RectFToBlitterRect(RectF(rect.x(), rect.bottom() - bottom,
                                             rect.width() - right, bottom)));
  // Right
  SbBlitterFillRect(
      context, RectFToBlitterRect(RectF(rect.right() - right, rect.y() + top,
                                        right, rect.height() - top)));
  // Top
  SbBlitterFillRect(
      context, RectFToBlitterRect(
                   RectF(rect.x() + left, rect.y(), rect.width() - left, top)));
}

}  // namespace

void RenderTreeNodeVisitor::Visit(render_tree::RectNode* rect_node) {
  TRACE_EVENT0_IF_ENABLED("Visit(RectNode)");

  if (rect_node->data().rounded_corners) {
    // We can't render rounded corners through the Blitter API.
    RenderWithSoftwareRenderer(rect_node);
    return;
  }
  if (rect_node->data().border) {
    if (!AllBorderSidesHaveSameColorAndStyle(*rect_node->data().border)) {
      // If the borders don't all have the same color and style, we can't
      // render them with the Blitter API (because we can't just render 4
      // rectangles), so fallback to software.
      RenderWithSoftwareRenderer(rect_node);
      return;
    }
  }

  const RectF& transformed_rect =
      render_state_.transform.TransformRect(rect_node->data().rect);

  if (rect_node->data().background_brush) {
    base::TypeId background_brush_typeid(
        rect_node->data().background_brush->GetTypeId());

    if (background_brush_typeid == base::GetTypeId<SolidColorBrush>()) {
      // Render the solid color fill, if a brush exists.
      SolidColorBrush* solid_color_brush =
          base::polymorphic_downcast<SolidColorBrush*>(
              rect_node->data().background_brush.get());
      ColorRGBA color = solid_color_brush->color();

      if (!IsOpaque(render_state_.opacity)) {
        color.set_a(color.a() * render_state_.opacity);
      }

      SbBlitterSetBlending(context_, !IsOpaque(color.a()));
      SbBlitterSetColor(context_, RenderTreeToBlitterColor(color));

      SbBlitterFillRect(context_, RectFToBlitterRect(transformed_rect));
    } else if (background_brush_typeid ==
               base::GetTypeId<LinearGradientBrush>()) {
      DCHECK(rect_node != NULL);
      bool rendered_gradient = RenderLinearGradient(
          device_, context_, render_state_, *rect_node, linear_gradient_cache_);
      if (!rendered_gradient) {
        RenderWithSoftwareRenderer(rect_node);
        return;
      }
    } else {
      // If we have a more complicated brush fallback to software.
      RenderWithSoftwareRenderer(rect_node);
      return;
    }
  }

  // Render the border, if it exists.
  if (rect_node->data().border) {
    const Border& border = *rect_node->data().border;
    DCHECK(AllBorderSidesHaveSameColorAndStyle(border));

    if (border.left.style != render_tree::kBorderStyleNone) {
      DCHECK_EQ(render_tree::kBorderStyleSolid, border.left.style);

      float left_width =
          border.left.width * render_state_.transform.scale().x();
      float right_width =
          border.right.width * render_state_.transform.scale().x();
      float top_width = border.top.width * render_state_.transform.scale().y();
      float bottom_width =
          border.bottom.width * render_state_.transform.scale().y();

      ColorRGBA color = border.left.color;
      if (!IsOpaque(render_state_.opacity)) {
        color.set_a(color.a() * render_state_.opacity);
      }
      RenderRectNodeBorder(context_, color, left_width, right_width, top_width,
                           bottom_width, transformed_rect);
    }
  }
}

void RenderTreeNodeVisitor::Visit(
    render_tree::RectShadowNode* rect_shadow_node) {
  TRACE_EVENT0_IF_ENABLED("Visit(RectShadowNode)");

  RenderWithSoftwareRenderer(rect_shadow_node);
}

void RenderTreeNodeVisitor::Visit(render_tree::TextNode* text_node) {
  TRACE_EVENT0_IF_ENABLED("Visit(TextNode)");

  RenderWithSoftwareRenderer(text_node);
}

void RenderTreeNodeVisitor::RenderWithSoftwareRenderer(
    render_tree::Node* node) {
  TRACE_EVENT0("cobalt::renderer", "RenderWithSoftwareRenderer()");
  CachedSoftwareRasterizer::SurfaceReference software_surface_reference(
      software_surface_cache_, node, render_state_.transform);
  CachedSoftwareRasterizer::Surface software_surface =
      software_surface_reference.surface();
  if (!SbBlitterIsSurfaceValid(software_surface.surface)) {
    return;
  }

  Transform apply_transform(render_state_.transform);
  apply_transform.ApplyScale(software_surface.coord_mapping.output_post_scale);
  math::RectF output_rectf = apply_transform.TransformRect(
      software_surface.coord_mapping.output_bounds);
  // We can simulate a "pre-multiply" by translation by offsetting the final
  // output rectangle by the pre-translate, effectively resulting in the
  // translation being applied last, as intended.
  output_rectf.Offset(software_surface.coord_mapping.output_pre_translate);
  SbBlitterRect output_blitter_rect = RectFToBlitterRect(output_rectf);

  SbBlitterSetBlending(context_, true);

  if (!IsOpaque(render_state_.opacity)) {
    SbBlitterSetModulateBlitsWithColor(context_, true);
    SbBlitterSetColor(
        context_,
        SbBlitterColorFromRGBA(255, 255, 255,
                               static_cast<int>(255 * render_state_.opacity)));
  } else {
    SbBlitterSetModulateBlitsWithColor(context_, false);
  }

// Blit the software rasterized surface to our actual render target.
#if defined(ENABLE_DEBUGGER)
  if (render_state_.highlight_software_draws && software_surface.created) {
    SbBlitterSetColor(context_, SbBlitterColorFromRGBA(0, 255, 0, 255));
    SbBlitterFillRect(context_, output_blitter_rect);
  } else  // NOLINT(readability/braces)
#endif    // defined(ENABLE_DEBUGGER)
  {
    TRACE_EVENT0("cobalt::renderer", "SbBlitterBlitRectToRect()");
    SbBlitterBlitRectToRect(
        context_, software_surface.surface,
        SbBlitterMakeRect(
            0, 0, software_surface.coord_mapping.output_bounds.width(),
            software_surface.coord_mapping.output_bounds.height()),
        output_blitter_rect);
  }
}

std::unique_ptr<RenderTreeNodeVisitor::OffscreenRender>
RenderTreeNodeVisitor::RenderToOffscreenSurface(render_tree::Node* node) {
  TRACE_EVENT0_IF_ENABLED("RenderToOffscreenSurface()");

  common::OffscreenRenderCoordinateMapping coord_mapping =
      common::GetOffscreenRenderCoordinateMapping(
          node->GetBounds(), render_state_.transform.ToMatrix(),
          render_state_.bounds_stack.Top());
  if (coord_mapping.output_bounds.IsEmpty()) {
    // There's nothing to render if the bounds are 0.
    return std::unique_ptr<OffscreenRender>();
  }
  DCHECK_GE(0.001f, std::abs(1.0f -
                             render_state_.transform.scale().x() *
                                 coord_mapping.output_post_scale.x()));
  DCHECK_GE(0.001f, std::abs(1.0f -
                             render_state_.transform.scale().y() *
                                 coord_mapping.output_post_scale.y()));

  std::unique_ptr<CachedScratchSurface> scratch_surface(
      new CachedScratchSurface(scratch_surface_cache_,
                               coord_mapping.output_bounds.size()));
  SbBlitterSurface surface = scratch_surface->GetSurface();
  if (!SbBlitterIsSurfaceValid(surface)) {
    return std::unique_ptr<RenderTreeNodeVisitor::OffscreenRender>();
  }

  SbBlitterRenderTarget render_target =
      SbBlitterGetRenderTargetFromSurface(surface);

  SbBlitterSetRenderTarget(context_, render_target);

  // Render to the sub-surface.
  RenderTreeNodeVisitor sub_visitor(
      device_, context_,
      RenderState(
          render_target, Transform(coord_mapping.sub_render_transform),
          BoundsStack(context_, Rect(coord_mapping.output_bounds.size()))),
      scratch_surface_cache_, software_surface_cache_, linear_gradient_cache_);
  node->Accept(&sub_visitor);

  // Restore our original render target.
  SbBlitterSetRenderTarget(context_, render_state_.render_target);
  // Restore our context's scissor rectangle to what it was before we switched
  // render targets.
  render_state_.bounds_stack.UpdateContext();

  math::PointF output_point = coord_mapping.output_bounds.origin() +
                              coord_mapping.output_pre_translate +
                              render_state_.transform.translate();

  std::unique_ptr<OffscreenRender> ret(new OffscreenRender());
  ret->destination_rect =
      math::RectF(output_point, coord_mapping.output_bounds.size());
  ret->scratch_surface = std::move(scratch_surface);

  return std::move(ret);
}

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

#endif  // #if SB_HAS(BLITTER)
