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

#include "cobalt/renderer/rasterizer/blitter/image.h"

#include "cobalt/render_tree/image.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_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))),
      descriptor_(size, pixel_format, alpha_format,
                  SbBlitterGetPixelDataPitchInBytes(pixel_data_)) {
  CHECK(alpha_format == render_tree::kAlphaFormatPremultiplied ||
        alpha_format == render_tree::kAlphaFormatOpaque);
  CHECK(SbBlitterIsPixelDataValid(pixel_data_));
}

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

uint8* ImageData::GetMemory() {
  return static_cast<uint8*>(SbBlitterGetPixelDataPointer(pixel_data_));
}

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

SinglePlaneImage::SinglePlaneImage(scoped_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)
    : surface_(surface), is_opaque_(is_opaque) {
  CHECK(SbBlitterIsSurfaceValid(surface_));
  SbBlitterSurfaceInfo info;
  if (!SbBlitterGetSurfaceInfo(surface_, &info)) {
    NOTREACHED();
  }
  size_ = math::Size(info.width, info.height);
}

bool SinglePlaneImage::EnsureInitialized() { return false; }

const SkBitmap& SinglePlaneImage::GetBitmap() 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.
  if (!bitmap_) {
    bitmap_.emplace();

    SkImageInfo image_info = SkImageInfo::Make(
        size_.width(), size_.height(), kN32_SkColorType, kPremul_SkAlphaType);
    bitmap_->allocPixels(image_info);

    SkAutoLockPixels lock(*bitmap_);

    CHECK(SbBlitterDownloadSurfacePixels(
        surface_, SkiaToBlitterPixelFormat(image_info.colorType()),
        bitmap_->rowBytes(), bitmap_->getPixels()));
  }

  return *bitmap_;
}

SinglePlaneImage::~SinglePlaneImage() { SbBlitterDestroySurface(surface_); }

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

#endif  // #if SB_HAS(BLITTER)
