// 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/image.h"

#include "base/bind.h"
#include "cobalt/render_tree/image.h"
#include "cobalt/renderer/backend/blitter/surface_render_target.h"
#include "cobalt/renderer/rasterizer/blitter/render_tree_blitter_conversions.h"
#include "cobalt/renderer/rasterizer/blitter/skia_blitter_conversions.h"
#include "cobalt/renderer/rasterizer/skia/image.h"
#include "starboard/blitter.h"

#if SB_API_VERSION < SB_BLITTER_DEPRECATED_VERSION && SB_HAS(BLITTER)

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

ImageData::ImageData(SbBlitterDevice device, const math::Size& size,
                     render_tree::PixelFormat pixel_format,
                     render_tree::AlphaFormat alpha_format)
    : device_(device),
      pixel_data_(SbBlitterCreatePixelData(
          device_, size.width(), size.height(),
          RenderTreePixelFormatToBlitter(pixel_format))) {
  CHECK(alpha_format == render_tree::kAlphaFormatPremultiplied ||
        alpha_format == render_tree::kAlphaFormatOpaque);

  if (SbBlitterIsPixelDataValid(pixel_data_)) {
    descriptor_.emplace(size, pixel_format, alpha_format,
                        SbBlitterGetPixelDataPitchInBytes(pixel_data_));
  } else {
    LOG(ERROR) << "Failed to allocate pixel data for image.";
  }
}

ImageData::~ImageData() {
  if (SbBlitterIsPixelDataValid(pixel_data_)) {
    SbBlitterDestroyPixelData(pixel_data_);
  }
}

uint8* ImageData::GetMemory() {
  if (!SbBlitterIsPixelDataValid(pixel_data_)) {
    return NULL;
  } else {
    return static_cast<uint8*>(SbBlitterGetPixelDataPointer(pixel_data_));
  }
}

SbBlitterPixelData ImageData::TakePixelData() {
  SbBlitterPixelData pixel_data = pixel_data_;
  pixel_data_ = kSbBlitterInvalidPixelData;
  return pixel_data;
}

SinglePlaneImage::SinglePlaneImage(std::unique_ptr<ImageData> image_data)
    : size_(image_data->GetDescriptor().size) {
  surface_ = SbBlitterCreateSurfaceFromPixelData(image_data->device(),
                                                 image_data->TakePixelData());
  CHECK(SbBlitterIsSurfaceValid(surface_));

  is_opaque_ = image_data->GetDescriptor().alpha_format ==
               render_tree::kAlphaFormatOpaque;
}

SinglePlaneImage::SinglePlaneImage(SbBlitterSurface surface, bool is_opaque,
                                   const base::Closure& delete_function)
    : surface_(surface),
      is_opaque_(is_opaque),
      delete_function_(delete_function) {
  CHECK(SbBlitterIsSurfaceValid(surface_));
  SbBlitterSurfaceInfo info;
  if (!SbBlitterGetSurfaceInfo(surface_, &info)) {
    NOTREACHED();
  }
  size_ = math::Size(info.width, info.height);
}

SinglePlaneImage::SinglePlaneImage(
    const scoped_refptr<render_tree::Node>& root,
    SubmitOffscreenCallback submit_offscreen_callback, SbBlitterDevice device)
    : size_(static_cast<int>(root->GetBounds().right()),
            static_cast<int>(root->GetBounds().bottom())),
      is_opaque_(false),
      surface_(kSbBlitterInvalidSurface) {
  initialize_image_ = base::Bind(
      &SinglePlaneImage::InitializeImageFromRenderTree, base::Unretained(this),
      root, submit_offscreen_callback, device);
}

bool SinglePlaneImage::EnsureInitialized() {
  if (!initialize_image_.is_null()) {
    initialize_image_.Run();
    initialize_image_.Reset();
    return true;
  }
  return false;
}

const sk_sp<SkImage>& SinglePlaneImage::GetImage() const {
  // This function will only ever get called if the Skia software renderer needs
  // to reference the image, and so should be called rarely.  In that case, the
  // first time it is called on this image, we will download the image data from
  // the Blitter API surface into a SkBitmap object where the pixel data lives
  // in CPU memory.  It will then create an SkImage from that SkBitmap object,
  // and the pointer to the new SkImage object will be returned.
  if (!image_) {
    SkImageInfo image_info = SkImageInfo::Make(
        size_.width(), size_.height(), kN32_SkColorType, kPremul_SkAlphaType);

    SkBitmap bitmap;
    bool allocation_successful = bitmap.tryAllocPixels(image_info);
    if (!allocation_successful) {
      LOG(WARNING) << "Unable to allocate pixels of size " << size_.width()
                   << "x" << size_.height();
      return image_;
    }
    bool result = SbBlitterDownloadSurfacePixels(
        surface_, SkiaToBlitterPixelFormat(image_info.colorType()),
        bitmap.rowBytes(), bitmap.getPixels());
    if (!result) {
      LOG(WARNING) << "Failed to download surface pixel data so that it could "
                      "be accessed by software skia.";
      NOTREACHED();
    } else {
      image_ = SkImage::MakeFromBitmap(bitmap);
    }
  }

  return image_;
}

SinglePlaneImage::~SinglePlaneImage() {
  if (!delete_function_.is_null()) {
    delete_function_.Run();
  } else {
    SbBlitterDestroySurface(surface_);
  }
}

void SinglePlaneImage::InitializeImageFromRenderTree(
    const scoped_refptr<render_tree::Node>& root,
    const SubmitOffscreenCallback& submit_offscreen_callback,
    SbBlitterDevice device) {
  scoped_refptr<backend::SurfaceRenderTargetBlitter> render_target(
      new backend::SurfaceRenderTargetBlitter(device, size_));

  submit_offscreen_callback.Run(root, render_target);
  surface_ = render_target->TakeSbSurface();
  CHECK(SbBlitterIsSurfaceValid(surface_));
}

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

#endif  // SB_API_VERSION < SB_BLITTER_DEPRECATED_VERSION && SB_HAS(BLITTER)
