// Copyright 2017 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 "starboard/configuration.h"
#if SB_API_VERSION >= 12 || SB_HAS(GLES2)

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

#include <algorithm>
#include <cmath>
#include <limits>
#include <memory>

#include "base/logging.h"
#include "base/optional.h"
#include "base/trace_event/trace_event.h"
#include "cobalt/base/polymorphic_downcast.h"
#include "cobalt/base/type_id.h"
#include "cobalt/math/matrix3_f.h"
#include "cobalt/math/transform_2d.h"
#include "cobalt/renderer/rasterizer/common/utils.h"
#include "cobalt/renderer/rasterizer/egl/draw_callback.h"
#include "cobalt/renderer/rasterizer/egl/draw_clear.h"
#include "cobalt/renderer/rasterizer/egl/draw_poly_color.h"
#include "cobalt/renderer/rasterizer/egl/draw_rect_border.h"
#include "cobalt/renderer/rasterizer/egl/draw_rect_color_texture.h"
#include "cobalt/renderer/rasterizer/egl/draw_rect_linear_gradient.h"
#include "cobalt/renderer/rasterizer/egl/draw_rect_radial_gradient.h"
#include "cobalt/renderer/rasterizer/egl/draw_rect_shadow_blur.h"
#include "cobalt/renderer/rasterizer/egl/draw_rect_shadow_spread.h"
#include "cobalt/renderer/rasterizer/egl/draw_rect_texture.h"
#include "cobalt/renderer/rasterizer/egl/draw_rrect_color.h"
#include "cobalt/renderer/rasterizer/egl/draw_rrect_color_texture.h"
#include "cobalt/renderer/rasterizer/skia/hardware_image.h"
#include "cobalt/renderer/rasterizer/skia/image.h"
#include "cobalt/renderer/rasterizer/skia/skottie_animation.h"

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

using common::utils::IsOpaque;
using common::utils::IsTransparent;

