blob: 1868914348ea436667724673b2667ca532b1e728 [file] [log] [blame]
// 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 <fcntl.h>
#include <fidl/fuchsia.sysmem2/cpp/fidl.h>
#include <fidl/fuchsia.sysmem2/cpp/wire.h>
#include <sys/stat.h>
#include <unistd.h>
#include <gtest/gtest.h>
#include "src/sysmem/server/usage_pixel_format_cost.h"
namespace sysmem_service {
namespace {
std::vector<uint8_t> LoadFile(const char* filename) {
int fd = open(filename, O_RDONLY);
struct stat file_stat;
int fstat_result = fstat(fd, &file_stat);
ZX_ASSERT(fstat_result == 0);
size_t size = file_stat.st_size;
std::vector<uint8_t> data(size);
ssize_t read_size = read(fd, data.data(), data.size());
ZX_ASSERT(read_size == static_cast<ssize_t>(size));
close(fd);
return data;
}
std::vector<fuchsia_sysmem2::FormatCostEntry> LoadCostEntries(std::vector<const char*> filenames) {
std::vector<fuchsia_sysmem2::FormatCostEntry> result;
for (auto cost_filename : filenames) {
auto data = LoadFile(cost_filename);
auto unpersist_result = fidl::Unpersist<fuchsia_sysmem2::FormatCosts>(data);
ZX_ASSERT(unpersist_result.is_ok());
auto& format_costs = unpersist_result.value();
auto format_cost_entries = std::move(format_costs.format_costs().value());
for (auto& entry : format_cost_entries) {
result.emplace_back(std::move(entry));
}
}
return result;
}
std::vector<fuchsia_sysmem2::FormatCostEntry> LoadArmCostEntries() {
return LoadCostEntries(std::vector{
"/pkg/data/format_costs/intel.format_costs_persistent_fidl",
"/pkg/data/format_costs/arm_mali.format_costs_persistent_fidl",
"/pkg/data/format_costs/video_decoder_nv12.format_costs_persistent_fidl",
});
}
std::vector<fuchsia_sysmem2::FormatCostEntry> LoadGenericCostEntries() {
return LoadCostEntries(std::vector{
// For historical reasons the "intel" format costs are treated as "generic" for tests.
"/pkg/data/format_costs/intel.format_costs_persistent_fidl",
});
}
TEST(PixelFormatCost, Afbc) {
UsagePixelFormatCost arm_costs(LoadArmCostEntries());
UsagePixelFormatCost generic_costs(LoadGenericCostEntries());
for (uint32_t is_x = 0; is_x < 2; ++is_x) {
fuchsia_sysmem2::BufferCollectionConstraints constraints;
constraints.image_format_constraints().emplace(2);
{
fuchsia_sysmem2::ImageFormatConstraints image_format_constraints;
{
image_format_constraints.pixel_format() = fuchsia_images2::PixelFormat::kB8G8R8A8;
if (is_x) {
image_format_constraints.is_alpha_present() = false;
}
}
constraints.image_format_constraints()->at(0) = std::move(image_format_constraints);
}
{
fuchsia_sysmem2::ImageFormatConstraints image_format_constraints;
{
image_format_constraints.pixel_format() = fuchsia_images2::PixelFormat::kB8G8R8A8;
image_format_constraints.pixel_format_modifier() =
fuchsia_images2::PixelFormatModifier::kArmAfbc32X8;
if (is_x) {
image_format_constraints.is_alpha_present() = false;
}
}
constraints.image_format_constraints()->at(1) = std::move(image_format_constraints);
}
EXPECT_LT(0, arm_costs.Compare(constraints, 0, 1));
EXPECT_GT(0, arm_costs.Compare(constraints, 1, 0));
EXPECT_EQ(0, generic_costs.Compare(constraints, 0, 1));
EXPECT_EQ(0, generic_costs.Compare(constraints, 1, 0));
}
}
TEST(PixelFormatCost, IntelTiling) {
UsagePixelFormatCost generic_costs(LoadGenericCostEntries());
for (uint32_t is_x = 0; is_x < 2; ++is_x) {
fuchsia_sysmem2::BufferCollectionConstraints constraints;
constraints.image_format_constraints().emplace(2);
fuchsia_images2::PixelFormatModifier tiling_types[] = {
fuchsia_images2::PixelFormatModifier::kIntelI915XTiled,
fuchsia_images2::PixelFormatModifier::kIntelI915YfTiled,
fuchsia_images2::PixelFormatModifier::kIntelI915YTiled};
for (auto modifier : tiling_types) {
{
fuchsia_sysmem2::ImageFormatConstraints image_format_constraints;
{
image_format_constraints.pixel_format() = fuchsia_images2::PixelFormat::kB8G8R8A8;
image_format_constraints.pixel_format_modifier() =
fuchsia_images2::PixelFormatModifier::kLinear;
if (is_x) {
image_format_constraints.is_alpha_present() = false;
}
}
constraints.image_format_constraints()->at(0) = std::move(image_format_constraints);
}
{
fuchsia_sysmem2::ImageFormatConstraints image_format_constraints;
{
image_format_constraints.pixel_format() = fuchsia_images2::PixelFormat::kB8G8R8A8;
image_format_constraints.pixel_format_modifier() = modifier;
if (is_x) {
image_format_constraints.is_alpha_present() = false;
}
}
constraints.image_format_constraints()->at(1) = std::move(image_format_constraints);
}
EXPECT_LT(0, generic_costs.Compare(constraints, 0, 1));
EXPECT_GT(0, generic_costs.Compare(constraints, 1, 0));
// Explicit linear should be treated the same as no format modifier value.
constraints.image_format_constraints()->at(0).pixel_format_modifier() =
fuchsia_images2::PixelFormatModifier::kLinear;
EXPECT_LT(0, generic_costs.Compare(constraints, 0, 1));
EXPECT_GT(0, generic_costs.Compare(constraints, 1, 0));
// Explicit linear should be treated the same as no format modifier value.
{
constraints.image_format_constraints()->at(0).pixel_format() =
fuchsia_images2::PixelFormat::kB8G8R8A8;
if (is_x) {
constraints.image_format_constraints()->at(0).is_alpha_present() = false;
}
}
EXPECT_LT(0, generic_costs.Compare(constraints, 0, 1));
EXPECT_GT(0, generic_costs.Compare(constraints, 1, 0));
}
// Formats are in ascending preference order (descending cost order).
std::array modifier_list = {
fuchsia_images2::PixelFormatModifier::kLinear,
fuchsia_images2::PixelFormatModifier::kIntelI915XTiled,
fuchsia_images2::PixelFormatModifier::kIntelI915YTiled,
fuchsia_images2::PixelFormatModifier::kIntelI915YfTiled,
fuchsia_images2::PixelFormatModifier::kIntelI915YTiledCcs,
fuchsia_images2::PixelFormatModifier::kIntelI915YfTiledCcs,
};
constraints.image_format_constraints().emplace(modifier_list.size());
for (uint32_t i = 0; i < modifier_list.size(); ++i) {
{
fuchsia_sysmem2::ImageFormatConstraints image_format_constraints;
{
image_format_constraints.pixel_format() = fuchsia_images2::PixelFormat::kB8G8R8A8;
image_format_constraints.pixel_format_modifier() = modifier_list[i];
if (is_x) {
image_format_constraints.is_alpha_present() = false;
}
}
constraints.image_format_constraints()->at(i) = std::move(image_format_constraints);
}
}
for (uint32_t i = 1; i < modifier_list.size(); ++i) {
EXPECT_LT(0, generic_costs.Compare(constraints, i - 1, i)) << "i=" << i;
EXPECT_GT(0, generic_costs.Compare(constraints, i, i - 1)) << "i=" << i;
}
}
}
TEST(PixelFormatCost, ArmTransactionElimination) {
auto arm_costs = UsagePixelFormatCost(LoadArmCostEntries());
auto generic_costs = UsagePixelFormatCost(LoadGenericCostEntries());
for (uint32_t is_x = 0; is_x < 2; ++is_x) {
fuchsia_sysmem2::BufferCollectionConstraints constraints;
constraints.image_format_constraints().emplace(2);
{
fuchsia_sysmem2::ImageFormatConstraints image_format_constraints;
{
image_format_constraints.pixel_format() = fuchsia_images2::PixelFormat::kB8G8R8A8;
image_format_constraints.pixel_format_modifier() =
fuchsia_images2::PixelFormatModifier::kArmAfbc32X8;
if (is_x) {
image_format_constraints.is_alpha_present() = false;
}
}
constraints.image_format_constraints()->at(0) = std::move(image_format_constraints);
}
{
fuchsia_sysmem2::ImageFormatConstraints image_format_constraints;
{
image_format_constraints.pixel_format() = fuchsia_images2::PixelFormat::kB8G8R8A8;
image_format_constraints.pixel_format_modifier() =
fuchsia_images2::PixelFormatModifier::kArmAfbc32X8Te;
if (is_x) {
image_format_constraints.is_alpha_present() = false;
}
}
constraints.image_format_constraints()->at(1) = std::move(image_format_constraints);
}
EXPECT_LT(0, arm_costs.Compare(constraints, 0, 1));
EXPECT_GT(0, arm_costs.Compare(constraints, 1, 0));
EXPECT_EQ(0, generic_costs.Compare(constraints, 0, 1));
EXPECT_EQ(0, generic_costs.Compare(constraints, 1, 0));
}
}
TEST(PixelFormatCost, AfbcWithFlags) {
auto arm_costs = UsagePixelFormatCost(LoadArmCostEntries());
auto generic_costs = UsagePixelFormatCost(LoadGenericCostEntries());
for (uint32_t is_x = 0; is_x < 2; ++is_x) {
// Formats are in ascending preference order (descending cost order).
std::array modifier_list = {
fuchsia_images2::PixelFormatModifier::kLinear,
fuchsia_images2::PixelFormatModifier::kArmAfbc16X16,
fuchsia_images2::PixelFormatModifier::kArmAfbc16X16SplitBlockSparseYuv,
fuchsia_images2::PixelFormatModifier::kArmAfbc16X16SplitBlockSparseYuvTiledHeader,
fuchsia_images2::PixelFormatModifier::kArmAfbc16X16Te,
fuchsia_images2::PixelFormatModifier::kArmAfbc16X16SplitBlockSparseYuvTe,
fuchsia_images2::PixelFormatModifier::kArmAfbc16X16SplitBlockSparseYuvTeTiledHeader,
};
fuchsia_sysmem2::BufferCollectionConstraints constraints;
constraints.image_format_constraints().emplace(modifier_list.size());
for (uint32_t i = 0; i < modifier_list.size(); ++i) {
{
fuchsia_sysmem2::ImageFormatConstraints image_format_constraints;
{
image_format_constraints.pixel_format() = fuchsia_images2::PixelFormat::kB8G8R8A8;
image_format_constraints.pixel_format_modifier() = modifier_list[i];
if (is_x) {
image_format_constraints.is_alpha_present() = false;
}
}
constraints.image_format_constraints()->at(i) = std::move(image_format_constraints);
}
}
for (uint32_t i = 1; i < modifier_list.size(); ++i) {
EXPECT_LT(0, arm_costs.Compare(constraints, i - 1, i)) << "i=" << i;
EXPECT_GT(0, arm_costs.Compare(constraints, i, i - 1)) << "i=%d" << i;
EXPECT_EQ(0, generic_costs.Compare(constraints, i - 1, i));
EXPECT_EQ(0, generic_costs.Compare(constraints, i, i - 1));
}
}
}
} // namespace
} // namespace sysmem_service