blob: b4c0b3ba0133da10017b40acec83c573b69538df [file] [log] [blame]
// Copyright 2016 The Chromium 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 <memory>
#include <string>
#include <utility>
#include <vector>
#include "base/macros.h"
#include "mojo/public/cpp/base/file_path_mojom_traits.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/display/display.h"
#include "ui/display/display_layout.h"
#include "ui/display/mojo/display_layout_struct_traits.h"
#include "ui/display/mojo/display_mode_struct_traits.h"
#include "ui/display/mojo/display_snapshot_struct_traits.h"
#include "ui/display/mojo/display_struct_traits.h"
#include "ui/display/mojo/gamma_ramp_rgb_entry_struct_traits.h"
#include "ui/display/types/display_constants.h"
#include "ui/display/types/display_mode.h"
#include "ui/display/types/display_snapshot.h"
#include "ui/display/types/gamma_ramp_rgb_entry.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/mojo/color_space_mojom_traits.h"
namespace display {
namespace {
constexpr int64_t kDisplayId1 = 123;
constexpr int64_t kDisplayId2 = 456;
constexpr int64_t kDisplayId3 = 789;
void CheckDisplaysEqual(const Display& input, const Display& output) {
EXPECT_NE(&input, &output); // Make sure they aren't the same object.
EXPECT_EQ(input.id(), output.id());
EXPECT_EQ(input.bounds(), output.bounds());
EXPECT_EQ(input.GetSizeInPixel(), output.GetSizeInPixel());
EXPECT_EQ(input.work_area(), output.work_area());
EXPECT_EQ(input.device_scale_factor(), output.device_scale_factor());
EXPECT_EQ(input.rotation(), output.rotation());
EXPECT_EQ(input.touch_support(), output.touch_support());
EXPECT_EQ(input.accelerometer_support(), output.accelerometer_support());
EXPECT_EQ(input.maximum_cursor_size(), output.maximum_cursor_size());
EXPECT_EQ(input.color_depth(), output.color_depth());
EXPECT_EQ(input.depth_per_component(), output.depth_per_component());
EXPECT_EQ(input.is_monochrome(), output.is_monochrome());
EXPECT_EQ(input.display_frequency(), output.display_frequency());
}
void CheckDisplayLayoutsEqual(const DisplayLayout& input,
const DisplayLayout& output) {
EXPECT_NE(&input, &output); // Make sure they aren't the same object.
EXPECT_EQ(input.placement_list, output.placement_list);
EXPECT_EQ(input.default_unified, output.default_unified);
EXPECT_EQ(input.primary_id, output.primary_id);
}
void CheckDisplayModesEqual(const DisplayMode* input,
const DisplayMode* output) {
// DisplaySnapshot can have null DisplayModes, so if |input| is null then
// |output| should be null too.
if (input == nullptr && output == nullptr)
return;
EXPECT_NE(input, output); // Make sure they aren't the same object.
EXPECT_EQ(input->size(), output->size());
EXPECT_EQ(input->is_interlaced(), output->is_interlaced());
EXPECT_EQ(input->refresh_rate(), output->refresh_rate());
}
void CheckDisplaySnapShotMojoEqual(const DisplaySnapshot& input,
const DisplaySnapshot& output) {
// We want to test each component individually to make sure each data member
// was correctly serialized and deserialized.
EXPECT_NE(&input, &output); // Make sure they aren't the same object.
EXPECT_EQ(input.display_id(), output.display_id());
EXPECT_EQ(input.origin(), output.origin());
EXPECT_EQ(input.physical_size(), output.physical_size());
EXPECT_EQ(input.type(), output.type());
EXPECT_EQ(input.is_aspect_preserving_scaling(),
output.is_aspect_preserving_scaling());
EXPECT_EQ(input.has_overscan(), output.has_overscan());
EXPECT_EQ(input.has_color_correction_matrix(),
output.has_color_correction_matrix());
EXPECT_EQ(input.color_correction_in_linear_space(),
output.color_correction_in_linear_space());
EXPECT_EQ(input.display_name(), output.display_name());
EXPECT_EQ(input.sys_path(), output.sys_path());
EXPECT_EQ(input.product_code(), output.product_code());
EXPECT_EQ(input.modes().size(), output.modes().size());
for (size_t i = 0; i < input.modes().size(); i++)
CheckDisplayModesEqual(input.modes()[i].get(), output.modes()[i].get());
EXPECT_EQ(input.edid(), output.edid());
CheckDisplayModesEqual(input.current_mode(), output.current_mode());
CheckDisplayModesEqual(input.native_mode(), output.native_mode());
EXPECT_EQ(input.maximum_cursor_size(), output.maximum_cursor_size());
}
// Test StructTrait serialization and deserialization for copyable type. |input|
// will be serialized and then deserialized into |output|.
template <class MojomType, class Type>
void SerializeAndDeserialize(const Type& input, Type* output) {
MojomType::Deserialize(MojomType::Serialize(&input), output);
}
// Test StructTrait serialization and deserialization for move only type.
// |input| will be serialized and then deserialized into |output|.
template <class MojomType, class Type>
void SerializeAndDeserialize(Type&& input, Type* output) {
MojomType::Deserialize(MojomType::Serialize(&input), output);
}
} // namespace
TEST(DisplayStructTraitsTest, DefaultDisplayValues) {
Display input(5);
Display output;
SerializeAndDeserialize<mojom::Display>(input, &output);
CheckDisplaysEqual(input, output);
}
TEST(DisplayStructTraitsTest, SetAllDisplayValues) {
const gfx::Rect bounds(100, 200, 500, 600);
const gfx::Rect work_area(150, 250, 400, 500);
const gfx::Size maximum_cursor_size(64, 64);
Display input(246345234, bounds);
input.set_work_area(work_area);
input.set_device_scale_factor(2.0f);
input.set_rotation(Display::ROTATE_270);
input.set_touch_support(Display::TouchSupport::AVAILABLE);
input.set_accelerometer_support(Display::AccelerometerSupport::UNAVAILABLE);
input.set_maximum_cursor_size(maximum_cursor_size);
input.set_color_depth(input.color_depth() + 1);
input.set_depth_per_component(input.depth_per_component() + 1);
input.set_is_monochrome(!input.is_monochrome());
input.set_display_frequency(input.display_frequency() + 1);
Display output;
SerializeAndDeserialize<mojom::Display>(input, &output);
CheckDisplaysEqual(input, output);
}
TEST(DisplayStructTraitsTest, DefaultDisplayMode) {
std::unique_ptr<DisplayMode> input =
std::make_unique<DisplayMode>(gfx::Size(1024, 768), true, 61.0);
std::unique_ptr<DisplayMode> output;
SerializeAndDeserialize<mojom::DisplayMode>(input->Clone(), &output);
CheckDisplayModesEqual(input.get(), output.get());
}
TEST(DisplayStructTraitsTest, DisplayPlacementFlushAtTop) {
DisplayPlacement input;
input.display_id = kDisplayId1;
input.parent_display_id = kDisplayId2;
input.position = DisplayPlacement::TOP;
input.offset = 0;
input.offset_reference = DisplayPlacement::TOP_LEFT;
DisplayPlacement output;
SerializeAndDeserialize<mojom::DisplayPlacement>(input, &output);
EXPECT_EQ(input, output);
}
TEST(DisplayStructTraitsTest, DisplayPlacementWithOffset) {
DisplayPlacement input;
input.display_id = kDisplayId1;
input.parent_display_id = kDisplayId2;
input.position = DisplayPlacement::BOTTOM;
input.offset = -100;
input.offset_reference = DisplayPlacement::BOTTOM_RIGHT;
DisplayPlacement output;
SerializeAndDeserialize<mojom::DisplayPlacement>(input, &output);
EXPECT_EQ(input, output);
}
TEST(DisplayStructTraitsTest, DisplayLayoutTwoExtended) {
DisplayPlacement placement;
placement.display_id = kDisplayId1;
placement.parent_display_id = kDisplayId2;
placement.position = DisplayPlacement::RIGHT;
placement.offset = 0;
placement.offset_reference = DisplayPlacement::TOP_LEFT;
auto input = std::make_unique<DisplayLayout>();
input->placement_list.push_back(placement);
input->primary_id = kDisplayId2;
input->default_unified = true;
std::unique_ptr<DisplayLayout> output;
SerializeAndDeserialize<mojom::DisplayLayout>(input->Copy(), &output);
CheckDisplayLayoutsEqual(*input, *output);
}
TEST(DisplayStructTraitsTest, DisplayLayoutThreeExtended) {
DisplayPlacement placement1;
placement1.display_id = kDisplayId2;
placement1.parent_display_id = kDisplayId1;
placement1.position = DisplayPlacement::LEFT;
placement1.offset = 0;
placement1.offset_reference = DisplayPlacement::TOP_LEFT;
DisplayPlacement placement2;
placement2.display_id = kDisplayId3;
placement2.parent_display_id = kDisplayId1;
placement2.position = DisplayPlacement::RIGHT;
placement2.offset = -100;
placement2.offset_reference = DisplayPlacement::BOTTOM_RIGHT;
auto input = std::make_unique<DisplayLayout>();
input->placement_list.push_back(placement1);
input->placement_list.push_back(placement2);
input->primary_id = kDisplayId1;
input->default_unified = false;
std::unique_ptr<DisplayLayout> output;
SerializeAndDeserialize<mojom::DisplayLayout>(input->Copy(), &output);
CheckDisplayLayoutsEqual(*input, *output);
}
TEST(DisplayStructTraitsTest, BasicGammaRampRGBEntry) {
const GammaRampRGBEntry input{259, 81, 16};
GammaRampRGBEntry output;
SerializeAndDeserialize<mojom::GammaRampRGBEntry>(input, &output);
EXPECT_EQ(input.r, output.r);
EXPECT_EQ(input.g, output.g);
EXPECT_EQ(input.b, output.b);
}
// One display mode, current and native mode nullptr.
TEST(DisplayStructTraitsTest, DisplaySnapshotCurrentAndNativeModesNull) {
// Prepare sample input with random values.
const int64_t display_id = 7;
const gfx::Point origin(1, 2);
const gfx::Size physical_size(5, 9);
const gfx::Size maximum_cursor_size(3, 5);
const DisplayConnectionType type = DISPLAY_CONNECTION_TYPE_DISPLAYPORT;
const bool is_aspect_preserving_scaling = true;
const bool has_overscan = true;
const bool has_color_correction_matrix = true;
const bool color_correction_in_linear_space = true;
const gfx::ColorSpace display_color_space = gfx::ColorSpace::CreateREC709();
const std::string display_name("whatever display_name");
const base::FilePath sys_path = base::FilePath::FromUTF8Unsafe("a/cb");
const int64_t product_code = 19;
const int32_t year_of_manufacture = 1776;
const DisplayMode display_mode(gfx::Size(13, 11), true, 40.0f);
DisplaySnapshot::DisplayModeList modes;
modes.push_back(display_mode.Clone());
const DisplayMode* current_mode = nullptr;
const DisplayMode* native_mode = nullptr;
const std::vector<uint8_t> edid = {1};
std::unique_ptr<DisplaySnapshot> input = std::make_unique<DisplaySnapshot>(
display_id, origin, physical_size, type, is_aspect_preserving_scaling,
has_overscan, has_color_correction_matrix,
color_correction_in_linear_space, display_color_space, display_name,
sys_path, std::move(modes), edid, current_mode, native_mode, product_code,
year_of_manufacture, maximum_cursor_size);
std::unique_ptr<DisplaySnapshot> output;
SerializeAndDeserialize<mojom::DisplaySnapshot>(input->Clone(), &output);
CheckDisplaySnapShotMojoEqual(*input, *output);
}
// One display mode that is the native mode and no current mode.
TEST(DisplayStructTraitsTest, DisplaySnapshotCurrentModeNull) {
// Prepare sample input with random values.
const int64_t display_id = 6;
const gfx::Point origin(11, 32);
const gfx::Size physical_size(55, 49);
const gfx::Size maximum_cursor_size(13, 95);
const DisplayConnectionType type = DISPLAY_CONNECTION_TYPE_VGA;
const bool is_aspect_preserving_scaling = true;
const bool has_overscan = true;
const bool has_color_correction_matrix = true;
const bool color_correction_in_linear_space = true;
const gfx::ColorSpace display_color_space = gfx::ColorSpace::CreateREC709();
const std::string display_name("whatever display_name");
const base::FilePath sys_path = base::FilePath::FromUTF8Unsafe("z/b");
const int64_t product_code = 9;
const int32_t year_of_manufacture = 1776;
const DisplayMode display_mode(gfx::Size(13, 11), true, 50.0f);
DisplaySnapshot::DisplayModeList modes;
modes.push_back(display_mode.Clone());
const DisplayMode* current_mode = nullptr;
const DisplayMode* native_mode = modes[0].get();
const std::vector<uint8_t> edid = {1};
std::unique_ptr<DisplaySnapshot> input = std::make_unique<DisplaySnapshot>(
display_id, origin, physical_size, type, is_aspect_preserving_scaling,
has_overscan, has_color_correction_matrix,
color_correction_in_linear_space, display_color_space, display_name,
sys_path, std::move(modes), edid, current_mode, native_mode, product_code,
year_of_manufacture, maximum_cursor_size);
std::unique_ptr<DisplaySnapshot> output;
SerializeAndDeserialize<mojom::DisplaySnapshot>(input->Clone(), &output);
CheckDisplaySnapShotMojoEqual(*input, *output);
}
// Multiple display modes, both native and current mode set.
TEST(DisplayStructTraitsTest, DisplaySnapshotExternal) {
// Prepare sample input from external display.
const int64_t display_id = 9834293210466051;
const gfx::Point origin(0, 1760);
const gfx::Size physical_size(520, 320);
const gfx::Size maximum_cursor_size(4, 5);
const DisplayConnectionType type = DISPLAY_CONNECTION_TYPE_HDMI;
const bool is_aspect_preserving_scaling = false;
const bool has_overscan = false;
const bool has_color_correction_matrix = false;
const bool color_correction_in_linear_space = false;
const std::string display_name("HP Z24i");
const gfx::ColorSpace display_color_space = gfx::ColorSpace::CreateSRGB();
const base::FilePath sys_path = base::FilePath::FromUTF8Unsafe("a/cb");
const int64_t product_code = 139;
const int32_t year_of_manufacture = 2018;
const DisplayMode display_mode(gfx::Size(1024, 768), false, 60.0f);
const DisplayMode display_current_mode(gfx::Size(1440, 900), false, 59.89f);
const DisplayMode display_native_mode(gfx::Size(1920, 1200), false, 59.89f);
DisplaySnapshot::DisplayModeList modes;
modes.push_back(display_mode.Clone());
modes.push_back(display_current_mode.Clone());
modes.push_back(display_native_mode.Clone());
const DisplayMode* current_mode = modes[1].get();
const DisplayMode* native_mode = modes[2].get();
const std::vector<uint8_t> edid = {2, 3, 4, 5};
std::unique_ptr<DisplaySnapshot> input = std::make_unique<DisplaySnapshot>(
display_id, origin, physical_size, type, is_aspect_preserving_scaling,
has_overscan, has_color_correction_matrix,
color_correction_in_linear_space, display_color_space, display_name,
sys_path, std::move(modes), edid, current_mode, native_mode, product_code,
year_of_manufacture, maximum_cursor_size);
std::unique_ptr<DisplaySnapshot> output;
SerializeAndDeserialize<mojom::DisplaySnapshot>(input->Clone(), &output);
CheckDisplaySnapShotMojoEqual(*input, *output);
}
TEST(DisplayStructTraitsTest, DisplaySnapshotInternal) {
// Prepare sample input from Pixel's internal display.
const int64_t display_id = 13761487533244416;
const gfx::Point origin(0, 0);
const gfx::Size physical_size(270, 180);
const gfx::Size maximum_cursor_size(64, 64);
const DisplayConnectionType type = DISPLAY_CONNECTION_TYPE_INTERNAL;
const bool is_aspect_preserving_scaling = true;
const bool has_overscan = false;
const bool has_color_correction_matrix = false;
const bool color_correction_in_linear_space = false;
const gfx::ColorSpace display_color_space =
gfx::ColorSpace::CreateDisplayP3D65();
const std::string display_name("");
const base::FilePath sys_path;
const int64_t product_code = 139;
const int32_t year_of_manufacture = 2018;
const DisplayMode display_mode(gfx::Size(2560, 1700), false, 95.96f);
DisplaySnapshot::DisplayModeList modes;
modes.push_back(display_mode.Clone());
const DisplayMode* current_mode = modes[0].get();
const DisplayMode* native_mode = modes[0].get();
const std::vector<uint8_t> edid = {2, 3};
std::unique_ptr<DisplaySnapshot> input = std::make_unique<DisplaySnapshot>(
display_id, origin, physical_size, type, is_aspect_preserving_scaling,
has_overscan, has_color_correction_matrix,
color_correction_in_linear_space, display_color_space, display_name,
sys_path, std::move(modes), edid, current_mode, native_mode, product_code,
year_of_manufacture, maximum_cursor_size);
std::unique_ptr<DisplaySnapshot> output;
SerializeAndDeserialize<mojom::DisplaySnapshot>(input->Clone(), &output);
CheckDisplaySnapShotMojoEqual(*input, *output);
}
} // namespace display