namespace {

typedef float ColorTransformMatrix[16];

using render_tree::kMultiPlaneImageFormatYUV3PlaneBT601FullRange;
using render_tree::kMultiPlaneImageFormatYUV3PlaneBT709;

const render_tree::ColorRGBA kOpaqueWhite(1.0f, 1.0f, 1.0f, 1.0f);
const render_tree::ColorRGBA kTransparentBlack(0.0f, 0.0f, 0.0f, 0.0f);

const ColorTransformMatrix kBT601FullRangeColorTransformMatrixInColumnMajor = {
    1.0f,   1.0f,      1.0f, 0.0f, 0.0f,   -0.34414f, 1.772f,  0.0f,
    1.402f, -0.71414f, 0.0f, 0.0f, -0.701, 0.529f,    -0.886f, 1.f,
};

const ColorTransformMatrix kBT709ColorTransformMatrixInColumnMajor = {
    1.164f, 1.164f,  1.164f, 0.0f, 0.0f,      -0.213f,  2.112f,    0.0f,
    1.793f, -0.533f, 0.0f,   0.0f, -0.96925f, 0.30025f, -1.12875f, 1.0f};

const ColorTransformMatrix& GetColorTransformMatrixInColumnMajor(
    render_tree::MultiPlaneImageFormat format) {
  const float* transform;
  if (format == kMultiPlaneImageFormatYUV3PlaneBT601FullRange) {
    return kBT601FullRangeColorTransformMatrixInColumnMajor;
  }
  DCHECK_EQ(format, kMultiPlaneImageFormatYUV3PlaneBT709);
  return kBT709ColorTransformMatrixInColumnMajor;
}

bool IsUniformSolidColor(const render_tree::Border& border) {
  return border.left.style == render_tree::kBorderStyleSolid &&
         border.right.style == render_tree::kBorderStyleSolid &&
         border.top.style == render_tree::kBorderStyleSolid &&
         border.bottom.style == render_tree::kBorderStyleSolid &&
         border.left.color == border.right.color &&
         border.top.color == border.bottom.color &&
         border.left.color == border.top.color;
}

math::RectF RoundOut(const math::RectF& input, float pad) {
  float left = std::floor(input.x() - pad);
  float right = std::ceil(input.right() + pad);
  float top = std::floor(input.y() - pad);
  float bottom = std::ceil(input.bottom() + pad);
  return math::RectF(left, top, right - left, bottom - top);
}

math::Matrix3F GetTexcoordTransform(
    const OffscreenTargetManager::TargetInfo& target) {
  // Flip the texture vertically to accommodate OpenGL's bottom-left origin.
  float scale_x = 1.0f / target.framebuffer->GetSize().width();
  float scale_y = -1.0f / target.framebuffer->GetSize().height();
  return math::Matrix3F::FromValues(
      target.region.width() * scale_x, 0, target.region.x() * scale_x, 0,
      target.region.height() * scale_y, 1.0f + target.region.y() * scale_y, 0,
      0, 1);
}

math::SizeF GetTransformScale(const math::Matrix3F& transform) {
  math::PointF mapped_origin = transform * math::PointF(0, 0);
  math::PointF mapped_x = transform * math::PointF(1, 0);
  math::PointF mapped_y = transform * math::PointF(0, 1);
  math::Vector2dF mapped_vecx(mapped_x.x() - mapped_origin.x(),
                              mapped_x.y() - mapped_origin.y());
  math::Vector2dF mapped_vecy(mapped_y.x() - mapped_origin.x(),
                              mapped_y.y() - mapped_origin.y());
  return math::SizeF(mapped_vecx.Length(), mapped_vecy.Length());
}

bool ImageNodeSupportedNatively(render_tree::ImageNode* image_node) {
  // The image node may contain nothing. For example, when it represents a video
  // element before any frame is decoded.
  if (!image_node->data().source) {
    return true;
  }

  // Ensure any required backend processing is done to create the necessary
  // GPU resource. This must be done to verify whether the GPU resource can
  // be rendered by the shader.
  skia::Image* skia_image =
      base::polymorphic_downcast<skia::Image*>(image_node->data().source.get());
  skia_image->EnsureInitialized();

  if (skia_image->GetTypeId() == base::GetTypeId<skia::MultiPlaneImage>()) {
    skia::HardwareMultiPlaneImage* hardware_image =
        base::polymorphic_downcast<skia::HardwareMultiPlaneImage*>(skia_image);
    // TODO: Also enable rendering of three plane BT.709 images here.
    return hardware_image->GetFormat() ==
           kMultiPlaneImageFormatYUV3PlaneBT601FullRange;
  }
  if (skia_image->GetTypeId() == base::GetTypeId<skia::SinglePlaneImage>() &&
      skia_image->CanRenderInSkia()) {
    skia::HardwareFrontendImage* hardware_image =
        base::polymorphic_downcast<skia::HardwareFrontendImage*>(skia_image);
    // We don't yet handle alternative formats that piggyback on a GL_RGBA
    // texture.  This comes up, for example, with UYVY (YUV 422) textures.
    return !hardware_image->alternate_rgba_format();
  }
  return false;
}

bool RoundedRectContainsNonRoundedRect(
    const math::RectF& outer_rect,
    const render_tree::RoundedCorners& outer_corners,
    const math::RectF& inner_rect) {
  // Calculate the biggest (by area), the tallest, and the widest non-rounded
  // rects contained by the rounded rect. See if one of these contains the
  // inner rect.
  float inset_left = std::max(outer_corners.top_left.horizontal,
                              outer_corners.bottom_left.horizontal);
  float inset_right = std::max(outer_corners.top_right.horizontal,
                               outer_corners.bottom_right.horizontal);
  float inset_top = std::max(outer_corners.top_left.vertical,
                             outer_corners.top_right.vertical);
  float inset_bottom = std::max(outer_corners.bottom_left.vertical,
                                outer_corners.bottom_right.vertical);

  // Given an ellipse centered at the origin with radii A and B, the inscribed
  // rectangle with the largest area would extend A * sqrt(2) / 2 and
  // B * sqrt(2) / 2 units in each quadrant.
  const float kInsetScale = 0.2929f;  // 1 - sqrt(2) / 2
  math::RectF biggest_rect(outer_rect);
  biggest_rect.Inset(kInsetScale * inset_left, kInsetScale * inset_top,
                     kInsetScale * inset_right, kInsetScale * inset_bottom);

  math::RectF tallest_rect(outer_rect);
  tallest_rect.Inset(inset_left, 0, inset_right, 0);

  math::RectF widest_rect(outer_rect);
  widest_rect.Inset(0, inset_top, 0, inset_bottom);

  return biggest_rect.Contains(inner_rect) ||
         tallest_rect.Contains(inner_rect) || widest_rect.Contains(inner_rect);
}

bool RoundedRectContainsRoundedRect(
    const math::RectF& orect, const render_tree::RoundedCorners& ocorners,
    const math::RectF& irect, const render_tree::RoundedCorners& icorners) {
  // Use a quick and simple comparison. This may return false negatives,
  // but never return false positives.
  return orect.Contains(irect) &&
         ocorners.top_left.horizontal <= icorners.top_left.horizontal &&
         ocorners.top_left.vertical <= icorners.top_left.vertical &&
         ocorners.top_right.horizontal <= icorners.top_right.horizontal &&
         ocorners.top_right.vertical <= icorners.top_right.vertical &&
         ocorners.bottom_right.horizontal <= icorners.bottom_right.horizontal &&
         ocorners.bottom_right.vertical <= icorners.bottom_right.vertical &&
         ocorners.bottom_left.horizontal <= icorners.bottom_left.horizontal &&
         ocorners.bottom_left.vertical <= icorners.bottom_left.vertical;
}

bool RoundedViewportSupportedForSource(
    render_tree::Node* source, math::Vector2dF offset,
    const render_tree::ViewportFilter& filter) {
  base::TypeId source_type = source->GetTypeId();
  if (source_type == base::GetTypeId<render_tree::ImageNode>()) {
    // Image nodes are supported if the image can be rendered natively.
    render_tree::ImageNode* image_node =
        base::polymorphic_downcast<render_tree::ImageNode*>(source);
    return ImageNodeSupportedNatively(image_node);
  } else if (source_type == base::GetTypeId<render_tree::RectNode>()) {
    // Rect nodes are supported if they are fully contained by the filter
    // (i.e. the filter effectively does nothing).
    const render_tree::RectNode::Builder& rect_data =
        base::polymorphic_downcast<render_tree::RectNode*>(source)->data();
    math::RectF content_rect(rect_data.rect);
    content_rect.Offset(offset);
    if (rect_data.rounded_corners) {
      return RoundedRectContainsRoundedRect(
          filter.viewport(), filter.rounded_corners(), content_rect,
          *rect_data.rounded_corners);
    } else {
      return RoundedRectContainsNonRoundedRect(
          filter.viewport(), filter.rounded_corners(), content_rect);
    }
  } else if (source_type == base::GetTypeId<render_tree::CompositionNode>()) {
    // If this is a composition of valid sources, then rendering with a rounded
    // viewport is also supported.
    render_tree::CompositionNode* composition_node =
        base::polymorphic_downcast<render_tree::CompositionNode*>(source);
    typedef render_tree::CompositionNode::Children Children;
    const Children& children = composition_node->data().children();
    offset += composition_node->data().offset();

    for (Children::const_iterator iter = children.begin();
         iter != children.end(); ++iter) {
      if (!RoundedViewportSupportedForSource(iter->get(), offset, filter)) {
        return false;
      }
    }
    return true;
  } else if (source_type == base::GetTypeId<render_tree::FilterNode>()) {
    const render_tree::FilterNode::Builder& filter_data =
        base::polymorphic_downcast<render_tree::FilterNode*>(source)->data();
    // If the inner rounded viewport filter is contained by the outer
    // rounded viewport filter, then just render the inner filter.
    if (filter_data.viewport_filter &&
        filter_data.viewport_filter->has_rounded_corners() &&
        !filter_data.opacity_filter && !filter_data.blur_filter &&
        !filter_data.map_to_mesh_filter) {
      math::RectF viewport_rect = filter_data.viewport_filter->viewport();
      viewport_rect.Offset(offset);
      return RoundedRectContainsRoundedRect(
                 filter.viewport(), filter.rounded_corners(), viewport_rect,
                 filter_data.viewport_filter->rounded_corners()) &&
             RoundedViewportSupportedForSource(filter_data.source.get(),
                                               math::Vector2dF(),
                                               *filter_data.viewport_filter);
    }
    return false;
  }

  bool is_transform =
      source_type == base::GetTypeId<render_tree::MatrixTransformNode>() ||
      source_type == base::GetTypeId<render_tree::MatrixTransform3DNode>();
  if (!is_transform) {
    // Generic nodes are handled if they are fully contained in the filter
    // (i.e. the filter effectively does nothing). Transform nodes are not
    // handled because their interaction with the rounded viewport filter is
    // not handled.
    math::RectF node_bounds(source->GetBounds());
    node_bounds.Offset(offset);
    return RoundedRectContainsNonRoundedRect(
        filter.viewport(), filter.rounded_corners(), node_bounds);
  }

  return false;
}

// Return the error value of a given offscreen target cache entry.
// |desired_bounds| specifies the world-space bounds to which an offscreen
//   target will be rendered.
// |cached_bounds| specifies the world-space bounds used when the offscreen
//   target was generated.
// Lower return values indicate better fits. Only cache entries with an error
//   less than 1 will be considered suitable.
float OffscreenTargetErrorFunction(const math::RectF& desired_bounds,
                                   const math::RectF& cached_bounds) {
  // The cached contents must be within 0.5 pixels of the desired size to avoid
  // scaling artifacts.
  if (std::abs(desired_bounds.width() - cached_bounds.width()) >= 0.5f ||
      std::abs(desired_bounds.height() - cached_bounds.height()) >= 0.5f) {
    return 1.0f;
  }

  // Use the cached contents' sub-pixel offset as the error rating.
  math::PointF desired_offset(
      desired_bounds.x() - std::floor(desired_bounds.x()),
      desired_bounds.y() - std::floor(desired_bounds.y()));
  math::PointF cached_offset(cached_bounds.x() - std::floor(cached_bounds.x()),
                             cached_bounds.y() - std::floor(cached_bounds.y()));
  float error_x = std::abs(desired_offset.x() - cached_offset.x());
  float error_y = std::abs(desired_offset.y() - cached_offset.y());

  // Any sub-pixel offset is okay. Return something less than 1.
  return (error_x + error_y) * 0.49f;
}

float OffscreenTargetErrorFunction1D(float desired, const float& cached) {
  return std::abs(cached - desired);
}

}  // namespace

