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

#include <vector>

#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/debug/trace_event.h"
#include "cobalt/renderer/backend/egl/framebuffer_render_target.h"
#include "cobalt/renderer/backend/egl/texture.h"
#include "cobalt/renderer/rasterizer/skia/cobalt_skia_type_conversions.h"
#include "cobalt/renderer/rasterizer/skia/gl_format_conversions.h"
#include "third_party/skia/include/gpu/SkGrPixelRef.h"

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

GrTexture* WrapCobaltTextureWithSkiaTexture(
    GrContext* gr_context, backend::TextureEGL* cobalt_texture) {
  // Setup a Skia texture descriptor to describe the texture we wish to have
  // wrapped within a Skia GrTexture.
  GrBackendTextureDesc desc;
  desc.fFlags = kNone_GrBackendTextureFlag;
  desc.fOrigin = kTopLeft_GrSurfaceOrigin;
  desc.fWidth = cobalt_texture->GetSize().width();
  desc.fHeight = cobalt_texture->GetSize().height();
  desc.fConfig = ConvertGLFormatToGr(cobalt_texture->GetFormat());
  desc.fSampleCnt = 0;

  desc.fTextureHandle =
      static_cast<GrBackendObject>(cobalt_texture->GetPlatformHandle());

  return gr_context->wrapBackendTexture(desc);
}

HardwareImageData::HardwareImageData(
    scoped_ptr<backend::TextureDataEGL> texture_data,
    render_tree::PixelFormat pixel_format,
    render_tree::AlphaFormat alpha_format)
    : texture_data_(texture_data.Pass()),
      descriptor_(texture_data_->GetSize(), pixel_format, alpha_format,
                  texture_data_->GetPitchInBytes()) {}

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

uint8_t* HardwareImageData::GetMemory() { return texture_data_->GetMemory(); }

scoped_ptr<backend::TextureDataEGL> HardwareImageData::PassTextureData() {
  return texture_data_.Pass();
}

HardwareRawImageMemory::HardwareRawImageMemory(
    scoped_ptr<backend::RawTextureMemoryEGL> raw_texture_memory)
    : raw_texture_memory_(raw_texture_memory.Pass()) {}

size_t HardwareRawImageMemory::GetSizeInBytes() const {
  return raw_texture_memory_->GetSizeInBytes();
}

uint8_t* HardwareRawImageMemory::GetMemory() {
  return raw_texture_memory_->GetMemory();
}

scoped_ptr<backend::RawTextureMemoryEGL>
HardwareRawImageMemory::PassRawTextureMemory() {
  return raw_texture_memory_.Pass();
}

// This will store the given pixel data in a GrTexture and the function
// GetBitmap(), overridden from SkiaImage, will return a reference to a SkBitmap
// object that refers to the image's GrTexture.  This object should only be
// initialized, destructed and used from the same rasterizer thread; it can be
// constructed from any thread though.
class HardwareFrontendImage::HardwareBackendImage {
 public:
  typedef base::Callback<void(HardwareBackendImage*)> InitializeFunction;

  explicit HardwareBackendImage(const InitializeFunction& initialize_function)
      : initialize_function_(initialize_function),
        initialized_task_executed_(false) {
    thread_checker_.DetachFromThread();
  }

  ~HardwareBackendImage() {
    TRACE_EVENT0("cobalt::renderer",
                 "HardwareBackendImage::~HardwareBackendImage()");
    // This object should always be destroyed from the thread that it was
    // constructed on.
    DCHECK(thread_checker_.CalledOnValidThread());
  }

  // Return true if the object was initialized due to this call, or false if
  // the image was already initialized.
  bool EnsureInitialized() {
    DCHECK(thread_checker_.CalledOnValidThread());
    return ResetAndRunIfNotNull(&initialize_function_, this);
  }

  void InitializeTask() {
    DCHECK(thread_checker_.CalledOnValidThread());
    initialized_task_executed_ = true;
    EnsureInitialized();
  }

  bool TryDestroy() {
    DCHECK(thread_checker_.CalledOnValidThread());
    initialize_function_.Reset();
    return initialized_task_executed_;
  }

  // Initialize functions for the various ways to create a backend image.
  // One of these should be passed to the constructor to tell the object how
  // to create the image from the rasterizer thread. Ideally, these would be
  // non-static member functions, however, the problem is binding "this" to
  // the callback while passing it to the constructor. Options are:
  //   1. Use static functions which accept "this".
  //   2. Use a default constructor so that HardwareBackendImage can be
  //      constructed first, then a separate function to set the callback.
  //   3. Bind std::placeholders::_1 for "this". base::Callback does not accept
  //      placeholders, so the callback needs to be changed to std::function.
  //      However, std::function cannot take ownership of scoped_ptr objects,
  //      so such parameters would have to be manually deleted.

