// 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_IMAGE_H_
#define COBALT_RENDERER_RASTERIZER_BLITTER_IMAGE_H_

#include <memory>
#include <string>

#include "base/callback.h"
#include "base/memory/aligned_memory.h"
#include "base/optional.h"
#include "cobalt/base/polymorphic_downcast.h"
#include "cobalt/render_tree/font.h"
#include "cobalt/render_tree/font_provider.h"
#include "cobalt/render_tree/image.h"
#include "cobalt/render_tree/resource_provider.h"
#include "cobalt/renderer/backend/blitter/render_target.h"
#include "cobalt/renderer/rasterizer/skia/image.h"
#include "starboard/blitter.h"

#if SB_HAS(BLITTER)

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

typedef base::Callback<void(
    const scoped_refptr<render_tree::Node>& render_tree,
    const scoped_refptr<backend::RenderTarget>& render_target)>
    SubmitOffscreenCallback;

// render_tree::ImageData objects are implemented in the Blitter API via the
// SbBlitterPixelData objects, which is conceptually an exact match for
// ImageData.
class ImageData : public render_tree::ImageData {
 public:
  ImageData(SbBlitterDevice device, const math::Size& size,
            render_tree::PixelFormat pixel_format,
            render_tree::AlphaFormat alpha_format);
  ~ImageData() override;

  const render_tree::ImageDataDescriptor& GetDescriptor() const override {
    return *descriptor_;
  }

  uint8* GetMemory() override;

  SbBlitterPixelData TakePixelData();
  SbBlitterDevice device() { return device_; }

 private:
  SbBlitterDevice device_;
  SbBlitterPixelData pixel_data_;
  base::Optional<render_tree::ImageDataDescriptor> descriptor_;
};

// render_tree::Image objects are implemented in the Blitter API via
// SbBlitterSurface objects, which are conceptually an exact match for Image.
// We derive from skia::SinglePlaneImage here because it is possible for
// render tree nodes referencing blitter:Images to be passed into a Skia
// software renderer.  Thus, SinglePlaneImage is implemented such
// that Skia render tree node visitors can also render it.
class SinglePlaneImage : public skia::SinglePlaneImage {
 public:
  explicit SinglePlaneImage(std::unique_ptr<ImageData> image_data);
  // If |delete_function| is provided, it will be called in the destructor
  // instead of manually calling SbBlitterDestroySurface(surface_).
  SinglePlaneImage(SbBlitterSurface surface, bool is_opaque,
                   const base::Closure& delete_function);

  SinglePlaneImage(const scoped_refptr<render_tree::Node>& root,
                   SubmitOffscreenCallback submit_offscreen_callback,
                   SbBlitterDevice device);

  const math::Size& GetSize() const override { return size_; }

  SbBlitterSurface surface() const { return surface_; }

  // Overrides from skia::SinglePlaneImage.
  bool EnsureInitialized() override;

  // When GetImage() is called on a blitter::SinglePlaneImage for the first
  // time, we do a one-time download of the pixel data from the Blitter API
  // surface into a SkImage.
  const sk_sp<SkImage>& GetImage() const override;

  bool IsOpaque() const override { return is_opaque_; }

 private:
  ~SinglePlaneImage() override;

  void InitializeImageFromRenderTree(
      const scoped_refptr<render_tree::Node>& root,
      const SubmitOffscreenCallback& submit_offscreen_callback,
      SbBlitterDevice device);

  math::Size size_;
  SbBlitterSurface surface_;

  bool is_opaque_;

  // This field is populated when GetBitmap() is called for the first time, and
  // after that is never modified.
  mutable sk_sp<SkImage> image_;

  // If |delete_function| is provided, it will be called in the destructor
  // instead of manually calling SbBlitterDestroySurface(surface_).
  base::Closure delete_function_;

  // This closure binds the image construction parameters so that we can delay
  // construction of it until it is accessed by the rasterizer thread.
  base::Closure initialize_image_;
};

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

#endif  // #if SB_HAS(BLITTER)

#endif  // COBALT_RENDERER_RASTERIZER_BLITTER_IMAGE_H_