RenderTreeNodeVisitor::RenderTreeNodeVisitor(
    GraphicsState* graphics_state, DrawObjectManager* draw_object_manager,
    OffscreenTargetManager* offscreen_target_manager,
    const FallbackRasterizeFunction& fallback_rasterize,
    SkCanvas* fallback_render_target, backend::RenderTarget* render_target,
    const math::Rect& content_rect)
    : graphics_state_(graphics_state),
      draw_object_manager_(draw_object_manager),
      offscreen_target_manager_(offscreen_target_manager),
      fallback_rasterize_(fallback_rasterize),
      fallback_render_target_(fallback_render_target),
      render_target_(render_target),
      onscreen_render_target_(render_target),
      last_draw_id_(0),
      fallback_rasterize_count_(0) {
  draw_state_.scissor.Intersect(content_rect);
}

void RenderTreeNodeVisitor::Visit(render_tree::ClearRectNode* clear_rect_node) {
  if (!IsVisible(clear_rect_node->GetBounds())) {
    return;
  }

  DCHECK_EQ(clear_rect_node->data().rect, clear_rect_node->GetBounds());
  AddClear(clear_rect_node->data().rect, clear_rect_node->data().color);
}

void RenderTreeNodeVisitor::Visit(
    render_tree::CompositionNode* composition_node) {
  const render_tree::CompositionNode::Builder& data = composition_node->data();
  math::Matrix3F old_transform = draw_state_.transform;
  draw_state_.transform =
      draw_state_.transform *
      math::TranslateMatrix(data.offset().x(), data.offset().y());
  draw_state_.rounded_scissor_rect.Offset(-data.offset());
  const render_tree::CompositionNode::Children& children = data.children();
  for (render_tree::CompositionNode::Children::const_iterator iter =
           children.begin();
       iter != children.end(); ++iter) {
    (*iter)->Accept(this);
  }
  draw_state_.rounded_scissor_rect.Offset(data.offset());
  draw_state_.transform = old_transform;
}

void RenderTreeNodeVisitor::Visit(
    render_tree::MatrixTransform3DNode* transform_3d_node) {
  // This is used in conjunction with a map-to-mesh filter. If that filter is
  // implemented natively, then this transform 3D must be handled natively
  // as well. Otherwise, use the fallback rasterizer for both.
  FallbackRasterize(transform_3d_node);
}

void RenderTreeNodeVisitor::Visit(
    render_tree::MatrixTransformNode* transform_node) {
  const render_tree::MatrixTransformNode::Builder& data =
      transform_node->data();
  math::Matrix3F old_transform = draw_state_.transform;
  draw_state_.transform = draw_state_.transform * data.transform;
  data.source->Accept(this);
  draw_state_.transform = old_transform;
}

void RenderTreeNodeVisitor::Visit(render_tree::FilterNode* filter_node) {
  const render_tree::FilterNode::Builder& data = filter_node->data();

  // Handle viewport-only filter.
  if (data.viewport_filter && !data.opacity_filter && !data.blur_filter &&
      !data.map_to_mesh_filter) {
    const math::Matrix3F& transform = draw_state_.transform;
    if (data.viewport_filter->has_rounded_corners()) {
      // Certain source nodes have an optimized path for rendering inside
      // rounded viewports.
      if (RoundedViewportSupportedForSource(
              data.source.get(), math::Vector2dF(), *data.viewport_filter)) {
        math::RectF old_scissor_rect = draw_state_.rounded_scissor_rect;
        DrawObject::OptionalRoundedCorners old_scissor_corners =
            draw_state_.rounded_scissor_corners;
        draw_state_.rounded_scissor_rect = data.viewport_filter->viewport();
        draw_state_.rounded_scissor_corners =
            data.viewport_filter->rounded_corners();
        data.source->Accept(this);
        draw_state_.rounded_scissor_rect = old_scissor_rect;
        draw_state_.rounded_scissor_corners = old_scissor_corners;
        return;
      } else {
        // The source is too complex and must be rendered to a texture, then
        // that texture will be rendered using the rounded viewport.
        DrawObject::BaseState old_draw_state = draw_state_;

        // Render the source into an offscreen target at 100% opacity in its
        // own local space. To avoid magnification artifacts, scale up the
        // local space to match the source's size when rendered in world space.
        math::Matrix3F texcoord_transform(math::Matrix3F::Identity());
        math::RectF content_rect = data.source->GetBounds();
        const backend::TextureEGL* texture = nullptr;
        if (!IsVisible(content_rect)) {
          return;
        }
        draw_state_.opacity = 1.0f;

        math::SizeF scale = GetTransformScale(draw_state_.transform);
        draw_state_.transform = math::ScaleMatrix(
            std::max(1.0f, scale.width()), std::max(1.0f, scale.height()));

        // Don't clip the source since it is in its own local space.
        bool limit_to_screen_size = false;
        math::RectF mapped_content_rect =
            draw_state_.transform.MapRect(content_rect);
        draw_state_.scissor =
            math::Rect::RoundFromRectF(RoundOut(mapped_content_rect, 0.0f));
        draw_state_.rounded_scissor_corners.reset();

        OffscreenRasterize(data.source, limit_to_screen_size, &texture,
                           &texcoord_transform, &mapped_content_rect);
        if (mapped_content_rect.IsEmpty()) {
          return;
        }

        // Then render that offscreen target with the rounded filter.
        draw_state_ = old_draw_state;
        draw_state_.rounded_scissor_rect = data.viewport_filter->viewport();
        draw_state_.rounded_scissor_corners =
            data.viewport_filter->rounded_corners();
        std::unique_ptr<DrawObject> draw(new DrawRRectColorTexture(
            graphics_state_, draw_state_, content_rect, kOpaqueWhite, texture,
            texcoord_transform, true /* clamp_texcoords */));
        AddDraw(std::move(draw), content_rect,
                DrawObjectManager::kBlendSrcAlpha);

        draw_state_ = old_draw_state;
        return;
      }
    } else if (cobalt::math::IsOnlyScaleAndTranslate(transform)) {
      // Orthogonal viewport filters without rounded corners can be collapsed
      // into the world-space scissor.

      // Transform local viewport to world viewport.
      const math::RectF& filter_viewport = data.viewport_filter->viewport();
      math::RectF transformed_viewport(
          filter_viewport.x() * transform(0, 0) + transform(0, 2),
          filter_viewport.y() * transform(1, 1) + transform(1, 2),
          filter_viewport.width() * transform(0, 0),
          filter_viewport.height() * transform(1, 1));
      // Ensure transformed viewport data is sane (in case global transform
      // flipped any axis).
      if (transformed_viewport.width() < 0) {
        transformed_viewport.set_x(transformed_viewport.right());
        transformed_viewport.set_width(-transformed_viewport.width());
      }
      if (transformed_viewport.height() < 0) {
        transformed_viewport.set_y(transformed_viewport.bottom());
        transformed_viewport.set_height(-transformed_viewport.height());
      }
      // Combine the new viewport filter with existing viewport filter.
      math::Rect old_scissor = draw_state_.scissor;
      draw_state_.scissor.Intersect(
          math::Rect::RoundFromRectF(transformed_viewport));
      if (!draw_state_.scissor.IsEmpty()) {
        data.source->Accept(this);
      }
      draw_state_.scissor = old_scissor;
      return;
    }
  }

  // Handle opacity-only filter.
  if (data.opacity_filter && !data.viewport_filter && !data.blur_filter &&
      !data.map_to_mesh_filter) {
    const float filter_opacity = data.opacity_filter->opacity();
    if (IsTransparent(filter_opacity)) {
      // Totally transparent. Ignore the source.
      return;
    } else if (IsOpaque(filter_opacity)) {
      // Totally opaque. Render like normal.
      data.source->Accept(this);
      return;
    } else if (common::utils::NodeCanRenderWithOpacity(data.source.get())) {
      // Simple opacity that does not require an offscreen target.
      float old_opacity = draw_state_.opacity;
      draw_state_.opacity *= filter_opacity;
      data.source->Accept(this);
      draw_state_.opacity = old_opacity;
      return;
    } else {
      // Complex opacity that requires an offscreen target.
      math::Matrix3F texcoord_transform(math::Matrix3F::Identity());
      math::RectF content_rect;
      const backend::TextureEGL* texture = nullptr;

      // Render source at 100% opacity to an offscreen target, then render
      // that result with the specified filter opacity.
      float old_opacity = draw_state_.opacity;
      draw_state_.opacity = 1.0f;
      // Since the offscreen target is mapped to world space, limit the target
      // to the screen size to avoid unnecessarily large offscreen targets.
      bool limit_to_screen_size = true;
      OffscreenRasterize(data.source, limit_to_screen_size, &texture,
                         &texcoord_transform, &content_rect);
      if (content_rect.IsEmpty()) {
        return;
      }

      // The content rect is already in screen space, so reset the transform.
      math::Matrix3F old_transform = draw_state_.transform;
      draw_state_.transform = math::Matrix3F::Identity();
      draw_state_.opacity = old_opacity * filter_opacity;
      std::unique_ptr<DrawObject> draw(new DrawRectColorTexture(
          graphics_state_, draw_state_, content_rect, kOpaqueWhite, texture,
          texcoord_transform, true /* clamp_texcoords */));
      AddDraw(std::move(draw), content_rect, DrawObjectManager::kBlendSrcAlpha);
      draw_state_.opacity = old_opacity;
      draw_state_.transform = old_transform;
      return;
    }
  }

  // Handle blur-only filter.
  if (data.blur_filter && !data.viewport_filter && !data.opacity_filter &&
      !data.map_to_mesh_filter) {
    if (data.blur_filter->blur_sigma() == 0.0f) {
      // Ignorable blur request. Render normally.
      data.source->Accept(this);
      return;
    }
  }

  // No filter.
  if (!data.opacity_filter && !data.viewport_filter && !data.blur_filter &&
      !data.map_to_mesh_filter) {
    data.source->Accept(this);
    return;
  }

  // Use the fallback rasterizer to handle everything else.
  FallbackRasterize(filter_node);
}