  static void InitializeFromImageData(
      scoped_ptr<HardwareImageData> image_data,
      backend::GraphicsContextEGL* cobalt_context, GrContext* gr_context,
      HardwareBackendImage* backend) {
    TRACE_EVENT0("cobalt::renderer",
                 "HardwareBackendImage::InitializeFromImageData()");
    backend->texture_ = cobalt_context->CreateTexture(
        image_data->PassTextureData());
    backend->CommonInitialize(gr_context);
  }

  static void InitializeFromRawImageData(
      const scoped_refptr<backend::ConstRawTextureMemoryEGL>& texture_memory,
      intptr_t offset, const render_tree::ImageDataDescriptor& descriptor,
      backend::GraphicsContextEGL* cobalt_context, GrContext* gr_context,
      HardwareBackendImage* backend) {
    TRACE_EVENT0("cobalt::renderer",
                 "HardwareBackendImage::InitializeFromRawImageData()");
    backend->texture_ = cobalt_context->CreateTextureFromRawMemory(
        texture_memory, offset, descriptor.size,
        ConvertRenderTreeFormatToGL(descriptor.pixel_format),
        descriptor.pitch_in_bytes);
    backend->CommonInitialize(gr_context);
  }

  static void InitializeFromTexture(
      scoped_ptr<backend::TextureEGL> texture, GrContext* gr_context,
      HardwareBackendImage* backend) {
    TRACE_EVENT0("cobalt::renderer",
                 "HardwareBackendImage::InitializeFromTexture()");
    backend->texture_ = texture.Pass();
    backend->CommonInitialize(gr_context);
  }

  static void InitializeFromRenderTree(
      const scoped_refptr<render_tree::Node>& root, const math::Size& size,
      const SubmitOffscreenCallback& submit_offscreen_callback,
      backend::GraphicsContextEGL* cobalt_context, GrContext* gr_context,
      HardwareBackendImage* backend) {
    TRACE_EVENT0("cobalt::renderer",
                 "HardwareBackendImage::InitializeFromRenderTree()");

    scoped_refptr<backend::FramebufferRenderTargetEGL> render_target(
        new backend::FramebufferRenderTargetEGL(cobalt_context, size));

    submit_offscreen_callback.Run(root, render_target);

    scoped_ptr<backend::TextureEGL> texture(
        new backend::TextureEGL(cobalt_context, render_target));

    InitializeFromTexture(texture.Pass(), gr_context, backend);
  }

  // Initiate all texture initialization code here, which should be executed
  // on the rasterizer thread.
  void CommonInitialize(GrContext* gr_context) {
    DCHECK(thread_checker_.CalledOnValidThread());
    TRACE_EVENT0("cobalt::renderer",
                 "HardwareBackendImage::CommonInitialize()");
    if (texture_->GetTarget() == GL_TEXTURE_2D) {
      gr_texture_.reset(
          WrapCobaltTextureWithSkiaTexture(gr_context, texture_.get()));
      DCHECK(gr_texture_);

      // Prepare a member SkBitmap that refers to the newly created GrTexture
      // and will be the object that Skia draw calls will reference when
      // referring to this image.
      bitmap_.setInfo(gr_texture_->info());
      bitmap_.setPixelRef(
                 SkNEW_ARGS(SkGrPixelRef, (bitmap_.info(), gr_texture_)))
          ->unref();
    }
  }

  const SkBitmap* GetBitmap() const {
    DCHECK(thread_checker_.CalledOnValidThread());
    return &bitmap_;
  }

  const backend::TextureEGL* GetTextureEGL() const {
    DCHECK(thread_checker_.CalledOnValidThread());
    return texture_.get();
  }

 private:
  // Keep a reference to the texture alive as long as this backend image
  // exists.
  scoped_ptr<backend::TextureEGL> texture_;

  base::ThreadChecker thread_checker_;
  SkAutoTUnref<GrTexture> gr_texture_;
  SkBitmap bitmap_;

  InitializeFunction initialize_function_;
  bool initialized_task_executed_;
};

namespace {
// Given a ImageDataDescriptor, returns a AlternateRgbaFormat value for it,
// which for most formats will be base::nullopt, but for those that piggy-back
// on RGBA but assign different meanings to each of the 4 pixels, this will
// return a special formatting option.
base::optional<AlternateRgbaFormat> AlternateRgbaFormatFromImageDataDescriptor(
    const render_tree::ImageDataDescriptor& descriptor) {
  if (descriptor.pixel_format == render_tree::kPixelFormatUYVY) {
    return AlternateRgbaFormat_UYVY;
  } else {
    return base::nullopt;
  }
}

// Depending on the alternate RGBA format, possibly adjust the content rect
// size.  For example, UYVY needs the content rect's width to be multiplied
// by two since each "pixel" actually represents two pixels side-by-side.  This
// allows render_tree::ImageNode objects that are constructed without an
// explicit size assigned to them to take on the size of the Y-width for UYVY,
// which is more natural.
math::Size AdjustSizeForFormat(
    const math::Size& size,
    const base::optional<AlternateRgbaFormat>& alternate_rgba_format) {
  if (!alternate_rgba_format) {
    return size;
  }

  switch (*alternate_rgba_format) {
    case AlternateRgbaFormat_UYVY: {
      return math::Size(size.width() * 2, size.height());
    }
    default: {
      NOTREACHED();
      return size;
    }
  }
}
}  // namespace

