// Copyright 2016 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef COBALT_RENDERER_RASTERIZER_SKIA_SURFACE_CACHE_DELEGATE_H_
#define COBALT_RENDERER_RASTERIZER_SKIA_SURFACE_CACHE_DELEGATE_H_

#include <string>

#include "base/callback.h"
#include "base/optional.h"
#if defined(ENABLE_DEBUG_CONSOLE)
#include "cobalt/base/console_commands.h"
#endif
#include "cobalt/renderer/rasterizer/common/offscreen_render_coordinate_mapping.h"
#include "cobalt/renderer/rasterizer/common/surface_cache.h"
#include "cobalt/renderer/rasterizer/skia/render_tree_node_visitor_draw_state.h"
#include "third_party/skia/include/core/SkSurface.h"

namespace cobalt {
namespace renderer {
namespace rasterizer {
namespace skia {

// Implements skia-specific cache recording and playback surface management
// in order to provide skia-support for the render tree surface caching system.
class SurfaceCacheDelegate : public common::SurfaceCache::Delegate {
 private:
  class CachedSurface : public common::SurfaceCache::CachedSurface {
   public:
    CachedSurface(SkSurface* surface, const math::Vector2dF& output_post_scale,
                  const math::Vector2dF& output_pre_translate,
                  const math::Rect& output_bounds)
        : surface_(surface),
          image_(surface_ ? surface_->newImageSnapshot() : NULL),
          output_post_scale_(output_post_scale),
          output_pre_translate_(output_pre_translate),
          output_bounds_(output_bounds) {}
    ~CachedSurface() OVERRIDE {}

    SkImage* image() const { return image_.get(); }
    const math::Vector2dF& output_post_scale() const {
      return output_post_scale_;
    }
    const math::Vector2dF& output_pre_translate() const {
      return output_pre_translate_;
    }
    const math::Rect& output_bounds() const { return output_bounds_; }

   private:
    // The actual skia surface representing the cached render tree.
    SkAutoTUnref<SkSurface> surface_;
    // For convenience, we save the image snapshot associated with |surface_|
    // above.
    SkAutoTUnref<SkImage> image_;
    // When applying |surface_| to another render target, the current
    // transformation should be post-multiplied by |output_post_scale_|, and
    // pre-multiplied by |output_pre_translate_|.
    math::Vector2dF output_post_scale_;
    math::Vector2dF output_pre_translate_;
    // The rectangle coordinates into which |surface_| should be rendered.
    math::Rect output_bounds_;
  };

 public:
  typedef base::Callback<SkSurface*(const math::Size&)> CreateSkSurfaceFunction;

  // Creating a ScopedContext object declares a render tree visitor context,
  // and so there should be one ScopedContext per render tree visitor.  Since
  // it is typical to recursively create sub render tree visitors, this class
  // is designed to be instantiated multiple times on the same
  // SurfaceCacheDelegate object.
  class ScopedContext {
   public:
    ScopedContext(SurfaceCacheDelegate* delegate,
                  RenderTreeNodeVisitorDrawState* draw_state)
        : delegate_(delegate), old_draw_state_(delegate_->draw_state_) {
      // Setup our new draw state (including render target) to the provided one.
      delegate_->draw_state_ = draw_state;

      // A new canvas may mean a new total matrix, so inform our delegate to
      // refresh its scale.
      delegate_->UpdateCanvasScale();
    }
    ~ScopedContext() {
      // Restore the draw state to the old setting.
      delegate_->draw_state_ = old_draw_state_;

      if (delegate_->draw_state_) {
        delegate_->UpdateCanvasScale();
      }
    }

   private:
    SurfaceCacheDelegate* delegate_;
    RenderTreeNodeVisitorDrawState* old_draw_state_;
  };

  SurfaceCacheDelegate(
      const CreateSkSurfaceFunction& create_sk_surface_function,
      const math::Size& max_surface_size);

  // Must be called every time our client changes the current scale on us, e.g.
  // when visiting a MatrixTransformNode.
  void UpdateCanvasScale();

  void ApplySurface(common::SurfaceCache::CachedSurface* surface) OVERRIDE;
  void StartRecording(const math::RectF& local_bounds) OVERRIDE;
  common::SurfaceCache::CachedSurface* EndRecording() OVERRIDE;
  void ReleaseSurface(common::SurfaceCache::CachedSurface* surface) OVERRIDE;
  math::Size GetRenderSize(const math::SizeF& local_size) OVERRIDE;
  math::Size MaximumSurfaceSize() OVERRIDE;

 private:
  // Defines a set of data that is relevant only while recording.
  struct RecordingData {
    RecordingData(const RenderTreeNodeVisitorDrawState& original_draw_state,
                  const common::OffscreenRenderCoordinateMapping& coord_mapping,
                  SkSurface* surface)
        : original_draw_state(original_draw_state),
          coord_mapping(coord_mapping),
          surface(surface) {}

    // The original draw state (including render target/canvas) that the
    // recorded draw calls would have otherwise targeted if we were not
    // recording.
    RenderTreeNodeVisitorDrawState original_draw_state;

    // Information about how to map the offscreen cached surface to the main
    // render target.
    common::OffscreenRenderCoordinateMapping coord_mapping;

    // The offscreen cached surface that we are recording to.
    SkSurface* surface;
  };

#if defined(ENABLE_DEBUG_CONSOLE)
  void OnToggleCacheHighlights(const std::string& message);
#endif

  // A function that will return a fresh SkSurface object when we need to cache
  // something new.
  CreateSkSurfaceFunction create_sk_surface_function_;

  // The maximum size of an SkSurface.
  math::Size max_surface_size_;

  // The current draw state (including the SkCanvas) that is being targeted,
  // whether its the main onscreen surface or a cached surface.
  RenderTreeNodeVisitorDrawState* draw_state_;

  // If we are currently recording, this will contain all of the data relevant
  // to that recording.
  base::optional<RecordingData> recording_data_;

  // The current scale of draw_state_->render_target->getTotalMatrix().  This
  // lets us quickly check if the scale of a render node changes from the last
  // time we observed it, which may happen if an animation is targeting a
  // MatrixTransformNode render tree node.
  math::Vector2dF scale_;

#if defined(ENABLE_DEBUG_CONSOLE)
  // Debug command to toggle cache highlights to help visualize which nodes
  // are being cached.
  bool toggle_cache_highlights_;
  base::ConsoleCommandManager::CommandHandler
      toggle_cache_highlights_command_handler_;
#endif
};

}  // namespace skia
}  // namespace rasterizer
}  // namespace renderer
}  // namespace cobalt

#endif  // COBALT_RENDERER_RASTERIZER_SKIA_SURFACE_CACHE_DELEGATE_H_