void RenderTreeNodeVisitor::Visit(render_tree::ImageNode* image_node) {
  const render_tree::ImageNode::Builder& data = image_node->data();

  // The image node may contain nothing. For example, when it represents a video
  // element before any frame is decoded.
  if (!data.source) {
    return;
  }

  if (!IsVisible(image_node->GetBounds())) {
    return;
  }

  if (!ImageNodeSupportedNatively(image_node)) {
    FallbackRasterize(image_node);
    return;
  }

  bool clamp_texcoords = false;
  skia::Image* skia_image =
      base::polymorphic_downcast<skia::Image*>(data.source.get());
  bool is_opaque = skia_image->IsOpaque() && IsOpaque(draw_state_.opacity);

  // Calculate matrix to transform texture coordinates according to the local
  // transform.
  math::Matrix3F texcoord_transform(math::Matrix3F::Identity());
  if (cobalt::math::IsOnlyScaleAndTranslate(data.local_transform)) {
    texcoord_transform(0, 0) =
        data.local_transform(0, 0) != 0 ? 1.0f / data.local_transform(0, 0) : 0;
    texcoord_transform(1, 1) =
        data.local_transform(1, 1) != 0 ? 1.0f / data.local_transform(1, 1) : 0;
    texcoord_transform(0, 2) =
        -texcoord_transform(0, 0) * data.local_transform(0, 2);
    texcoord_transform(1, 2) =
        -texcoord_transform(1, 1) * data.local_transform(1, 2);
    if (texcoord_transform(0, 0) < 1.0f || texcoord_transform(1, 1) < 1.0f) {
      // Edges may interpolate with texels outside the designated region.
      // Use a fragment shader that clamps the texture coordinates to prevent
      // that from happening.
      clamp_texcoords = true;
    }
  } else {
    texcoord_transform = data.local_transform.Inverse();
  }

  // Different shaders are used depending on whether the image has a single
  // plane or multiple planes.
  std::unique_ptr<DrawObject> draw;

  if (skia_image->GetTypeId() == base::GetTypeId<skia::SinglePlaneImage>()) {
    skia::HardwareFrontendImage* hardware_image =
        base::polymorphic_downcast<skia::HardwareFrontendImage*>(skia_image);
    if (!hardware_image->GetTextureEGL()) {
      return;
    }

    if (draw_state_.rounded_scissor_corners) {
      // Transparency is used to anti-alias the rounded rect.
      is_opaque = false;
      draw.reset(new DrawRRectColorTexture(
          graphics_state_, draw_state_, data.destination_rect, kOpaqueWhite,
          hardware_image->GetTextureEGL(), texcoord_transform,
          clamp_texcoords));
    } else if (clamp_texcoords || !is_opaque) {
      draw.reset(new DrawRectColorTexture(graphics_state_, draw_state_,
                                          data.destination_rect, kOpaqueWhite,
                                          hardware_image->GetTextureEGL(),
                                          texcoord_transform, clamp_texcoords));
    } else {
      draw.reset(new DrawRectTexture(
          graphics_state_, draw_state_, data.destination_rect,
          hardware_image->GetTextureEGL(), texcoord_transform));
    }
  } else if (skia_image->GetTypeId() ==
             base::GetTypeId<skia::MultiPlaneImage>()) {
    skia::HardwareMultiPlaneImage* hardware_image =
        base::polymorphic_downcast<skia::HardwareMultiPlaneImage*>(skia_image);
    auto image_format = hardware_image->GetFormat();
    auto y_texture_egl = hardware_image->GetTextureEGL(0);
    auto u_texture_egl = hardware_image->GetTextureEGL(1);
    auto v_texture_egl = hardware_image->GetTextureEGL(2);

    if (!y_texture_egl || !u_texture_egl || !v_texture_egl) {
      return;
    }

    const ColorTransformMatrix& color_transform_in_column_major =
        GetColorTransformMatrixInColumnMajor(image_format);

    if (draw_state_.rounded_scissor_corners) {
      // Transparency is used to anti-alias the rounded rect.
      is_opaque = false;
      draw.reset(new DrawRRectColorTexture(
          graphics_state_, draw_state_, data.destination_rect, kOpaqueWhite,
          y_texture_egl, u_texture_egl, v_texture_egl,
          color_transform_in_column_major, texcoord_transform,
          clamp_texcoords));
    } else if (clamp_texcoords || !is_opaque) {
      draw.reset(new DrawRectColorTexture(
          graphics_state_, draw_state_, data.destination_rect, kOpaqueWhite,
          y_texture_egl, u_texture_egl, v_texture_egl,
          color_transform_in_column_major, texcoord_transform,
          clamp_texcoords));
    } else {
      draw.reset(new DrawRectTexture(
          graphics_state_, draw_state_, data.destination_rect, y_texture_egl,
          u_texture_egl, v_texture_egl, color_transform_in_column_major,
          texcoord_transform));
    }
  } else {
    NOTREACHED();
    return;
  }

  AddDraw(std::move(draw), image_node->GetBounds(),
          is_opaque ? DrawObjectManager::kBlendNoneOrSrcAlpha
                    : DrawObjectManager::kBlendSrcAlpha);
}

