// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "layer.h"
#include <math.h>
#include "runner.h"
#include "utils.h"

namespace {

uint32_t scale(uint32_t x, uint32_t from_limit, uint32_t to_limit) {
  if (from_limit == to_limit) {
    return x;
  } else {
    return (x * to_limit + (from_limit - 1)) / from_limit;
  }
}

}  // namespace

namespace display_test {
namespace internal {

LayerImpl::LayerImpl(Runner* runner) : runner_(runner) {
  runner->display()->CreateLayer([this](zx_status_t status, uint64_t id) {
    ZX_ASSERT(status == ZX_OK);
    id_ = id;
    runner_->OnResourceReady();
  });
}

fuchsia::hardware::display::ControllerPtr& LayerImpl::controller() const {
  return runner_->display();
}

}  // namespace internal

PrimaryLayer::PrimaryLayer(internal::Runner* runner, uint32_t width,
                           uint32_t height)
    : Layer(runner) {
  config_ = {};
  config_.width = width;
  config_.height = height;
  config_.pixel_format = internal::ImageImpl::kFormat;

  pending_state_.set_position = false;
  pending_state_.transform = fuchsia::hardware::display::Transform::IDENTITY;
  pending_state_.src = {};
  pending_state_.src.width = width;
  pending_state_.src.height = height;
  pending_state_.dest = pending_state_.src;
  pending_state_.set_alpha = false;
  pending_state_.alpha_mode = fuchsia::hardware::display::AlphaMode::DISABLE;
  pending_state_.image = nullptr;
  pending_state_.flip_image = false;
}

void PrimaryLayer::SetImage(const Image* image) {
  pending_state_.image = internal::ImageImpl::GetImageImpl(image);
  pending_state_.flip_image = true;
}

void PrimaryLayer::SetPosition(fuchsia::hardware::display::Transform transform,
                               fuchsia::hardware::display::Frame src,
                               fuchsia::hardware::display::Frame dest) {
  src.x_pos = src.x_pos & ~1;
  dest.x_pos = dest.x_pos & ~1;
  src.width = src.width & ~1;
  dest.width = dest.width & ~1;

  ZX_ASSERT(src.width == dest.width || dest.width >= kMinScalableImageSize);
  ZX_ASSERT(src.height == dest.height || dest.height >= kMinScalableImageSize);

  pending_state_.transform = transform;
  pending_state_.src = src;
  pending_state_.dest = dest;
  pending_state_.set_position = true;
}

void PrimaryLayer::SetAlpha(fuchsia::hardware::display::AlphaMode mode,
                            float val) {
  pending_state_.alpha_mode = mode;
  pending_state_.alpha_val = val;
  pending_state_.set_alpha = true;
}

bool PrimaryLayer::GetPixel(const void* state, uint32_t x, uint32_t y,
                            uint32_t* value_out, bool* skip_out) const {
  auto s = static_cast<const struct state*>(state);

  // Transform the global x,y coordinate to a dest-frame coordinate
  x -= s->dest.x_pos;
  y -= s->dest.y_pos;
  if (x >= s->dest.width || y >= s->dest.height) {
    return false;
  }

  uint32_t dest_width = s->dest.width;
  uint32_t dest_height = s->dest.height;

  // Undo x reflection if necessary
  if (s->transform == fuchsia::hardware::display::Transform::REFLECT_X ||
      s->transform == fuchsia::hardware::display::Transform::ROT_180 ||
      s->transform == fuchsia::hardware::display::Transform::ROT_270 ||
      s->transform == fuchsia::hardware::display::Transform::ROT_90_REFLECT_X) {
    x = (dest_width - 1) - x;
  }

  // Undo y reflection if necessary
  if (s->transform == fuchsia::hardware::display::Transform::REFLECT_Y ||
      s->transform == fuchsia::hardware::display::Transform::ROT_180 ||
      s->transform == fuchsia::hardware::display::Transform::ROT_270 ||
      s->transform == fuchsia::hardware::display::Transform::ROT_90_REFLECT_Y) {
    y = (dest_height - 1) - y;
  }

  // Undo 90-degree counterclockwise rotation if necessary
  if (s->transform == fuchsia::hardware::display::Transform::ROT_90 ||
      s->transform == fuchsia::hardware::display::Transform::ROT_90_REFLECT_X ||
      s->transform == fuchsia::hardware::display::Transform::ROT_90_REFLECT_Y ||
      s->transform == fuchsia::hardware::display::Transform::ROT_270) {
    dest_width = s->dest.height;
    dest_height = s->dest.width;
    uint32_t tmp = x;
    x = (dest_width - 1) - y;
    y = tmp;
  }

  // Scale from dest-coords back to src-coords
  x = scale(x, dest_width, s->src.width);
  y = scale(y, dest_height, s->src.height);

  // If we're scaling, skip over pixels that depend on hardware interpolation
  if (dest_width != s->src.width || dest_height != s->src.height) {
    constexpr uint32_t bounds = kMinScalableImageSize / 4;
    if ((x < bounds || dest_width - bounds <= x) &&
        (y < bounds || dest_height - bounds <= y)) {
      *skip_out = false;
    } else {
      *skip_out = true;
    }
  } else {
    *skip_out = false;
  }

  // Now we can actually get the image pixel data
  uint32_t val = s->image->get_pixel(s->src.x_pos + x, s->src.y_pos + y);

  // If there's plane alpha, add combine it with the image pixel
  if (!isnan(s->alpha_val)) {
    uint8_t plane_alpha = static_cast<uint8_t>(round(s->alpha_val * 255));
    uint32_t pixel_alpha = val >> 24;
    pixel_alpha = ((pixel_alpha * plane_alpha) + 254) >> 8;
    val = (val & ~(0xff000000)) | (pixel_alpha << 24);

    // If the mode is premultiplied, the hardware is supposed to
    // premultiply the alpha value before blending.
    if (s->alpha_mode == fuchsia::hardware::display::AlphaMode::PREMULTIPLIED) {
      val = internal::premultiply_color_channels(val, plane_alpha);
    }
  }

  if (s->alpha_mode == fuchsia::hardware::display::AlphaMode::DISABLE) {
    // Clobber the alpha value if it's disabled
    val |= 0xff000000;
  } else if (s->alpha_mode ==
             fuchsia::hardware::display::AlphaMode::HW_MULTIPLY) {
    // If blending is hwmultiply, then do the the channel multiplication
    // here so the caller of GetPixel can treat everything is premultiplied.
    val = internal::premultiply_color_channels(val, val >> 24);
  }

  *value_out = val;
  return true;
}

const void* PrimaryLayer::ApplyState() {
  auto state = new struct state;
  *state = pending_state_;
  pending_state_.set_config = false;
  pending_state_.set_position = false;
  pending_state_.set_alpha = false;
  pending_state_.flip_image = false;

  if (state->src.height != state->dest.height ||
      state->src.width != state->dest.width) {
    ZX_ASSERT(state->image->is_scalable());
  }
  return state;
}

void PrimaryLayer::SendState(const void* state) const {
  auto s = static_cast<const struct state*>(state);
  if (s->set_config) {
    controller()->SetLayerPrimaryConfig(id(), config_);
  }
  if (s->set_position) {
    controller()->SetLayerPrimaryPosition(id(), s->transform, s->src, s->dest);
  }
  if (s->set_alpha) {
    controller()->SetLayerPrimaryAlpha(id(), s->alpha_mode, s->alpha_val);
  }
  if (s->flip_image) {
    controller()->SetLayerImage(id(), s->image->id(), 0, 0);
  }
}

void PrimaryLayer::DeleteState(const void* state) const {
  delete static_cast<const struct state*>(state);
}

uint64_t PrimaryLayer::image_id(const void* state) const {
  auto image = static_cast<const struct state*>(state)->image;
  return image ? image->id() : 0;
}

}  // namespace display_test
