blob: 7db38c1146b854cd09c8a774b8055fdbb956449e [file] [log] [blame]
// Copyright 2022 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 <fidl/fuchsia.sysmem/cpp/wire.h>
#include <fidl/fuchsia.sysmem2/cpp/wire.h>
#include <lib/image-format/image_format.h>
#include <lib/sysmem-version/sysmem-version.h>
#include <fbl/algorithm.h>
#include <fbl/array.h>
#include <zxtest/zxtest.h>
namespace sysmem_v1 = fuchsia_sysmem;
namespace sysmem_v2 = fuchsia_sysmem2;
TEST(ImageFormat, IntelYTiledFormat_V2) {
sysmem_v2::ImageFormatConstraints constraints;
constraints.pixel_format() = fuchsia_images2::PixelFormat::kNv12;
constraints.pixel_format_modifier() = fuchsia_images2::PixelFormatModifier::kIntelI915YTiled;
constraints.min_size() = {128u, 32u};
auto image_format_result = ImageConstraintsToFormat(constraints, 3440u, 1440u);
EXPECT_TRUE(image_format_result.is_ok());
auto image_format = image_format_result.take_value();
constexpr uint32_t kTileSize = 4096u;
constexpr uint32_t kBytesPerRowPerTile = 128u;
constexpr uint32_t kYPlaneWidthInTiles = 27u;
constexpr uint32_t kYPlaneHeightInTiles = 45u;
constexpr uint32_t kUVPlaneWidthInTiles = 27u;
constexpr uint32_t kUVPlaneHeightInTiles = 23u;
constexpr uint32_t kYPlaneSize = kYPlaneWidthInTiles * kYPlaneHeightInTiles * kTileSize;
constexpr uint32_t kUVPlaneSize = kUVPlaneWidthInTiles * kUVPlaneHeightInTiles * kTileSize;
constexpr uint32_t kTotalSize = kYPlaneSize + kUVPlaneSize;
EXPECT_EQ(kTotalSize, ImageFormatImageSize(image_format));
uint64_t y_plane_byte_offset;
EXPECT_TRUE(ImageFormatPlaneByteOffset(image_format, 0u, &y_plane_byte_offset));
EXPECT_EQ(0u, y_plane_byte_offset);
uint64_t uv_plane_byte_offset;
EXPECT_TRUE(ImageFormatPlaneByteOffset(image_format, 1u, &uv_plane_byte_offset));
EXPECT_EQ(kYPlaneSize, uv_plane_byte_offset);
uint32_t y_plane_row_stride;
EXPECT_TRUE(ImageFormatPlaneRowBytes(image_format, 0u, &y_plane_row_stride));
EXPECT_EQ(kBytesPerRowPerTile * kYPlaneWidthInTiles, y_plane_row_stride);
uint32_t uv_plane_row_stride;
EXPECT_TRUE(ImageFormatPlaneRowBytes(image_format, 1u, &uv_plane_row_stride));
EXPECT_EQ(kBytesPerRowPerTile * kUVPlaneWidthInTiles, uv_plane_row_stride);
}
TEST(ImageFormat, IntelYTiledFormat_V2_wire) {
fidl::Arena allocator;
sysmem_v2::wire::ImageFormatConstraints constraints(allocator);
constraints.set_pixel_format(fuchsia_images2::wire::PixelFormat::kNv12);
constraints.set_pixel_format_modifier(
allocator, fuchsia_images2::wire::PixelFormatModifier::kIntelI915YTiled);
constraints.set_min_size(allocator, fuchsia_math::wire::SizeU{128u, 32u});
auto image_format_result = ImageConstraintsToFormat(allocator, constraints, 3440u, 1440u);
EXPECT_TRUE(image_format_result.is_ok());
auto image_format = image_format_result.take_value();
constexpr uint32_t kTileSize = 4096u;
constexpr uint32_t kBytesPerRowPerTile = 128u;
constexpr uint32_t kYPlaneWidthInTiles = 27u;
constexpr uint32_t kYPlaneHeightInTiles = 45u;
constexpr uint32_t kUVPlaneWidthInTiles = 27u;
constexpr uint32_t kUVPlaneHeightInTiles = 23u;
constexpr uint32_t kYPlaneSize = kYPlaneWidthInTiles * kYPlaneHeightInTiles * kTileSize;
constexpr uint32_t kUVPlaneSize = kUVPlaneWidthInTiles * kUVPlaneHeightInTiles * kTileSize;
constexpr uint32_t kTotalSize = kYPlaneSize + kUVPlaneSize;
EXPECT_EQ(kTotalSize, ImageFormatImageSize(image_format));
uint64_t y_plane_byte_offset;
EXPECT_TRUE(ImageFormatPlaneByteOffset(image_format, 0u, &y_plane_byte_offset));
EXPECT_EQ(0u, y_plane_byte_offset);
uint64_t uv_plane_byte_offset;
EXPECT_TRUE(ImageFormatPlaneByteOffset(image_format, 1u, &uv_plane_byte_offset));
EXPECT_EQ(kYPlaneSize, uv_plane_byte_offset);
uint32_t y_plane_row_stride;
EXPECT_TRUE(ImageFormatPlaneRowBytes(image_format, 0u, &y_plane_row_stride));
EXPECT_EQ(kBytesPerRowPerTile * kYPlaneWidthInTiles, y_plane_row_stride);
uint32_t uv_plane_row_stride;
EXPECT_TRUE(ImageFormatPlaneRowBytes(image_format, 1u, &uv_plane_row_stride));
EXPECT_EQ(kBytesPerRowPerTile * kUVPlaneWidthInTiles, uv_plane_row_stride);
}
TEST(ImageFormat, IntelYTiledFormat_V1_wire) {
sysmem_v1::wire::PixelFormat format = {
.type = sysmem_v1::wire::PixelFormatType::kNv12,
.has_format_modifier = true,
.format_modifier =
{
.value = sysmem_v1::wire::kFormatModifierIntelI915YTiled,
},
};
sysmem_v1::wire::ImageFormatConstraints constraints = {
.pixel_format = format,
.min_coded_width = 128u,
.max_coded_width = 1920u,
.min_coded_height = 32u,
.max_coded_height = 1080u,
.max_bytes_per_row = 0u,
.bytes_per_row_divisor = 0u,
};
auto optional_format = ImageConstraintsToFormat(constraints, 1920u, 1080u);
EXPECT_TRUE(optional_format);
auto& image_format = optional_format.value();
constexpr uint32_t kTileSize = 4096u;
constexpr uint32_t kBytesPerRowPerTile = 128u;
constexpr uint32_t kYPlaneWidthInTiles = 15u;
constexpr uint32_t kYPlaneHeightInTiles = 34u;
constexpr uint32_t kUVPlaneWidthInTiles = 15u;
constexpr uint32_t kUVPlaneHeightInTiles = 17u;
constexpr uint32_t kYPlaneSize = kYPlaneWidthInTiles * kYPlaneHeightInTiles * kTileSize;
constexpr uint32_t kUVPlaneSize = kUVPlaneWidthInTiles * kUVPlaneHeightInTiles * kTileSize;
constexpr uint32_t kTotalSize = kYPlaneSize + kUVPlaneSize;
EXPECT_EQ(kTotalSize, ImageFormatImageSize(image_format));
uint64_t y_plane_byte_offset;
EXPECT_TRUE(ImageFormatPlaneByteOffset(image_format, 0u, &y_plane_byte_offset));
EXPECT_EQ(0u, y_plane_byte_offset);
uint64_t uv_plane_byte_offset;
EXPECT_TRUE(ImageFormatPlaneByteOffset(image_format, 1u, &uv_plane_byte_offset));
EXPECT_EQ(kYPlaneSize, uv_plane_byte_offset);
uint32_t y_plane_row_stride;
EXPECT_TRUE(ImageFormatPlaneRowBytes(image_format, 0u, &y_plane_row_stride));
EXPECT_EQ(kBytesPerRowPerTile * kYPlaneWidthInTiles, y_plane_row_stride);
uint32_t uv_plane_row_stride;
EXPECT_TRUE(ImageFormatPlaneRowBytes(image_format, 1u, &uv_plane_row_stride));
EXPECT_EQ(kBytesPerRowPerTile * kUVPlaneWidthInTiles, uv_plane_row_stride);
}
TEST(ImageFormat, IntelCcsFormats_V1_wire) {
for (auto& format_modifier : {
sysmem_v1::wire::kFormatModifierIntelI915YTiledCcs,
sysmem_v1::wire::kFormatModifierIntelI915YfTiledCcs,
}) {
sysmem_v1::wire::PixelFormat format = {
.type = sysmem_v1::wire::PixelFormatType::kBgra32,
.has_format_modifier = true,
.format_modifier =
{
.value = format_modifier,
},
};
sysmem_v1::wire::ImageFormatConstraints constraints = {
.pixel_format = format,
.min_coded_width = 12,
.max_coded_width = 100,
.min_coded_height = 12,
.max_coded_height = 100,
.max_bytes_per_row = 100000,
.bytes_per_row_divisor = 4 * 8,
};
auto optional_format = ImageConstraintsToFormat(constraints, 64, 63);
EXPECT_TRUE(optional_format);
auto& image_format = optional_format.value();
constexpr uint32_t kWidthInTiles = 2;
constexpr uint32_t kHeightInTiles = 2;
constexpr uint32_t kTileSize = 4096;
constexpr uint32_t kMainPlaneSize = kWidthInTiles * kHeightInTiles * kTileSize;
constexpr uint32_t kCcsWidthInTiles = 1;
constexpr uint32_t kCcsHeightInTiles = 1;
constexpr uint32_t kCcsPlane = 3;
EXPECT_EQ(kMainPlaneSize + kCcsWidthInTiles * kCcsHeightInTiles * kTileSize,
ImageFormatImageSize(image_format));
uint64_t ccs_byte_offset;
EXPECT_TRUE(ImageFormatPlaneByteOffset(image_format, kCcsPlane, &ccs_byte_offset));
EXPECT_EQ(kMainPlaneSize, ccs_byte_offset);
uint32_t main_plane_row_stride;
EXPECT_TRUE(ImageFormatPlaneRowBytes(image_format, 0, &main_plane_row_stride));
EXPECT_EQ(128u * kWidthInTiles, main_plane_row_stride);
uint32_t ccs_row_stride;
EXPECT_TRUE(ImageFormatPlaneRowBytes(image_format, kCcsPlane, &ccs_row_stride));
EXPECT_EQ(ccs_row_stride, 128u * kCcsWidthInTiles);
}
}
TEST(ImageFormat, IntelYTiledFormat_V2BytesPerRowDivisor) {
fidl::Arena allocator;
sysmem_v2::wire::ImageFormatConstraints constraints(allocator);
constraints.set_pixel_format(fuchsia_images2::wire::PixelFormat::kB8G8R8A8);
constraints.set_pixel_format_modifier(
allocator, fuchsia_images2::wire::PixelFormatModifier::kIntelI915YTiled);
constraints.set_min_size(allocator, fuchsia_math::wire::SizeU{128u, 32u});
constraints.set_bytes_per_row_divisor(512u);
constexpr uint32_t kImageWidth = 540u / 4;
constexpr uint32_t kImageHeight = 140u;
auto image_format_result =
ImageConstraintsToFormat(allocator, constraints, kImageWidth, kImageHeight);
EXPECT_TRUE(image_format_result.is_ok());
auto image_format = image_format_result.take_value();
EXPECT_EQ(512u * 2, image_format.bytes_per_row());
constexpr uint32_t kYTileByteWidth = 128u;
constexpr uint32_t kYTileHeight = 32u;
{
constexpr uint32_t kWidthInTiles = fbl::round_up(512u * 2, kYTileByteWidth) / kYTileByteWidth;
constexpr uint32_t kHeightInTiles = fbl::round_up(kImageHeight, kYTileHeight) / kYTileHeight;
constexpr uint32_t kTileSize = 4096;
constexpr uint32_t kPlaneSize = kWidthInTiles * kHeightInTiles * kTileSize;
EXPECT_EQ(kPlaneSize, ImageFormatImageSize(image_format));
}
// Check that increasing the bytes per row increases the calculated image size.
image_format.set_bytes_per_row(512u * 3);
{
constexpr uint32_t kWidthInTiles = fbl::round_up(512u * 3, kYTileByteWidth) / kYTileByteWidth;
constexpr uint32_t kHeightInTiles = fbl::round_up(kImageHeight, kYTileHeight) / kYTileHeight;
constexpr uint32_t kTileSize = 4096;
constexpr uint32_t kPlaneSize = kWidthInTiles * kHeightInTiles * kTileSize;
EXPECT_EQ(kPlaneSize, ImageFormatImageSize(image_format));
}
}