void RenderTreeNodeVisitor::Visit(render_tree::LottieNode* lottie_node) {
  const render_tree::LottieNode::Builder& data = lottie_node->data();
  math::RectF content_rect = data.destination_rect;
  if (!IsVisible(content_rect)) {
    return;
  }

  skia::SkottieAnimation* animation =
      base::polymorphic_downcast<skia::SkottieAnimation*>(data.animation.get());
  if (animation->GetSize().GetArea() == 0) {
    return;
  }
  animation->SetAnimationTime(data.animation_time);

  // Get an offscreen target to cache the animation. Make the target big enough
  // to avoid scaling artifacts.
  math::SizeF scale = GetTransformScale(draw_state_.transform);
  math::SizeF mapped_size = content_rect.size();
  // Use a uniform scale to avoid impacting aspect ratio calculations.
  mapped_size.Scale(std::max(scale.width(), scale.height()));

  OffscreenTargetManager::TargetInfo target_info;
  if (!offscreen_target_manager_->GetCachedTarget(animation, mapped_size,
                                                  &target_info)) {
    // No pre-existing target was found. Allocate a new target.
    animation->ResetRenderCache();
    offscreen_target_manager_->AllocateCachedTarget(animation, mapped_size,
                                                    &target_info);
  }
  if (target_info.framebuffer == nullptr) {
    // Unable to allocate the render target for the animation cache.
    return;
  }

  // Add a draw call to update the cache.
  std::unique_ptr<DrawObject> update_cache(new DrawCallback(base::Bind(
      &skia::SkottieAnimation::UpdateRenderCache, base::Unretained(animation),
      base::Unretained(target_info.skia_canvas), target_info.region.size())));
  draw_object_manager_->AddBatchedExternalDraw(
      std::move(update_cache), lottie_node->GetTypeId(),
      target_info.framebuffer, target_info.region);

  // Add a draw call to render the cached animation to the current target.
  backend::TextureEGL* texture = target_info.framebuffer->GetColorTexture();
  math::Matrix3F texcoord_transform = GetTexcoordTransform(target_info);
  if (IsOpaque(draw_state_.opacity)) {
    std::unique_ptr<DrawObject> draw(
        new DrawRectTexture(graphics_state_, draw_state_, content_rect, texture,
                            texcoord_transform));
    AddDraw(std::move(draw), content_rect, DrawObjectManager::kBlendSrcAlpha);
  } else {
    std::unique_ptr<DrawObject> draw(new DrawRectColorTexture(
        graphics_state_, draw_state_, content_rect, kOpaqueWhite, texture,
        texcoord_transform, false /* clamp_texcoords */));
    AddDraw(std::move(draw), content_rect, DrawObjectManager::kBlendSrcAlpha);
  }
}

void RenderTreeNodeVisitor::Visit(
    render_tree::PunchThroughVideoNode* video_node) {
  if (!IsVisible(video_node->GetBounds())) {
    return;
  }

  const render_tree::PunchThroughVideoNode::Builder& data = video_node->data();
  math::RectF mapped_rect_float = draw_state_.transform.MapRect(data.rect);
  math::Rect mapped_rect = math::Rect::RoundFromRectF(mapped_rect_float);
  data.set_bounds_cb.Run(mapped_rect);

  DCHECK_EQ(data.rect, video_node->GetBounds());
  AddClear(data.rect, kTransparentBlack);
}

