// Copyright 2014 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/skia/software_image.h"

#include "base/memory/aligned_memory.h"
#include "cobalt/renderer/rasterizer/skia/cobalt_skia_type_conversions.h"

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

SoftwareImageData::SoftwareImageData(const math::Size& size,
                                     render_tree::PixelFormat pixel_format,
                                     render_tree::AlphaFormat alpha_format)
    : descriptor_(size, pixel_format, alpha_format,
                  size.width() * render_tree::BytesPerPixel(pixel_format)),
      pixel_data_(new uint8_t[size.height() * descriptor_.pitch_in_bytes]) {}

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

uint8_t* SoftwareImageData::GetMemory() { return pixel_data_.get(); }

std::unique_ptr<uint8_t[]> SoftwareImageData::PassPixelData() {
  return std::move(pixel_data_);
}

SoftwareImage::SoftwareImage(std::unique_ptr<SoftwareImageData> source_data) {
  owned_pixel_data_ = source_data->PassPixelData();
  Initialize(owned_pixel_data_.get(), source_data->GetDescriptor());
}

SoftwareImage::SoftwareImage(
    uint8_t* source_data, const render_tree::ImageDataDescriptor& descriptor) {
  Initialize(source_data, descriptor);
}

namespace {
// Converts UV8 texture data to an ARGB SkBitmap where the original U channel is
// found in the B channel, the original V channel is found in the A channel, and
// the R and G channels are zeroed out.
void ConvertUV8ToARGBSkBitmap(
    uint8_t* source_data, const render_tree::ImageDataDescriptor& descriptor,
    SkBitmap* bitmap) {
  bitmap->allocN32Pixels(descriptor.size.width(), descriptor.size.height());
  int row_pixels_dest = bitmap->rowBytes() / bitmap->bytesPerPixel();

  uint8_t* current_src = source_data;
  SkColor* current_dest = static_cast<SkColor*>(bitmap->getPixels());
  for (int row = 0; row < descriptor.size.height(); ++row) {
    for (int column = 0; column < descriptor.size.width(); ++column) {
      current_dest[column] = SkColorSetARGB(current_src[column * 2 + 1], 0, 0,
                                            current_src[column * 2 + 0]);
    }
    current_dest += row_pixels_dest;
    current_src += descriptor.pitch_in_bytes;
  }
}
}  // namespace

void SoftwareImage::Initialize(
    uint8_t* source_data, const render_tree::ImageDataDescriptor& descriptor) {
  is_opaque_ = (descriptor.alpha_format == render_tree::kAlphaFormatOpaque);
  SkAlphaType skia_alpha_format =
      RenderTreeAlphaFormatToSkia(descriptor.alpha_format);
  DCHECK_EQ(kPremul_SkAlphaType, skia_alpha_format);

  size_ = descriptor.size;

  if (descriptor.pixel_format == render_tree::kPixelFormatUV8) {
    // TODO: SKIA_M61_UNFINISHED_IMPLEMENATION: fix me
    // Convert UV8 to ARGB because Skia does not support any two-channel
    // formats.  This of course is not efficient, but efficiency in the software
    // renderer is not as important as completeness and correctness.
    // ConvertUV8ToARGBSkBitmap(source_data, descriptor, image_.get());
    NOTREACHED() << "Need to do this..";
  } else {
// Check that the incoming pixel data is indeed in premultiplied alpha
// format.
#if !defined(NDEBUG)
    Image::DCheckForPremultipliedAlpha(descriptor.size,
                                       descriptor.pitch_in_bytes,
                                       descriptor.pixel_format, source_data);
#endif
    // Convert our incoming pixel data from unpremultiplied alpha to
    // premultiplied alpha format, which is what Skia expects.
    SkImageInfo premul_image_info = SkImageInfo::Make(
        descriptor.size.width(), descriptor.size.height(),
        RenderTreeSurfaceFormatToSkia(descriptor.pixel_format),
        skia_alpha_format);
    SkBitmap bitmap;
    bitmap.installPixels(premul_image_info, source_data,
                         descriptor.pitch_in_bytes);
    image_ = SkImage::MakeFromBitmap(bitmap);
  }
}

SoftwareRawImageMemory::SoftwareRawImageMemory(size_t size_in_bytes,
                                               size_t alignment)
    : size_in_bytes_(size_in_bytes),
      pixel_data_(
          static_cast<uint8_t*>(base::AlignedAlloc(size_in_bytes, alignment))) {
}

size_t SoftwareRawImageMemory::GetSizeInBytes() const { return size_in_bytes_; }

uint8_t* SoftwareRawImageMemory::GetMemory() { return pixel_data_.get(); }

std::unique_ptr<uint8_t, base::AlignedFreeDeleter>
SoftwareRawImageMemory::PassPixelData() {
  return std::move(pixel_data_);
}

SoftwareMultiPlaneImage::SoftwareMultiPlaneImage(
    std::unique_ptr<SoftwareRawImageMemory> raw_image_memory,
    const render_tree::MultiPlaneImageDataDescriptor& descriptor)
    : size_(descriptor.GetPlaneDescriptor(0).size),
      format_(descriptor.image_format()),
      owned_pixel_data_(raw_image_memory->PassPixelData()) {
  for (int i = 0; i < descriptor.num_planes(); ++i) {
    planes_[i] = new SoftwareImage(
        owned_pixel_data_.get() + descriptor.GetPlaneOffset(i),
        descriptor.GetPlaneDescriptor(i));
  }
}

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