// Copyright 2019 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 "src/camera/lib/image_utils/image_format_rgba.h"

namespace camera {

constexpr uint8_t kOneByteMask = 0xff;

uint8_t BitWidthToByteMask(uint8_t bit_width) {
  ZX_DEBUG_ASSERT(bit_width <= 8);
  return static_cast<uint8_t>(0xff << (8 - bit_width));
}

Rgba Min(const Rgba &a, const Rgba &b) {
  return {std::min(a.r, b.r), std::min(a.g, b.g), std::min(a.b, b.b), std::min(a.a, b.a)};
}

Rgba BitWidthToByteMask(Rgba bit_width) {
  return {BitWidthToByteMask(bit_width.r), BitWidthToByteMask(bit_width.g),
          BitWidthToByteMask(bit_width.b), BitWidthToByteMask(bit_width.a)};
}
// RgbaPixelFormatInfo stores all the information needed to encode an RGBA pixel.
struct RgbaPixelFormatInfo {
  // bit_width is the width in bits of each channel.
  // bit offset is the offset of the start of the channel from the start of the pixel.
  Rgba bit_width, bit_offset;
  uint8_t bytes_per_pixel;
  char name[9];  // used for debug messages

  uint32_t Pack(Rgba in) const {
    // For each color, first shift it over to get just the most significant (bit_width) pixels,
    // then shift it to the correct alignment
    return static_cast<uint32_t>(in.r >> (8 - bit_width.r)) << bit_offset.r |
           static_cast<uint32_t>(in.g >> (8 - bit_width.g)) << bit_offset.g |
           static_cast<uint32_t>(in.b >> (8 - bit_width.b)) << bit_offset.b |
           static_cast<uint32_t>(in.a >> (8 - bit_width.a)) << bit_offset.a;
  }

  Rgba Unpack(uint32_t packed) const {
    return {
        .r = static_cast<uint8_t>(((packed >> bit_offset.r) << (8 - bit_width.r)) & kOneByteMask),
        .g = static_cast<uint8_t>(((packed >> bit_offset.g) << (8 - bit_width.g)) & kOneByteMask),
        .b = static_cast<uint8_t>(((packed >> bit_offset.b) << (8 - bit_width.b)) & kOneByteMask),
        .a = static_cast<uint8_t>(((packed >> bit_offset.a) << (8 - bit_width.a)) & kOneByteMask)};
  }
};

const std::map<fuchsia::sysmem::PixelFormatType, RgbaPixelFormatInfo> kPixelFormatInfo = {
    {fuchsia::sysmem::PixelFormatType::R8G8B8A8, {{8, 8, 8, 8}, {24, 16, 8, 0}, 4u, "R8G8B8A8"}},
    {fuchsia::sysmem::PixelFormatType::BGRA32, {{8, 8, 8, 8}, {8, 16, 24, 0}, 4u, "BGRA32\0"}},
    {fuchsia::sysmem::PixelFormatType::BGR24, {{8, 8, 8, 0}, {16, 8, 0, 0}, 3u, "BGR24\0"}},
    {fuchsia::sysmem::PixelFormatType::RGB565, {{5, 6, 5, 0}, {11, 5, 0, 0}, 2u, "RGB565\0"}},
    {fuchsia::sysmem::PixelFormatType::RGB332, {{3, 3, 2, 0}, {5, 2, 0, 0}, 1u, "RGB332\0"}},
    {fuchsia::sysmem::PixelFormatType::RGB2220, {{2, 2, 2, 0}, {6, 4, 2, 0}, 1u, "RGB2220\0"}},
};

RgbaPixelFormatInfo GetPixelInfo(const fuchsia::sysmem::PixelFormatType &format) {
  ZX_ASSERT(kPixelFormatInfo.count(format));
  return kPixelFormatInfo.find(format)->second;
}

Rgba RgbaUnpack(fuchsia::sysmem::PixelFormatType format, uint32_t packed) {
  return GetPixelInfo(format).Unpack(packed);
}

uint32_t RgbaPack(fuchsia::sysmem::PixelFormatType format, Rgba in) {
  return GetPixelInfo(format).Pack(in);
}

bool ComparePacked(fuchsia::sysmem::PixelFormatType format1, uint32_t value1,
                   fuchsia::sysmem::PixelFormatType format2, uint32_t value2) {
  auto pixel_info1 = GetPixelInfo(format1);
  Rgba unpacked1 = pixel_info1.Unpack(value1);
  auto pixel_info2 = GetPixelInfo(format2);
  Rgba unpacked2 = pixel_info2.Unpack(value2);
  // Since the formats may have different bit widths, mask the unpacked values
  // so we only compare bits that both values share.
  Rgba min_mask = BitWidthToByteMask(Min(pixel_info1.bit_width, pixel_info2.bit_width));
  return (unpacked1 & min_mask) == (unpacked2 & min_mask);
}

std::string ToString(const fuchsia::sysmem::PixelFormatType &type) {
  return GetPixelInfo(type).name;
}

Rgba BitWidth(const fuchsia::sysmem::PixelFormatType &type) { return GetPixelInfo(type).bit_width; }

uint32_t BytesPerPixel(const fuchsia::sysmem::PixelFormatType &type) {
  return GetPixelInfo(type).bytes_per_pixel;
}
bool IsSupportedPixelFormat(const fuchsia::sysmem::PixelFormatType &type) {
  return kPixelFormatInfo.count(type);
}

std::vector<fuchsia::sysmem::PixelFormatType> GetSupportedFormats() {
  std::vector<fuchsia::sysmem::PixelFormatType> ret;
  ret.reserve(kPixelFormatInfo.size());
  for (auto &entry : kPixelFormatInfo) {
    ret.push_back(entry.first);
  }
  return ret;
}

fuchsia_sysmem::wire::PixelFormat ConvertPixelFormatToWire(
    const fuchsia::sysmem::PixelFormat &format) {
  return {
      .type = static_cast<const fuchsia_sysmem::wire::PixelFormatType>(format.type),
      .has_format_modifier = format.has_format_modifier,
      .format_modifier =
          {
              .value = format.format_modifier.value,
          },
  };
}

fuchsia_sysmem::wire::ImageFormat2 ConvertImageFormatToWire(
    const fuchsia::sysmem::ImageFormat_2 &format) {
  return {
      .pixel_format = ConvertPixelFormatToWire(format.pixel_format),
      .coded_width = format.coded_width,
      .coded_height = format.coded_height,
      .bytes_per_row = format.bytes_per_row,
      .display_width = format.display_width,
      .display_height = format.display_height,
      .layers = format.layers,
      .color_space =
          {
              .type = static_cast<fuchsia_sysmem::wire::ColorSpaceType>(format.color_space.type),
          },
      .has_pixel_aspect_ratio = format.has_pixel_aspect_ratio,
      .pixel_aspect_ratio_width = format.pixel_aspect_ratio_width,
      .pixel_aspect_ratio_height = format.pixel_aspect_ratio_height,
  };
}

}  // namespace camera