void RenderTreeNodeVisitor::Visit(render_tree::RectNode* rect_node) {
  math::RectF node_bounds(rect_node->GetBounds());
  if (!IsVisible(node_bounds)) {
    return;
  }

  const render_tree::RectNode::Builder& data = rect_node->data();
  const std::unique_ptr<render_tree::Brush>& brush = data.background_brush;
  base::Optional<render_tree::RoundedCorners> content_corners;
  math::RectF content_rect(data.rect);
  bool content_rect_drawn = false;

  if (data.rounded_corners) {
    content_corners = *data.rounded_corners;
  }

  // Only solid color brushes are natively supported with rounded corners.
  if (data.rounded_corners && brush &&
      brush->GetTypeId() != base::GetTypeId<render_tree::SolidColorBrush>()) {
    FallbackRasterize(rect_node);
    return;
  }

  // Determine whether the RectNode's border attribute is supported. Update
  // the content and bounds if so.
  std::unique_ptr<DrawObject> draw_border;
  if (data.border) {
    std::unique_ptr<DrawRectBorder> rect_border(
        new DrawRectBorder(graphics_state_, draw_state_, rect_node));
    if (rect_border->IsValid()) {
      node_bounds = rect_border->GetBounds();
      content_rect = rect_border->GetContentRect();
      content_rect_drawn = rect_border->DrawsContentRect();
      draw_border.reset(rect_border.release());
    } else if (data.rounded_corners) {
      // Handle the special case of uniform rounded borders.
      math::Vector2dF scale = math::GetScale2d(draw_state_.transform);
      bool border_is_subpixel = data.border->left.width * scale.x() < 1.0f ||
                                data.border->right.width * scale.x() < 1.0f ||
                                data.border->top.width * scale.y() < 1.0f ||
                                data.border->bottom.width * scale.y() < 1.0f;
      if (IsUniformSolidColor(*data.border) && !border_is_subpixel) {
        math::RectF border_rect(content_rect);
        render_tree::RoundedCorners border_corners = *data.rounded_corners;
        content_rect.Inset(data.border->left.width, data.border->top.width,
                           data.border->right.width, data.border->bottom.width);
        content_corners = data.rounded_corners->Inset(
            data.border->left.width, data.border->top.width,
            data.border->right.width, data.border->bottom.width);
        content_corners = content_corners->Normalize(content_rect);
        draw_border.reset(new DrawRectShadowSpread(
            graphics_state_, draw_state_, content_rect, content_corners,
            border_rect, border_corners, data.border->top.color));
      }
    }
  }
  const bool border_supported = !data.border || draw_border;

  // Determine whether the RectNode's background brush is supported.
  base::TypeId brush_type =
      brush ? brush->GetTypeId() : base::GetTypeId<render_tree::Brush>();
  bool brush_is_solid_and_supported =
      brush_type == base::GetTypeId<render_tree::SolidColorBrush>();
  bool brush_is_linear_and_supported =
      brush_type == base::GetTypeId<render_tree::LinearGradientBrush>();
  bool brush_is_radial_and_supported =
      brush_type == base::GetTypeId<render_tree::RadialGradientBrush>();

  std::unique_ptr<DrawRectRadialGradient> draw_radial;
  if (brush_is_radial_and_supported) {
    const render_tree::RadialGradientBrush* radial_brush =
        base::polymorphic_downcast<const render_tree::RadialGradientBrush*>(
            brush.get());
    draw_radial.reset(new DrawRectRadialGradient(
        graphics_state_, draw_state_, content_rect, *radial_brush,
        base::Bind(&RenderTreeNodeVisitor::GetScratchTexture,
                   base::Unretained(this), base::WrapRefCounted(rect_node))));
    brush_is_radial_and_supported = draw_radial->IsValid();
  }

  const bool brush_supported = !brush || brush_is_solid_and_supported ||
                               brush_is_linear_and_supported ||
                               brush_is_radial_and_supported;

  if (!brush_supported || !border_supported) {
    FallbackRasterize(rect_node);
    return;
  }

  if (draw_border) {
    AddDraw(std::move(draw_border), node_bounds,
            DrawObjectManager::kBlendSrcAlpha);
  }
  if (content_rect_drawn) {
    return;
  }

  // Handle drawing the content.
  if (brush_is_solid_and_supported) {
    const render_tree::SolidColorBrush* solid_brush =
        base::polymorphic_downcast<const render_tree::SolidColorBrush*>(
            brush.get());
    if (content_corners) {
      std::unique_ptr<DrawObject> draw(
          new DrawRRectColor(graphics_state_, draw_state_, content_rect,
                             *content_corners, solid_brush->color()));
      // Transparency is used for anti-aliasing.
      AddDraw(std::move(draw), node_bounds, DrawObjectManager::kBlendSrcAlpha);
    } else {
      std::unique_ptr<DrawObject> draw(new DrawPolyColor(
          graphics_state_, draw_state_, content_rect, solid_brush->color()));
      // Match the blending mode used by other rect node draws to allow
      // merging of the draw objects if possible.
      AddDraw(std::move(draw), node_bounds,
              IsOpaque(draw_state_.opacity * solid_brush->color().a())
                  ? DrawObjectManager::kBlendNoneOrSrcAlpha
                  : DrawObjectManager::kBlendSrcAlpha);
    }
  } else if (brush_is_linear_and_supported) {
    const render_tree::LinearGradientBrush* linear_brush =
        base::polymorphic_downcast<const render_tree::LinearGradientBrush*>(
            brush.get());
    std::unique_ptr<DrawObject> draw(new DrawRectLinearGradient(
        graphics_state_, draw_state_, content_rect, *linear_brush));
    // The draw may use transparent pixels to ensure only pixels in the
    // specified area are modified.
    AddDraw(std::move(draw), node_bounds, DrawObjectManager::kBlendSrcAlpha);
  } else if (brush_is_radial_and_supported) {
    // The colors in the brush may be transparent.
    AddDraw(std::unique_ptr<DrawObject>(draw_radial.release()), node_bounds,
            DrawObjectManager::kBlendSrcAlpha);
  }
}

void RenderTreeNodeVisitor::Visit(render_tree::RectShadowNode* shadow_node) {
  math::RectF node_bounds(shadow_node->GetBounds());
  if (!IsVisible(node_bounds)) {
    return;
  }

  const render_tree::RectShadowNode::Builder& data = shadow_node->data();
  base::Optional<render_tree::RoundedCorners> spread_corners =
      data.rounded_corners;

  std::unique_ptr<DrawObject> draw;
  render_tree::ColorRGBA shadow_color(data.shadow.color);

  math::RectF spread_rect(data.rect);
  spread_rect.Offset(data.shadow.offset);
  if (data.inset) {
    if (spread_corners) {
      spread_corners = spread_corners->Inset(data.spread, data.spread,
                                             data.spread, data.spread);
    }
    spread_rect.Inset(data.spread, data.spread);
    if (!spread_rect.IsEmpty() && data.shadow.blur_sigma > 0.0f) {
      draw.reset(new DrawRectShadowBlur(graphics_state_, draw_state_, data.rect,
                                        data.rounded_corners, spread_rect,
                                        spread_corners, shadow_color,
                                        data.shadow.blur_sigma, data.inset));
    } else {
      draw.reset(new DrawRectShadowSpread(
          graphics_state_, draw_state_, spread_rect, spread_corners, data.rect,
          data.rounded_corners, shadow_color));
    }
  } else {
    if (spread_corners) {
      spread_corners = spread_corners->Inset(-data.spread, -data.spread,
                                             -data.spread, -data.spread);
    }
    spread_rect.Outset(data.spread, data.spread);
    if (spread_rect.IsEmpty()) {
      // Negative spread shenanigans! Nothing to draw.
      return;
    }
    if (data.shadow.blur_sigma > 0.0f) {
      draw.reset(new DrawRectShadowBlur(graphics_state_, draw_state_, data.rect,
                                        data.rounded_corners, spread_rect,
                                        spread_corners, shadow_color,
                                        data.shadow.blur_sigma, data.inset));
    } else {
      draw.reset(new DrawRectShadowSpread(
          graphics_state_, draw_state_, data.rect, data.rounded_corners,
          spread_rect, spread_corners, shadow_color));
    }
  }

  // Transparency is used to skip pixels that are not shadowed.
  AddDraw(std::move(draw), node_bounds, DrawObjectManager::kBlendSrcAlpha);
}

void RenderTreeNodeVisitor::Visit(render_tree::TextNode* text_node) {
  if (!IsVisible(text_node->GetBounds())) {
    return;
  }

  FallbackRasterize(text_node);
}

int64_t RenderTreeNodeVisitor::GetFallbackRasterizeCount() {
  return fallback_rasterize_count_;
}

// Get a scratch texture row region for use in rendering |node|.
void RenderTreeNodeVisitor::GetScratchTexture(
    scoped_refptr<render_tree::Node> node, float size,
    DrawObject::TextureInfo* out_texture_info) {
  // Get the cached texture region or create one.
  OffscreenTargetManager::TargetInfo target_info;
  bool cached = offscreen_target_manager_->GetCachedTarget(
      node.get(), base::Bind(&OffscreenTargetErrorFunction1D, size),
      &target_info);
  if (!cached) {
    offscreen_target_manager_->AllocateCachedTarget(node.get(), size, size,
                                                    &target_info);
  }

  out_texture_info->texture = target_info.framebuffer == nullptr
                                  ? nullptr
                                  : target_info.framebuffer->GetColorTexture();
  out_texture_info->region = target_info.region;
  out_texture_info->is_new = !cached;
}