HardwareFrontendImage::HardwareFrontendImage(
    scoped_ptr<HardwareImageData> image_data,
    backend::GraphicsContextEGL* cobalt_context, GrContext* gr_context,
    MessageLoop* rasterizer_message_loop)
    : is_opaque_(image_data->GetDescriptor().alpha_format ==
                 render_tree::kAlphaFormatOpaque),
      alternate_rgba_format_(AlternateRgbaFormatFromImageDataDescriptor(
          image_data->GetDescriptor())),
      size_(AdjustSizeForFormat(image_data->GetDescriptor().size,
                                alternate_rgba_format_)),
      rasterizer_message_loop_(rasterizer_message_loop) {
  backend_image_.reset(new HardwareBackendImage(base::Bind(
      &HardwareBackendImage::InitializeFromImageData,
      base::Passed(&image_data), cobalt_context, gr_context)));
  InitializeBackend();
}

HardwareFrontendImage::HardwareFrontendImage(
    const scoped_refptr<backend::ConstRawTextureMemoryEGL>& raw_texture_memory,
    intptr_t offset, const render_tree::ImageDataDescriptor& descriptor,
    backend::GraphicsContextEGL* cobalt_context, GrContext* gr_context,
    MessageLoop* rasterizer_message_loop)
    : is_opaque_(descriptor.alpha_format == render_tree::kAlphaFormatOpaque),
      alternate_rgba_format_(
          AlternateRgbaFormatFromImageDataDescriptor(descriptor)),
      size_(AdjustSizeForFormat(descriptor.size, alternate_rgba_format_)),
      rasterizer_message_loop_(rasterizer_message_loop) {
  TRACE_EVENT0("cobalt::renderer",
               "HardwareFrontendImage::HardwareFrontendImage()");
  backend_image_.reset(new HardwareBackendImage(base::Bind(
      &HardwareBackendImage::InitializeFromRawImageData,
      raw_texture_memory, offset, descriptor, cobalt_context, gr_context)));
  InitializeBackend();
}

HardwareFrontendImage::HardwareFrontendImage(
    scoped_ptr<backend::TextureEGL> texture,
    render_tree::AlphaFormat alpha_format,
    backend::GraphicsContextEGL* cobalt_context, GrContext* gr_context,
    scoped_ptr<math::Rect> content_region, MessageLoop* rasterizer_message_loop,
    base::optional<AlternateRgbaFormat> alternate_rgba_format)
    : is_opaque_(alpha_format == render_tree::kAlphaFormatOpaque),
      content_region_(content_region.Pass()),
      alternate_rgba_format_(alternate_rgba_format),
      size_(AdjustSizeForFormat(
          content_region_ ? math::Size(std::abs(content_region_->width()),
                                       std::abs(content_region_->height()))
                          : texture->GetSize(),
          alternate_rgba_format_)),
      rasterizer_message_loop_(rasterizer_message_loop) {
  TRACE_EVENT0("cobalt::renderer",
               "HardwareFrontendImage::HardwareFrontendImage()");
  backend_image_.reset(new HardwareBackendImage(base::Bind(
      &HardwareBackendImage::InitializeFromTexture, base::Passed(&texture),
      gr_context)));
  InitializeBackend();
}

HardwareFrontendImage::HardwareFrontendImage(
    const scoped_refptr<render_tree::Node>& root,
    const SubmitOffscreenCallback& submit_offscreen_callback,
    backend::GraphicsContextEGL* cobalt_context, GrContext* gr_context,
    MessageLoop* rasterizer_message_loop)
    : is_opaque_(false),
      size_(AdjustSizeForFormat(
          math::Size(static_cast<int>(root->GetBounds().right()),
                     static_cast<int>(root->GetBounds().bottom())),
          alternate_rgba_format_)),
      rasterizer_message_loop_(rasterizer_message_loop) {
  TRACE_EVENT0("cobalt::renderer",
               "HardwareFrontendImage::HardwareFrontendImage()");
  backend_image_.reset(new HardwareBackendImage(base::Bind(
      &HardwareBackendImage::InitializeFromRenderTree, root, size_,
      submit_offscreen_callback, cobalt_context, gr_context)));
  InitializeBackend();
}

