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

#ifndef COBALT_RENDERER_RASTERIZER_BLITTER_RENDER_STATE_H_
#define COBALT_RENDERER_RASTERIZER_BLITTER_RENDER_STATE_H_

#include <algorithm>
#include <stack>

#include "base/logging.h"
#include "cobalt/math/matrix3_f.h"
#include "cobalt/math/rect.h"
#include "cobalt/math/rect_f.h"
#include "cobalt/math/vector2d_f.h"
#include "cobalt/render_tree/brush.h"
#include "starboard/blitter.h"

#if SB_HAS(BLITTER)

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

// Keeps track of the current scale/offset transforms.  Note that while the
// render tree supports general affine transformations, the Starboard Blitter
// API only supports scale and translations, so we maintain only those.  If
// rotations are used, we can fallback to software rendering.
class Transform {
 public:
  Transform() : scale_(1.0f, 1.0f), translate_(0.0f, 0.0f) {}

  explicit Transform(const math::Matrix3F& matrix)
      : scale_(matrix.Get(0, 0), matrix.Get(1, 1)),
        translate_(matrix.Get(0, 2), matrix.Get(1, 2)) {
    // We cannot handle sheers and rotations.
    DCHECK_EQ(0, matrix.Get(0, 1));
    DCHECK_EQ(0, matrix.Get(1, 0));
  }

  Transform(const math::Vector2dF& scale, const math::Vector2dF& translate)
      : scale_(scale), translate_(translate) {}

  const math::Vector2dF& scale() const { return scale_; }
  const math::Vector2dF& translate() const { return translate_; }

  void ApplyOffset(const math::Vector2dF& offset) {
    translate_ +=
        math::Vector2dF(scale_.x() * offset.x(), scale_.y() * offset.y());
  }
  void ApplyScale(const math::Vector2dF& scale_mult) {
    scale_.Scale(scale_mult.x(), scale_mult.y());
  }

  math::RectF TransformRect(const math::RectF& rect) const {
    return math::RectF(rect.x() * scale_.x() + translate_.x(),
                       rect.y() * scale_.y() + translate_.y(),
                       rect.width() * scale_.x(), rect.height() * scale_.y());
  }

  math::Matrix3F ToMatrix() const {
    return math::Matrix3F::FromValues(scale_.x(), 0, translate_.x(), 0,
                                      scale_.y(), translate_.y(), 0, 0, 1);
  }

 private:
  math::Vector2dF scale_;
  math::Vector2dF translate_;
};

// Helper class to manage the pushing and popping of rectangular bounding
// boxes.  This manages intersecting newly pushed bounding boxes with the
// existing stack of bounding boxes.
class BoundsStack {
 public:
  // Helper class to scope a pair of Push()/Pop() calls.
  class ScopedPush {
   public:
    ScopedPush(BoundsStack* stack, const math::Rect& bounds) : stack_(stack) {
      stack_->Push(bounds);
    }
    ~ScopedPush() { stack_->Pop(); }

   private:
    BoundsStack* stack_;
  };

  BoundsStack(SbBlitterContext context, const math::Rect& initial_bounds);
  void Push(const math::Rect& bounds);
  void Pop();

  const math::Rect& Top() const { return bounds_.top(); }

  // Updates the SbBlitterContext object with the current top of the stack.
  void UpdateContext();

 private:
  SbBlitterContext context_;
  std::stack<math::Rect> bounds_;
};

// The full render state used by the Blitter API RenderTreeNodeVisitor.
// Packages together a render target, current transform and clip stack.
struct RenderState {
  RenderState(SbBlitterRenderTarget render_target, const Transform& transform,
              const BoundsStack& bounds_stack)
      : render_target(render_target),
        transform(transform),
        bounds_stack(bounds_stack),
        opacity(1.0f)
#if defined(ENABLE_DEBUGGER)
        ,
        highlight_software_draws(false)
#endif  // defined(ENABLE_DEBUGGER)
  {
  }

  SbBlitterRenderTarget render_target;
  Transform transform;
  BoundsStack bounds_stack;
  float opacity;

#if defined(ENABLE_DEBUGGER)
  // If true, all software rasterization results are replaced with a green
  // fill rectangle.  Thus, if the software cache is used, one will see a flash
  // of green every time something is registered with the cache.
  bool highlight_software_draws;
#endif  // defined(ENABLE_DEBUGGER)
};

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

#endif  // #if SB_HAS(BLITTER)

#endif  // COBALT_RENDERER_RASTERIZER_BLITTER_RENDER_STATE_H_