// Get a cached offscreen target to render |node|.
// |out_content_cached| is true if the node's contents are already cached in
//   the returned offscreen target.
// |out_target_info| describes the offscreen surface into which |node| should
//   be rendered.
// |out_content_rect| is the onscreen rect (already in screen space) where the
//   offscreen contents should be rendered.
void RenderTreeNodeVisitor::GetCachedTarget(
    scoped_refptr<render_tree::Node> node, bool* out_content_cached,
    OffscreenTargetManager::TargetInfo* out_target_info,
    math::RectF* out_content_rect) {
  math::RectF node_bounds(node->GetBounds());
  if (node->GetTypeId() == base::GetTypeId<render_tree::TextNode>()) {
    // Work around bug with text width calculation being slightly too small for
    // cursive text.
    node_bounds.set_width(node_bounds.width() * 1.01f);
  }
  math::RectF mapped_bounds(draw_state_.transform.MapRect(node_bounds));
  if (mapped_bounds.IsEmpty()) {
    *out_content_cached = true;
    out_content_rect->SetRect(0.0f, 0.0f, 0.0f, 0.0f);
    return;
  }

  // Request a slightly larger render target than the calculated bounds. The
  // rasterizer may use an extra pixel along the edge of anti-aliased objects.
  *out_content_rect = RoundOut(mapped_bounds, 1.0f);

  // Get a suitable cache of the render tree node if one exists, or allocate
  // a new offscreen target if possible. The OffscreenTargetErrorFunction will
  // determine whether any caches are fit for use.

  // Do not cache rotating nodes since these will result in inappropriate
  // reuse of offscreen targets. Transforms that are rotations of angles in
  // the first quadrant will produce the same mapped rect sizes as angles in
  // the other 3 quadrants. Also avoid caching reflections.
  bool allow_caching =
      cobalt::math::IsOnlyScaleAndTranslate(draw_state_.transform) &&
      draw_state_.transform(0, 0) > 0.0f && draw_state_.transform(1, 1) > 0.0f;
  if (allow_caching) {
    *out_content_cached = offscreen_target_manager_->GetCachedTarget(
        node.get(), base::Bind(&OffscreenTargetErrorFunction, mapped_bounds),
        out_target_info);
    if (!(*out_content_cached)) {
      offscreen_target_manager_->AllocateCachedTarget(
          node.get(), out_content_rect->size(), mapped_bounds, out_target_info);
    } else {
      // Maintain the size of the cached contents to avoid scaling artifacts.
      out_content_rect->set_size(out_target_info->region.size());
    }
  } else {
    *out_content_cached = false;
    out_target_info->framebuffer = nullptr;
  }

  // If no offscreen target could be allocated, then the render tree node will
  // be rendered directly onto the current render target. Use the draw scissor
  // to minimize what has to be drawn.
  if (out_target_info->framebuffer == nullptr) {
    out_content_rect->Intersect(draw_state_.scissor);
  }
}

void RenderTreeNodeVisitor::FallbackRasterize(
    scoped_refptr<render_tree::Node> node) {
  OffscreenTargetManager::TargetInfo target_info;
  math::RectF content_rect;

  if (node->GetTypeId() != base::GetTypeId<render_tree::TextNode>()) {
    ++fallback_rasterize_count_;
  }

  // Retrieve the previously cached contents or try to allocate a cached
  // render target for the node.
  bool content_is_cached = false;
  GetCachedTarget(node, &content_is_cached, &target_info, &content_rect);

  if (content_rect.IsEmpty()) {
    return;
  }

  // If no offscreen target was available, then just render directly onto the
  // current render target.
  if (target_info.framebuffer == nullptr) {
    base::Closure rasterize_callback =
        base::Bind(fallback_rasterize_, node, fallback_render_target_,
                   draw_state_.transform, content_rect, draw_state_.opacity,
                   kFallbackShouldFlush);
    std::unique_ptr<DrawObject> draw(new DrawCallback(rasterize_callback));
    AddExternalDraw(std::move(draw), content_rect, node->GetTypeId());
    return;
  }

  // Setup draw for the contents as needed.
  if (!content_is_cached) {
    // Cache the results when drawn with 100% opacity, then draw the cached
    // results at the desired opacity. This avoids having to generate different
    // caches under varying opacity filters.
    float old_opacity = draw_state_.opacity;
    draw_state_.opacity = 1.0f;
    FallbackRasterize(node, target_info, content_rect);
    draw_state_.opacity = old_opacity;
  }

  // Sub-pixel offsets are passed to the fallback rasterizer to preserve
  // sharpness. The results should be drawn to |content_rect| which is already
  // in screen space.
  math::Matrix3F old_transform = draw_state_.transform;
  draw_state_.transform = math::Matrix3F::Identity();

  // Create the appropriate draw object to call the draw callback, then render
  // its results onscreen. A transparent draw must be used even if the current
  // opacity is 100% because the contents may have transparency.
  backend::TextureEGL* texture = target_info.framebuffer->GetColorTexture();
  math::Matrix3F texcoord_transform = GetTexcoordTransform(target_info);
  if (IsOpaque(draw_state_.opacity)) {
    std::unique_ptr<DrawObject> draw(
        new DrawRectTexture(graphics_state_, draw_state_, content_rect, texture,
                            texcoord_transform));
    AddDraw(std::move(draw), content_rect, DrawObjectManager::kBlendSrcAlpha);
  } else {
    std::unique_ptr<DrawObject> draw(new DrawRectColorTexture(
        graphics_state_, draw_state_, content_rect, kOpaqueWhite, texture,
        texcoord_transform, false /* clamp_texcoords */));
    AddDraw(std::move(draw), content_rect, DrawObjectManager::kBlendSrcAlpha);
  }

  draw_state_.transform = old_transform;
}

void RenderTreeNodeVisitor::FallbackRasterize(
    scoped_refptr<render_tree::Node> node,
    const OffscreenTargetManager::TargetInfo& target_info,
    const math::RectF& content_rect) {
  uint32_t rasterize_flags = 0;

  // Pre-translate the content so it starts in target_info.region.
  math::Matrix3F content_transform =
      math::TranslateMatrix(target_info.region.x() - content_rect.x(),
                            target_info.region.y() - content_rect.y()) *
      draw_state_.transform;
  base::Closure rasterize_callback = base::Bind(
      fallback_rasterize_, node, target_info.skia_canvas, content_transform,
      target_info.region, draw_state_.opacity, rasterize_flags);
  std::unique_ptr<DrawObject> draw(new DrawCallback(rasterize_callback));

  draw_object_manager_->AddBatchedExternalDraw(
      std::move(draw), node->GetTypeId(), target_info.framebuffer,
      target_info.region);
}