HardwareFrontendImage::~HardwareFrontendImage() {
  TRACE_EVENT0("cobalt::renderer",
               "HardwareFrontendImage::~HardwareFrontendImage()");
  // InitializeBackend() posted a task to call backend_image_'s
  // InitializeTask(). Make sure that task has finished before
  // destroying backend_image_.
  if (rasterizer_message_loop_) {
    if (rasterizer_message_loop_ != MessageLoop::current() ||
        !backend_image_->TryDestroy()) {
      rasterizer_message_loop_->DeleteSoon(FROM_HERE, backend_image_.release());
    }
  }  // else let the scoped pointer clean it up immediately.
}

void HardwareFrontendImage::InitializeBackend() {
  // Initialize the image as soon as possible, rather than waiting for the
  // rasterizer to initialize it when needed. The image initialization process
  // may take some time, so doing a lazy initialize can cause a big spike in
  // frame time if multiple images are initialized in one frame.
  if (rasterizer_message_loop_) {
    rasterizer_message_loop_->PostTask(FROM_HERE, base::Bind(
        &HardwareBackendImage::InitializeTask,
        base::Unretained(backend_image_.get())));
  }
}

const SkBitmap* HardwareFrontendImage::GetBitmap() const {
  DCHECK_EQ(rasterizer_message_loop_, MessageLoop::current());
  // Forward this call to the backend image.  This method must be called from
  // the rasterizer thread (e.g. during a render tree visitation).  The backend
  // image will check that this is being called from the correct thread.
  return backend_image_->GetBitmap();
}

const backend::TextureEGL* HardwareFrontendImage::GetTextureEGL() const {
  DCHECK_EQ(rasterizer_message_loop_, MessageLoop::current());
  return backend_image_->GetTextureEGL();
}

bool HardwareFrontendImage::CanRenderInSkia() const {
  DCHECK_EQ(rasterizer_message_loop_, MessageLoop::current());
  // In some cases, especially when dealing with SbDecodeTargets, we may end
  // up with a GLES2 texture whose target is not GL_TEXTURE_2D, in which case
  // we cannot use our typical Skia flow to render it, and we delegate to
  // a rasterizer-provided callback for performing custom rendering (e.g.
  // via direct GL calls).
  // We also fallback if a content region is specified on the image, since we
  // don't support handling that in the normal flow.
  return !GetContentRegion() &&
         (!GetTextureEGL() || GetTextureEGL()->GetTarget() == GL_TEXTURE_2D) &&
         !alternate_rgba_format_;
}

bool HardwareFrontendImage::EnsureInitialized() {
  DCHECK_EQ(rasterizer_message_loop_, MessageLoop::current());
  return backend_image_->EnsureInitialized();
}

HardwareMultiPlaneImage::HardwareMultiPlaneImage(
    scoped_ptr<HardwareRawImageMemory> raw_image_memory,
    const render_tree::MultiPlaneImageDataDescriptor& descriptor,
    backend::GraphicsContextEGL* cobalt_context, GrContext* gr_context,
    MessageLoop* rasterizer_message_loop)
    : size_(descriptor.GetPlaneDescriptor(0).size),
      format_(descriptor.image_format()) {
  scoped_refptr<backend::ConstRawTextureMemoryEGL> const_raw_texture_memory(
      new backend::ConstRawTextureMemoryEGL(
          raw_image_memory->PassRawTextureMemory()));

  // Construct a single plane image for each plane of this multi plane image.
  for (int i = 0; i < descriptor.num_planes(); ++i) {
    planes_[i] = new HardwareFrontendImage(
        const_raw_texture_memory, descriptor.GetPlaneOffset(i),
        descriptor.GetPlaneDescriptor(i), cobalt_context, gr_context,
        rasterizer_message_loop);
  }
}

HardwareMultiPlaneImage::HardwareMultiPlaneImage(
    render_tree::MultiPlaneImageFormat format,
    const std::vector<scoped_refptr<HardwareFrontendImage> >& planes)
    : size_(planes[0]->GetSize()), format_(format) {
  DCHECK(planes.size() <=
         render_tree::MultiPlaneImageDataDescriptor::kMaxPlanes);
  for (unsigned int i = 0; i < planes.size(); ++i) {
    planes_[i] = planes[i];
  }
}

HardwareMultiPlaneImage::~HardwareMultiPlaneImage() {}

bool HardwareMultiPlaneImage::EnsureInitialized() {
  // A multi-plane image is not considered backend-initialized until all its
  // single-plane images are backend-initialized, thus we ensure that all
  // the component images are backend-initialized.
  bool initialized = false;
  for (int i = 0; i < render_tree::MultiPlaneImageDataDescriptor::kMaxPlanes;
       ++i) {
    if (planes_[i]) {
      initialized |= planes_[i]->EnsureInitialized();
    }
  }
  return initialized;
}

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