// Add draw objects to render |node| to an offscreen render target.
// |limit_to_screen_size| specifies whether the allocated render target should
//   be limited to the onscreen render target size.
// |out_texture| and |out_texcoord_transform| describe the texture subregion
//   that will contain the result of rendering |node|.
// |out_content_rect| describes the onscreen rect (in screen space) which
//   should be used to render node's contents. This will be IsEmpty() if
//   nothing needs to be rendered.
void RenderTreeNodeVisitor::OffscreenRasterize(
    scoped_refptr<render_tree::Node> node, bool limit_to_screen_size,
    const backend::TextureEGL** out_texture,
    math::Matrix3F* out_texcoord_transform, math::RectF* out_content_rect) {
  // Map the target to world space. This avoids scaling artifacts if the target
  // is magnified.
  math::RectF mapped_bounds = draw_state_.transform.MapRect(node->GetBounds());

  if (!mapped_bounds.IsExpressibleAsRect()) {
    DLOG(WARNING) << "Invalid rectangle of " << mapped_bounds.ToString()
                  << " will not be rendered";
    return;
  }

  // Check whether the node is visible.
  math::RectF rounded_out_bounds = RoundOut(mapped_bounds, 0.0f);
  math::RectF clipped_bounds =
      math::IntersectRects(rounded_out_bounds, draw_state_.scissor);

  if (clipped_bounds.IsEmpty()) {
    out_content_rect->SetRect(0.0f, 0.0f, 0.0f, 0.0f);
    return;
  }

  // Allocate an uncached render target. The smallest render target needed is
  // the clipped bounds' size. However, this may be involved in an animation,
  // so use the mapped size limited to the maximum visible area. This increases
  // the chance that the render target can be recycled in the next frame.
  OffscreenTargetManager::TargetInfo target_info;
  math::SizeF target_size(rounded_out_bounds.size());
  if (limit_to_screen_size) {
    target_size.SetToMin(onscreen_render_target_->GetSize());
  }
  offscreen_target_manager_->AllocateUncachedTarget(target_size, &target_info);

  if (!target_info.framebuffer) {
    LOG(ERROR) << "Could not allocate framebuffer (" << target_size.width()
               << "x" << target_size.height()
               << ") for offscreen rasterization.";
    out_content_rect->SetRect(0.0f, 0.0f, 0.0f, 0.0f);
    return;
  }

  // Only the clipped bounds will be rendered.
  DCHECK_GE(target_info.region.width(), clipped_bounds.width());
  DCHECK_GE(target_info.region.height(), clipped_bounds.height());
  target_info.region.set_size(clipped_bounds.size());
  *out_content_rect = clipped_bounds;
  *out_texture = target_info.framebuffer->GetColorTexture();
  *out_texcoord_transform = GetTexcoordTransform(target_info);

  // Push a new render state to rasterize to the offscreen render target.
  DrawObject::BaseState old_draw_state = draw_state_;
  SkCanvas* old_fallback_render_target = fallback_render_target_;
  backend::RenderTarget* old_render_target = render_target_;
  fallback_render_target_ = target_info.skia_canvas;
  render_target_ = target_info.framebuffer;

  // The contents of this new render target will be used in a draw call to the
  // previous render target. Inform the draw object manager of this dependency
  // so it can sort offscreen draws appropriately.
  draw_object_manager_->AddRenderTargetDependency(old_render_target,
                                                  render_target_);

  // Clear the new render target. (Set the transform to the identity matrix so
  // the bounds for the DrawClear comes out as the entire target region.)
  draw_state_.scissor = math::Rect::RoundFromRectF(target_info.region);
  draw_state_.transform = math::Matrix3F::Identity();
  std::unique_ptr<DrawObject> draw_clear(
      new DrawClear(graphics_state_, draw_state_, kTransparentBlack));
  AddDraw(std::move(draw_clear), target_info.region,
          DrawObjectManager::kBlendNone);

  // Adjust the transform to render into target_info.region.
  draw_state_.transform =
      math::TranslateMatrix(target_info.region.x() - clipped_bounds.x(),
                            target_info.region.y() - clipped_bounds.y()) *
      old_draw_state.transform;

  node->Accept(this);

  draw_state_ = old_draw_state;
  fallback_render_target_ = old_fallback_render_target;
  render_target_ = old_render_target;
}

bool RenderTreeNodeVisitor::IsVisible(const math::RectF& bounds) {
  math::RectF rect_bounds = draw_state_.transform.MapRect(bounds);
  math::RectF intersection = IntersectRects(rect_bounds, draw_state_.scissor);
  return !intersection.IsEmpty();
}

void RenderTreeNodeVisitor::AddDraw(std::unique_ptr<DrawObject> object,
                                    const math::RectF& local_bounds,
                                    DrawObjectManager::BlendType blend_type) {
  base::TypeId draw_type = object->GetTypeId();
  math::RectF mapped_bounds = draw_state_.transform.MapRect(local_bounds);
  if (render_target_ != onscreen_render_target_) {
    last_draw_id_ = draw_object_manager_->AddOffscreenDraw(
        std::move(object), blend_type, draw_type, render_target_,
        mapped_bounds);
  } else {
    last_draw_id_ = draw_object_manager_->AddOnscreenDraw(
        std::move(object), blend_type, draw_type, render_target_,
        mapped_bounds);
  }
}

void RenderTreeNodeVisitor::AddExternalDraw(std::unique_ptr<DrawObject> object,
                                            const math::RectF& world_bounds,
                                            base::TypeId draw_type) {
  if (render_target_ != onscreen_render_target_) {
    last_draw_id_ = draw_object_manager_->AddOffscreenDraw(
        std::move(object), DrawObjectManager::kBlendExternal, draw_type,
        render_target_, world_bounds);
  } else {
    last_draw_id_ = draw_object_manager_->AddOnscreenDraw(
        std::move(object), DrawObjectManager::kBlendExternal, draw_type,
        render_target_, world_bounds);
  }
}

void RenderTreeNodeVisitor::AddClear(const math::RectF& rect,
                                     const render_tree::ColorRGBA& color) {
  // Check to see if we're simply trying to clear a non-transformed rectangle
  // on the screen with no filters or effects applied, and if so, issue a
  // clear command instead of a more general draw command, to give the GL
  // driver a better chance to optimize.
  if (!draw_state_.rounded_scissor_corners &&
      draw_state_.transform.IsIdentity() && IsOpaque(draw_state_.opacity)) {
    math::Rect old_scissor = draw_state_.scissor;
    draw_state_.scissor.Intersect(math::Rect::RoundFromRectF(rect));
    std::unique_ptr<DrawObject> draw_clear(
        new DrawClear(graphics_state_, draw_state_, color));
    AddDraw(std::move(draw_clear), rect, DrawObjectManager::kBlendNone);
    draw_state_.scissor = old_scissor;
  } else {
    std::unique_ptr<DrawObject> draw(
        new DrawPolyColor(graphics_state_, draw_state_, rect, color));
    AddDraw(std::move(draw), rect, DrawObjectManager::kBlendNone);
  }
}

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

#endif  // SB_API_VERSION >= 12 || SB_HAS(GLES2)
