From 4d600057db0c977e75c5d6e2d5f01fa69d30b364 Mon Sep 17 00:00:00 2001 From: Marissa Wall Date: Thu, 15 Dec 2016 12:16:01 -0800 Subject: test-hwc2: open and close hwc2 device Test: Add "#define HAVE_NO_SURFACE_FLINGER" to frameworks/native/libs/gui/BufferQueueCore.cpp. Recompile and flash. Run "mm" in frameworks/native/services/surfaceflinger/tests/hwc2. Push test-hwc2 to device. Run "adb root && adb shell stop". Run test case. Ex: "./test-hwc2" Change-Id: Ie7d3963540b0c96db8251bd745f37beab8dd340b --- services/surfaceflinger/tests/hwc2/Android.mk | 32 ++++++ services/surfaceflinger/tests/hwc2/Hwc2Test.cpp | 145 ++++++++++++++++++++++++ 2 files changed, 177 insertions(+) create mode 100644 services/surfaceflinger/tests/hwc2/Android.mk create mode 100644 services/surfaceflinger/tests/hwc2/Hwc2Test.cpp diff --git a/services/surfaceflinger/tests/hwc2/Android.mk b/services/surfaceflinger/tests/hwc2/Android.mk new file mode 100644 index 0000000000..1322293100 --- /dev/null +++ b/services/surfaceflinger/tests/hwc2/Android.mk @@ -0,0 +1,32 @@ +# +# Copyright (C) 2016 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_MODULE := test-hwc2 +LOCAL_MODULE_TAGS := tests +LOCAL_CFLAGS += \ + -fstack-protector-all \ + -g \ + -Wall -Wextra \ + -Werror \ + -fno-builtin +LOCAL_SHARED_LIBRARIES := libcutils libutils libhardware +LOCAL_STATIC_LIBRARIES := libbase libadf libadfhwc +LOCAL_SRC_FILES := Hwc2Test.cpp + +include $(BUILD_NATIVE_TEST) diff --git a/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp new file mode 100644 index 0000000000..85c6d876db --- /dev/null +++ b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp @@ -0,0 +1,145 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +#define HWC2_INCLUDE_STRINGIFICATION +#define HWC2_USE_CPP11 +#include +#undef HWC2_INCLUDE_STRINGIFICATION +#undef HWC2_USE_CPP11 + +class Hwc2Test : public testing::Test { +public: + + virtual void SetUp() + { + hw_module_t const* hwc2Module; + + int err = hw_get_module(HWC_HARDWARE_MODULE_ID, &hwc2Module); + ASSERT_GE(err, 0) << "failed to get hwc hardware module: " + << strerror(-err); + + /* The following method will fail if you have not run + * "adb shell stop" */ + err = hwc2_open(hwc2Module, &mHwc2Device); + ASSERT_GE(err, 0) << "failed to open hwc hardware module: " + << strerror(-err); + } + + virtual void TearDown() + { + if (mHwc2Device) + hwc2_close(mHwc2Device); + } + +protected: + hwc2_function_pointer_t getFunction(hwc2_function_descriptor_t descriptor) + { + return mHwc2Device->getFunction(mHwc2Device, descriptor); + } + + void getCapabilities(std::vector* outCapabilities) + { + uint32_t num = 0; + + mHwc2Device->getCapabilities(mHwc2Device, &num, nullptr); + + outCapabilities->resize(num); + + mHwc2Device->getCapabilities(mHwc2Device, &num, + reinterpret_cast(outCapabilities->data())); + } + + hwc2_device_t* mHwc2Device = nullptr; +}; + + +static const std::array requiredFunctions = {{ + HWC2_FUNCTION_ACCEPT_DISPLAY_CHANGES, + HWC2_FUNCTION_CREATE_LAYER, + HWC2_FUNCTION_CREATE_VIRTUAL_DISPLAY, + HWC2_FUNCTION_DESTROY_LAYER, + HWC2_FUNCTION_DESTROY_VIRTUAL_DISPLAY, + HWC2_FUNCTION_DUMP, + HWC2_FUNCTION_GET_ACTIVE_CONFIG, + HWC2_FUNCTION_GET_CHANGED_COMPOSITION_TYPES, + HWC2_FUNCTION_GET_CLIENT_TARGET_SUPPORT, + HWC2_FUNCTION_GET_COLOR_MODES, + HWC2_FUNCTION_GET_DISPLAY_ATTRIBUTE, + HWC2_FUNCTION_GET_DISPLAY_CONFIGS, + HWC2_FUNCTION_GET_DISPLAY_NAME, + HWC2_FUNCTION_GET_DISPLAY_REQUESTS, + HWC2_FUNCTION_GET_DISPLAY_TYPE, + HWC2_FUNCTION_GET_DOZE_SUPPORT, + HWC2_FUNCTION_GET_HDR_CAPABILITIES, + HWC2_FUNCTION_GET_MAX_VIRTUAL_DISPLAY_COUNT, + HWC2_FUNCTION_GET_RELEASE_FENCES, + HWC2_FUNCTION_PRESENT_DISPLAY, + HWC2_FUNCTION_REGISTER_CALLBACK, + HWC2_FUNCTION_SET_ACTIVE_CONFIG, + HWC2_FUNCTION_SET_CLIENT_TARGET, + HWC2_FUNCTION_SET_COLOR_MODE, + HWC2_FUNCTION_SET_COLOR_TRANSFORM, + HWC2_FUNCTION_SET_CURSOR_POSITION, + HWC2_FUNCTION_SET_LAYER_BLEND_MODE, + HWC2_FUNCTION_SET_LAYER_BUFFER, + HWC2_FUNCTION_SET_LAYER_COLOR, + HWC2_FUNCTION_SET_LAYER_COMPOSITION_TYPE, + HWC2_FUNCTION_SET_LAYER_DATASPACE, + HWC2_FUNCTION_SET_LAYER_DISPLAY_FRAME, + HWC2_FUNCTION_SET_LAYER_PLANE_ALPHA, + HWC2_FUNCTION_SET_LAYER_SOURCE_CROP, + HWC2_FUNCTION_SET_LAYER_SURFACE_DAMAGE, + HWC2_FUNCTION_SET_LAYER_TRANSFORM, + HWC2_FUNCTION_SET_LAYER_VISIBLE_REGION, + HWC2_FUNCTION_SET_LAYER_Z_ORDER, + HWC2_FUNCTION_SET_OUTPUT_BUFFER, + HWC2_FUNCTION_SET_POWER_MODE, + HWC2_FUNCTION_SET_VSYNC_ENABLED, + HWC2_FUNCTION_VALIDATE_DISPLAY, +}}; + +/* TESTCASE: Tests that the HWC2 supports all required functions. */ +TEST_F(Hwc2Test, GET_FUNCTION) +{ + for (hwc2_function_descriptor_t descriptor : requiredFunctions) { + hwc2_function_pointer_t pfn = getFunction(descriptor); + EXPECT_TRUE(pfn) << "failed to get function " + << getFunctionDescriptorName(descriptor); + } +} + +/* TESTCASE: Tests that the HWC2 fails to retrieve and invalid function. */ +TEST_F(Hwc2Test, GET_FUNCTION_invalid_function) +{ + hwc2_function_pointer_t pfn = getFunction(HWC2_FUNCTION_INVALID); + EXPECT_FALSE(pfn) << "failed to get invalid function"; +} + +/* TESTCASE: Tests that the HWC2 does not return an invalid capability. */ +TEST_F(Hwc2Test, GET_CAPABILITIES) +{ + std::vector capabilities; + + getCapabilities(&capabilities); + + EXPECT_EQ(std::count(capabilities.begin(), capabilities.end(), + HWC2_CAPABILITY_INVALID), 0); +} -- cgit v1.2.3-59-g8ed1b From a4b01488e852c0c16df89d04914e6f060dd862e3 Mon Sep 17 00:00:00 2001 From: Marissa Wall Date: Fri, 17 Feb 2017 20:52:03 -0800 Subject: test-hwc2: register callback functions Test: Add "#define HAVE_NO_SURFACE_FLINGER" to frameworks/native/libs/gui/BufferQueueCore.cpp. Recompile and flash. Run "mm" in frameworks/native/services/surfaceflinger/tests/hwc2. Push test-hwc2 to device. Run "adb root && adb shell stop". Run test case. Ex: "./test-hwc2" Change-Id: Ic48431a830115f40e9e851bca8f7c730b06f6529 --- services/surfaceflinger/tests/hwc2/Hwc2Test.cpp | 59 +++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp index 85c6d876db..0ccc27664a 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp +++ b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp @@ -49,6 +49,23 @@ public: hwc2_close(mHwc2Device); } + void registerCallback(hwc2_callback_descriptor_t descriptor, + hwc2_callback_data_t callbackData, hwc2_function_pointer_t pointer, + hwc2_error_t* outErr = nullptr) + { + auto pfn = reinterpret_cast( + getFunction(HWC2_FUNCTION_REGISTER_CALLBACK)); + ASSERT_TRUE(pfn) << "failed to get function"; + + auto err = static_cast(pfn(mHwc2Device, descriptor, + callbackData, pointer)); + if (outErr) { + *outErr = err; + } else { + ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to register callback"; + } + } + protected: hwc2_function_pointer_t getFunction(hwc2_function_descriptor_t descriptor) { @@ -143,3 +160,45 @@ TEST_F(Hwc2Test, GET_CAPABILITIES) EXPECT_EQ(std::count(capabilities.begin(), capabilities.end(), HWC2_CAPABILITY_INVALID), 0); } + +static const std::array callbackDescriptors = {{ + HWC2_CALLBACK_HOTPLUG, + HWC2_CALLBACK_REFRESH, + HWC2_CALLBACK_VSYNC, +}}; + +/* TESTCASE: Tests that the HWC2 can successfully register all required + * callback functions. */ +TEST_F(Hwc2Test, REGISTER_CALLBACK) +{ + hwc2_callback_data_t data = reinterpret_cast( + const_cast("data")); + + for (auto descriptor : callbackDescriptors) { + ASSERT_NO_FATAL_FAILURE(registerCallback(descriptor, data, + []() { return; })); + } +} + +/* TESTCASE: Test that the HWC2 fails to register invalid callbacks. */ +TEST_F(Hwc2Test, REGISTER_CALLBACK_bad_parameter) +{ + hwc2_callback_data_t data = reinterpret_cast( + const_cast("data")); + hwc2_error_t err = HWC2_ERROR_NONE; + + ASSERT_NO_FATAL_FAILURE(registerCallback(HWC2_CALLBACK_INVALID, data, + []() { return; }, &err)); + EXPECT_EQ(err, HWC2_ERROR_BAD_PARAMETER) << "returned wrong error code"; +} + +/* TESTCASE: Tests that the HWC2 can register a callback with null data. */ +TEST_F(Hwc2Test, REGISTER_CALLBACK_null_data) +{ + hwc2_callback_data_t data = nullptr; + + for (auto descriptor : callbackDescriptors) { + ASSERT_NO_FATAL_FAILURE(registerCallback(descriptor, data, + []() { return; })); + } +} -- cgit v1.2.3-59-g8ed1b From cfb9a07ff9bcc36afc08cef5874344aec03f18fa Mon Sep 17 00:00:00 2001 From: Marissa Wall Date: Fri, 17 Feb 2017 20:53:18 -0800 Subject: test-hwc2: display type support Test: Add "#define HAVE_NO_SURFACE_FLINGER" to frameworks/native/libs/gui/BufferQueueCore.cpp. Recompile and flash. Run "mm" in frameworks/native/services/surfaceflinger/tests/hwc2. Push test-hwc2 to device. Run "adb root && adb shell stop". Run test case. Ex: "./test-hwc2" Change-Id: I0b1be456e360ac5a218ca0cd0e9f297e178c8727 --- services/surfaceflinger/tests/hwc2/Hwc2Test.cpp | 125 ++++++++++++++++++++++++ 1 file changed, 125 insertions(+) diff --git a/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp index 0ccc27664a..15ded9acfe 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp +++ b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp @@ -15,6 +15,7 @@ */ #include +#include #include #include #include @@ -25,6 +26,9 @@ #undef HWC2_INCLUDE_STRINGIFICATION #undef HWC2_USE_CPP11 +void hwc2TestHotplugCallback(hwc2_callback_data_t callbackData, + hwc2_display_t display, int32_t connected); + class Hwc2Test : public testing::Test { public: @@ -41,6 +45,8 @@ public: err = hwc2_open(hwc2Module, &mHwc2Device); ASSERT_GE(err, 0) << "failed to open hwc hardware module: " << strerror(-err); + + populateDisplays(); } virtual void TearDown() @@ -66,6 +72,37 @@ public: } } + void getDisplayType(hwc2_display_t display, hwc2_display_type_t* outType, + hwc2_error_t* outErr = nullptr) + { + auto pfn = reinterpret_cast( + getFunction(HWC2_FUNCTION_GET_DISPLAY_TYPE)); + ASSERT_TRUE(pfn) << "failed to get function"; + + auto err = static_cast(pfn(mHwc2Device, display, + reinterpret_cast(outType))); + if (outErr) { + *outErr = err; + } else { + ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to get display type"; + } + } + + /* If the populateDisplays function is still receiving displays and the + * display is connected, the display handle is stored in mDisplays. */ + void hotplugCallback(hwc2_display_t display, int32_t connected) + { + std::lock_guard lock(mHotplugMutex); + + if (mHotplugStatus != Hwc2TestHotplugStatus::Receiving) + return; + + if (connected == HWC2_CONNECTION_CONNECTED) + mDisplays.insert(display); + + mHotplugCv.notify_all(); + } + protected: hwc2_function_pointer_t getFunction(hwc2_function_descriptor_t descriptor) { @@ -84,9 +121,70 @@ protected: reinterpret_cast(outCapabilities->data())); } + /* Registers a hotplug callback and waits for hotplug callbacks. This + * function will have no effect if called more than once. */ + void populateDisplays() + { + /* Sets the hotplug status to receiving */ + { + std::lock_guard lock(mHotplugMutex); + + if (mHotplugStatus != Hwc2TestHotplugStatus::Init) + return; + mHotplugStatus = Hwc2TestHotplugStatus::Receiving; + } + + /* Registers the callback. This function call cannot be locked because + * a callback could happen on the same thread */ + ASSERT_NO_FATAL_FAILURE(registerCallback(HWC2_CALLBACK_HOTPLUG, this, + reinterpret_cast( + hwc2TestHotplugCallback))); + + /* Waits for hotplug events. If a hotplug event has not come within 1 + * second, stop waiting. */ + std::unique_lock lock(mHotplugMutex); + + while (mHotplugCv.wait_for(lock, std::chrono::seconds(1)) != + std::cv_status::timeout) { } + + /* Sets the hotplug status to done. Future calls will have no effect */ + mHotplugStatus = Hwc2TestHotplugStatus::Done; + } + + void getBadDisplay(hwc2_display_t* outDisplay) + { + for (hwc2_display_t display = 0; display < UINT64_MAX; display++) { + if (mDisplays.count(display) == 0) { + *outDisplay = display; + return; + } + } + ASSERT_TRUE(false) << "Unable to find bad display. UINT64_MAX displays" + " are registered. This should never happen."; + } + hwc2_device_t* mHwc2Device = nullptr; + + enum class Hwc2TestHotplugStatus { + Init = 1, + Receiving, + Done, + }; + + std::mutex mHotplugMutex; + std::condition_variable mHotplugCv; + Hwc2TestHotplugStatus mHotplugStatus = Hwc2TestHotplugStatus::Init; + std::unordered_set mDisplays; }; +void hwc2TestHotplugCallback(hwc2_callback_data_t callbackData, + hwc2_display_t display, int32_t connection) +{ + if (callbackData) + static_cast(callbackData)->hotplugCallback(display, + connection); +} + static const std::array requiredFunctions = {{ HWC2_FUNCTION_ACCEPT_DISPLAY_CHANGES, @@ -202,3 +300,30 @@ TEST_F(Hwc2Test, REGISTER_CALLBACK_null_data) []() { return; })); } } + +/* TESTCASE: Tests that the HWC2 returns the correct display type for each + * physical display. */ +TEST_F(Hwc2Test, GET_DISPLAY_TYPE) +{ + for (auto display : mDisplays) { + hwc2_display_type_t type; + + ASSERT_NO_FATAL_FAILURE(getDisplayType(display, &type)); + EXPECT_EQ(type, HWC2_DISPLAY_TYPE_PHYSICAL) << "failed to return" + " correct display type"; + } +} + +/* TESTCASE: Tests that the HWC2 returns an error when the display type of a bad + * display is requested. */ +TEST_F(Hwc2Test, GET_DISPLAY_TYPE_bad_display) +{ + hwc2_display_t display; + hwc2_display_type_t type; + hwc2_error_t err = HWC2_ERROR_NONE; + + ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display)); + + ASSERT_NO_FATAL_FAILURE(getDisplayType(display, &type, &err)); + EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code"; +} -- cgit v1.2.3-59-g8ed1b From 1db2e37295cd89946ec5280c1db2dc11bba45ee2 Mon Sep 17 00:00:00 2001 From: Marissa Wall Date: Thu, 15 Dec 2016 12:19:39 -0800 Subject: test-hwc2: create and destroy layers Test: Add "#define HAVE_NO_SURFACE_FLINGER" to frameworks/native/libs/gui/BufferQueueCore.cpp. Recompile and flash. Run "mm" in frameworks/native/services/surfaceflinger/tests/hwc2. Push test-hwc2 to device. Run "adb root && adb shell stop". Run test case. Ex: "./test-hwc2" Change-Id: I508174a871a74d4c4d2843fc0ded84c517553bce --- services/surfaceflinger/tests/hwc2/Hwc2Test.cpp | 181 ++++++++++++++++++++++++ 1 file changed, 181 insertions(+) diff --git a/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp index 15ded9acfe..57bf681b69 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp +++ b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp @@ -51,6 +51,15 @@ public: virtual void TearDown() { + + for (auto itr = mLayers.begin(); itr != mLayers.end();) { + hwc2_display_t display = itr->first; + hwc2_layer_t layer = itr->second; + itr++; + /* Destroys and removes the layer from mLayers */ + destroyLayer(display, layer); + } + if (mHwc2Device) hwc2_close(mHwc2Device); } @@ -103,6 +112,46 @@ public: mHotplugCv.notify_all(); } + void createLayer(hwc2_display_t display, hwc2_layer_t* outLayer, + hwc2_error_t* outErr = nullptr) + { + auto pfn = reinterpret_cast( + getFunction(HWC2_FUNCTION_CREATE_LAYER)); + ASSERT_TRUE(pfn) << "failed to get function"; + + auto err = static_cast(pfn(mHwc2Device, display, + outLayer)); + + if (err == HWC2_ERROR_NONE) + mLayers.insert(std::make_pair(display, *outLayer)); + + if (outErr) { + *outErr = err; + } else { + ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to create layer"; + } + } + + void destroyLayer(hwc2_display_t display, hwc2_layer_t layer, + hwc2_error_t* outErr = nullptr) + { + auto pfn = reinterpret_cast( + getFunction(HWC2_FUNCTION_DESTROY_LAYER)); + ASSERT_TRUE(pfn) << "failed to get function"; + + auto err = static_cast(pfn(mHwc2Device, display, layer)); + + if (err == HWC2_ERROR_NONE) + mLayers.erase(std::make_pair(display, layer)); + + if (outErr) { + *outErr = err; + } else { + ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to destroy layer " + << layer; + } + } + protected: hwc2_function_pointer_t getFunction(hwc2_function_descriptor_t descriptor) { @@ -163,6 +212,37 @@ protected: " are registered. This should never happen."; } + /* NOTE: will create min(newlayerCnt, max supported layers) layers */ + void createLayers(hwc2_display_t display, + std::vector* outLayers, size_t newLayerCnt) + { + std::vector newLayers; + hwc2_layer_t layer; + hwc2_error_t err = HWC2_ERROR_NONE; + + for (size_t i = 0; i < newLayerCnt; i++) { + + EXPECT_NO_FATAL_FAILURE(createLayer(display, &layer, &err)); + if (err == HWC2_ERROR_NO_RESOURCES) + break; + if (err != HWC2_ERROR_NONE) { + newLayers.clear(); + ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to create layer"; + } + newLayers.push_back(layer); + } + + *outLayers = std::move(newLayers); + } + + void destroyLayers(hwc2_display_t display, + std::vector&& layers) + { + for (hwc2_layer_t layer : layers) { + EXPECT_NO_FATAL_FAILURE(destroyLayer(display, layer)); + } + } + hwc2_device_t* mHwc2Device = nullptr; enum class Hwc2TestHotplugStatus { @@ -175,6 +255,10 @@ protected: std::condition_variable mHotplugCv; Hwc2TestHotplugStatus mHotplugStatus = Hwc2TestHotplugStatus::Init; std::unordered_set mDisplays; + + /* Store all created layers that have not been destroyed. If an ASSERT_* + * fails, then destroy the layers on exit */ + std::set> mLayers; }; void hwc2TestHotplugCallback(hwc2_callback_data_t callbackData, @@ -327,3 +411,100 @@ TEST_F(Hwc2Test, GET_DISPLAY_TYPE_bad_display) ASSERT_NO_FATAL_FAILURE(getDisplayType(display, &type, &err)); EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code"; } + +/* TESTCASE: Tests that the HWC2 can create and destroy layers. */ +TEST_F(Hwc2Test, CREATE_DESTROY_LAYER) +{ + for (auto display : mDisplays) { + hwc2_layer_t layer; + + ASSERT_NO_FATAL_FAILURE(createLayer(display, &layer)); + + ASSERT_NO_FATAL_FAILURE(destroyLayer(display, layer)); + } +} + +/* TESTCASE: Tests that the HWC2 cannot create a layer for a bad display */ +TEST_F(Hwc2Test, CREATE_LAYER_bad_display) +{ + hwc2_display_t display; + hwc2_layer_t layer; + hwc2_error_t err = HWC2_ERROR_NONE; + + ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display)); + + ASSERT_NO_FATAL_FAILURE(createLayer(display, &layer, &err)); + EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code"; +} + +/* TESTCASE: Tests that the HWC2 will either support a large number of resources + * or will return no resources. */ +TEST_F(Hwc2Test, CREATE_LAYER_no_resources) +{ + const size_t layerCnt = 1000; + + for (auto display : mDisplays) { + std::vector layers; + + ASSERT_NO_FATAL_FAILURE(createLayers(display, &layers, layerCnt)); + + ASSERT_NO_FATAL_FAILURE(destroyLayers(display, std::move(layers))); + } +} + +/* TESTCASE: Tests that the HWC2 cannot destroy a layer for a bad display */ +TEST_F(Hwc2Test, DESTROY_LAYER_bad_display) +{ + hwc2_display_t badDisplay; + + ASSERT_NO_FATAL_FAILURE(getBadDisplay(&badDisplay)); + + for (auto display : mDisplays) { + hwc2_layer_t layer = 0; + hwc2_error_t err = HWC2_ERROR_NONE; + + ASSERT_NO_FATAL_FAILURE(destroyLayer(badDisplay, layer, &err)); + EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code"; + + ASSERT_NO_FATAL_FAILURE(createLayer(display, &layer)); + + ASSERT_NO_FATAL_FAILURE(destroyLayer(badDisplay, layer, &err)); + EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code"; + + ASSERT_NO_FATAL_FAILURE(destroyLayer(display, layer)); + } +} + +/* TESTCASE: Tests that the HWC2 cannot destory a bad layer */ +TEST_F(Hwc2Test, DESTROY_LAYER_bad_layer) +{ + for (auto display : mDisplays) { + hwc2_layer_t layer; + hwc2_error_t err = HWC2_ERROR_NONE; + + ASSERT_NO_FATAL_FAILURE(destroyLayer(display, UINT64_MAX / 2, &err)); + EXPECT_EQ(err, HWC2_ERROR_BAD_LAYER) << "returned wrong error code"; + + ASSERT_NO_FATAL_FAILURE(destroyLayer(display, 0, &err)); + EXPECT_EQ(err, HWC2_ERROR_BAD_LAYER) << "returned wrong error code"; + + ASSERT_NO_FATAL_FAILURE(destroyLayer(display, UINT64_MAX - 1, &err)); + EXPECT_EQ(err, HWC2_ERROR_BAD_LAYER) << "returned wrong error code"; + + ASSERT_NO_FATAL_FAILURE(destroyLayer(display, 1, &err)); + EXPECT_EQ(err, HWC2_ERROR_BAD_LAYER) << "returned wrong error code"; + + ASSERT_NO_FATAL_FAILURE(destroyLayer(display, UINT64_MAX, &err)); + EXPECT_EQ(err, HWC2_ERROR_BAD_LAYER) << "returned wrong error code"; + + ASSERT_NO_FATAL_FAILURE(createLayer(display, &layer)); + + ASSERT_NO_FATAL_FAILURE(destroyLayer(display, layer + 1, &err)); + EXPECT_EQ(err, HWC2_ERROR_BAD_LAYER) << "returned wrong error code"; + + ASSERT_NO_FATAL_FAILURE(destroyLayer(display, layer)); + + ASSERT_NO_FATAL_FAILURE(destroyLayer(display, layer, &err)); + EXPECT_EQ(err, HWC2_ERROR_BAD_LAYER) << "returned wrong error code"; + } +} -- cgit v1.2.3-59-g8ed1b From cf935cbfa66ec65a71485e91e63a5929dc2922a1 Mon Sep 17 00:00:00 2001 From: Marissa Wall Date: Thu, 15 Dec 2016 12:20:47 -0800 Subject: test-hwc2: get display configs and attributes Test: Add "#define HAVE_NO_SURFACE_FLINGER" to frameworks/native/libs/gui/BufferQueueCore.cpp. Recompile and flash. Run "mm" in frameworks/native/services/surfaceflinger/tests/hwc2. Push test-hwc2 to device. Run "adb root && adb shell stop". Run test case. Ex: "./test-hwc2" Change-Id: I7aa1200057d9fa3cc7988554e8efcf6db2674584 --- services/surfaceflinger/tests/hwc2/Hwc2Test.cpp | 230 ++++++++++++++++++++++++ 1 file changed, 230 insertions(+) diff --git a/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp index 57bf681b69..87ea7585be 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp +++ b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp @@ -152,6 +152,53 @@ public: } } + void getDisplayAttribute(hwc2_display_t display, hwc2_config_t config, + hwc2_attribute_t attribute, int32_t* outValue, + hwc2_error_t* outErr = nullptr) + { + auto pfn = reinterpret_cast( + getFunction(HWC2_FUNCTION_GET_DISPLAY_ATTRIBUTE)); + ASSERT_TRUE(pfn) << "failed to get function"; + + auto err = static_cast(pfn(mHwc2Device, display, config, + attribute, outValue)); + + if (outErr) { + *outErr = err; + } else { + ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to get display attribute " + << getAttributeName(attribute) << " for config " << config; + } + } + + void getDisplayConfigs(hwc2_display_t display, + std::vector* outConfigs, + hwc2_error_t* outErr = nullptr) + { + auto pfn = reinterpret_cast( + getFunction(HWC2_FUNCTION_GET_DISPLAY_CONFIGS)); + ASSERT_TRUE(pfn) << "failed to get function"; + + uint32_t numConfigs = 0; + + auto err = static_cast(pfn(mHwc2Device, display, + &numConfigs, nullptr)); + + if (err == HWC2_ERROR_NONE) { + outConfigs->resize(numConfigs); + + err = static_cast(pfn(mHwc2Device, display, + &numConfigs, outConfigs->data())); + } + + if (outErr) { + *outErr = err; + } else { + ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to get configs for" + " display " << display; + } + } + protected: hwc2_function_pointer_t getFunction(hwc2_function_descriptor_t descriptor) { @@ -243,6 +290,26 @@ protected: } } + void getInvalidConfig(hwc2_display_t display, hwc2_config_t* outConfig) + { + std::vector configs; + + ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs)); + + hwc2_config_t CONFIG_MAX = UINT32_MAX; + + ASSERT_LE(configs.size() - 1, CONFIG_MAX) << "every config value" + " (2^32 values) has been taken which shouldn't happen"; + + hwc2_config_t config; + for (config = 0; config < CONFIG_MAX; config++) { + if (std::count(configs.begin(), configs.end(), config) == 0) + break; + } + + *outConfig = config; + } + hwc2_device_t* mHwc2Device = nullptr; enum class Hwc2TestHotplugStatus { @@ -508,3 +575,166 @@ TEST_F(Hwc2Test, DESTROY_LAYER_bad_layer) EXPECT_EQ(err, HWC2_ERROR_BAD_LAYER) << "returned wrong error code"; } } + +static const std::array requiredAttributes = {{ + HWC2_ATTRIBUTE_WIDTH, + HWC2_ATTRIBUTE_HEIGHT, +}}; + +static const std::array optionalAttributes = {{ + HWC2_ATTRIBUTE_VSYNC_PERIOD, + HWC2_ATTRIBUTE_DPI_X, + HWC2_ATTRIBUTE_DPI_Y, +}}; + +/* TESTCASE: Tests that the HWC2 can return display attributes for a valid + * config. */ +TEST_F(Hwc2Test, GET_DISPLAY_ATTRIBUTE) +{ + for (auto display : mDisplays) { + std::vector configs; + + ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs)); + + for (auto config : configs) { + int32_t value; + + for (auto attribute : requiredAttributes) { + ASSERT_NO_FATAL_FAILURE(getDisplayAttribute(display, config, + attribute, &value)); + EXPECT_GE(value, 0) << "missing required attribute " + << getAttributeName(attribute) << " for config " + << config; + } + for (auto attribute : optionalAttributes) { + ASSERT_NO_FATAL_FAILURE(getDisplayAttribute(display, config, + attribute, &value)); + } + } + } +} + +/* TESTCASE: Tests that the HWC2 will return a value of -1 for an invalid + * attribute */ +TEST_F(Hwc2Test, GET_DISPLAY_ATTRIBUTE_invalid_attribute) +{ + const hwc2_attribute_t attribute = HWC2_ATTRIBUTE_INVALID; + + for (auto display : mDisplays) { + std::vector configs; + + ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs)); + + for (auto config : configs) { + int32_t value; + hwc2_error_t err = HWC2_ERROR_NONE; + + ASSERT_NO_FATAL_FAILURE(getDisplayAttribute(display, config, + attribute, &value, &err)); + EXPECT_EQ(value, -1) << "failed to return -1 for an invalid" + " attribute for config " << config; + } + } +} + +/* TESTCASE: Tests that the HWC2 will fail to get attributes for a bad display */ +TEST_F(Hwc2Test, GET_DISPLAY_ATTRIBUTE_bad_display) +{ + hwc2_display_t display; + const hwc2_config_t config = 0; + int32_t value; + hwc2_error_t err = HWC2_ERROR_NONE; + + ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display)); + + for (auto attribute : requiredAttributes) { + ASSERT_NO_FATAL_FAILURE(getDisplayAttribute(display, config, attribute, + &value, &err)); + EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code"; + } + + for (auto attribute : optionalAttributes) { + ASSERT_NO_FATAL_FAILURE(getDisplayAttribute(display, config, attribute, + &value, &err)); + EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code"; + } +} + +/* TESTCASE: Tests that the HWC2 will fail to get attributes for a bad config */ +TEST_F(Hwc2Test, GET_DISPLAY_ATTRIBUTE_bad_config) +{ + for (auto display : mDisplays) { + hwc2_config_t config; + int32_t value; + hwc2_error_t err = HWC2_ERROR_NONE; + + ASSERT_NO_FATAL_FAILURE(getInvalidConfig(display, &config)); + + for (auto attribute : requiredAttributes) { + ASSERT_NO_FATAL_FAILURE(getDisplayAttribute(display, config, + attribute, &value, &err)); + EXPECT_EQ(err, HWC2_ERROR_BAD_CONFIG) << "returned wrong error code"; + } + + for (auto attribute : optionalAttributes) { + ASSERT_NO_FATAL_FAILURE(getDisplayAttribute(display, config, + attribute, &value, &err)); + EXPECT_EQ(err, HWC2_ERROR_BAD_CONFIG) << "returned wrong error code"; + } + } +} + +/* TESTCASE: Tests that the HWC2 will get display configs for active displays */ +TEST_F(Hwc2Test, GET_DISPLAY_CONFIGS) +{ + for (auto display : mDisplays) { + std::vector configs; + + ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs)); + } +} + +/* TESTCASE: Tests that the HWC2 will not get display configs for bad displays */ +TEST_F(Hwc2Test, GET_DISPLAY_CONFIGS_bad_display) +{ + hwc2_display_t display; + std::vector configs; + hwc2_error_t err = HWC2_ERROR_NONE; + + ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display)); + + ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs, &err)); + + EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code"; + EXPECT_TRUE(configs.empty()) << "returned configs for bad display"; +} + +/* TESTCASE: Tests that the HWC2 will return the same config list multiple + * times in a row. */ +TEST_F(Hwc2Test, GET_DISPLAY_CONFIGS_same) +{ + for (auto display : mDisplays) { + std::vector configs1, configs2; + + ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs1)); + ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs2)); + + EXPECT_TRUE(std::is_permutation(configs1.begin(), configs1.end(), + configs2.begin())) << "returned two different config sets"; + } +} + +/* TESTCASE: Tests that the HWC2 does not return duplicate display configs */ +TEST_F(Hwc2Test, GET_DISPLAY_CONFIGS_duplicate) +{ + for (auto display : mDisplays) { + std::vector configs; + + ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs)); + + std::unordered_set configsSet(configs.begin(), + configs.end()); + EXPECT_EQ(configs.size(), configsSet.size()) << "returned duplicate" + " configs"; + } +} -- cgit v1.2.3-59-g8ed1b From 93dc04fda8de625d780bcd9b3cef15ad7a4932a8 Mon Sep 17 00:00:00 2001 From: Marissa Wall Date: Thu, 15 Dec 2016 12:21:46 -0800 Subject: test-hwc2: get and set active config Test: Add "#define HAVE_NO_SURFACE_FLINGER" to frameworks/native/libs/gui/BufferQueueCore.cpp. Recompile and flash. Run "mm" in frameworks/native/services/surfaceflinger/tests/hwc2. Push test-hwc2 to device. Run "adb root && adb shell stop". Run test case. Ex: "./test-hwc2" Change-Id: I2ac012a27b31e34886e3ec7f04a8bfc3fd1b83c4 --- services/surfaceflinger/tests/hwc2/Hwc2Test.cpp | 134 ++++++++++++++++++++++++ 1 file changed, 134 insertions(+) diff --git a/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp index 87ea7585be..c50546c94f 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp +++ b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp @@ -199,6 +199,39 @@ public: } } + void getActiveConfig(hwc2_display_t display, hwc2_config_t* outConfig, + hwc2_error_t* outErr = nullptr) + { + auto pfn = reinterpret_cast( + getFunction(HWC2_FUNCTION_GET_ACTIVE_CONFIG)); + ASSERT_TRUE(pfn) << "failed to get function"; + + auto err = static_cast(pfn(mHwc2Device, display, + outConfig)); + if (outErr) { + *outErr = err; + } else { + ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to get active config on" + " display " << display; + } + } + + void setActiveConfig(hwc2_display_t display, hwc2_config_t config, + hwc2_error_t* outErr = nullptr) + { + auto pfn = reinterpret_cast( + getFunction(HWC2_FUNCTION_SET_ACTIVE_CONFIG)); + ASSERT_TRUE(pfn) << "failed to get function"; + + auto err = static_cast(pfn(mHwc2Device, display, config)); + if (outErr) { + *outErr = err; + } else { + ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set active config " + << config; + } + } + protected: hwc2_function_pointer_t getFunction(hwc2_function_descriptor_t descriptor) { @@ -738,3 +771,104 @@ TEST_F(Hwc2Test, GET_DISPLAY_CONFIGS_duplicate) " configs"; } } + +/* TESTCASE: Tests that the HWC2 returns the active config for a display */ +TEST_F(Hwc2Test, GET_ACTIVE_CONFIG) +{ + for (auto display : mDisplays) { + std::vector configs; + + ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs)); + + for (auto config : configs) { + hwc2_config_t activeConfig; + + ASSERT_NO_FATAL_FAILURE(setActiveConfig(display, config)); + ASSERT_NO_FATAL_FAILURE(getActiveConfig(display, &activeConfig)); + + EXPECT_EQ(activeConfig, config) << "failed to get active config"; + } + } +} + +/* TESTCASE: Tests that the HWC2 does not return an active config for a bad + * display. */ +TEST_F(Hwc2Test, GET_ACTIVE_CONFIG_bad_display) +{ + hwc2_display_t display; + hwc2_config_t activeConfig; + hwc2_error_t err = HWC2_ERROR_NONE; + + ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display)); + + ASSERT_NO_FATAL_FAILURE(getActiveConfig(display, &activeConfig, &err)); + + EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code"; +} + +/* TESTCASE: Tests that the HWC2 either begins with a valid active config + * or returns an error when getActiveConfig is called. */ +TEST_F(Hwc2Test, GET_ACTIVE_CONFIG_bad_config) +{ + for (auto display : mDisplays) { + std::vector configs; + hwc2_config_t activeConfig; + hwc2_error_t err = HWC2_ERROR_NONE; + + ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs)); + + if (configs.empty()) + return; + + ASSERT_NO_FATAL_FAILURE(getActiveConfig(display, &activeConfig, &err)); + if (err == HWC2_ERROR_NONE) { + EXPECT_NE(std::count(configs.begin(), configs.end(), + activeConfig), 0) << "active config is not found in " + " configs for display"; + } else { + EXPECT_EQ(err, HWC2_ERROR_BAD_CONFIG) << "returned wrong error code"; + } + } +} + +/* TESTCASE: Tests that the HWC2 can set every display config as an active + * config */ +TEST_F(Hwc2Test, SET_ACTIVE_CONFIG) +{ + for (auto display : mDisplays) { + std::vector configs; + + ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs)); + + for (auto config : configs) { + EXPECT_NO_FATAL_FAILURE(setActiveConfig(display, config)); + } + } +} + +/* TESTCASE: Tests that the HWC2 cannot set an active config for a bad display */ +TEST_F(Hwc2Test, SET_ACTIVE_CONFIG_bad_display) +{ + hwc2_display_t display; + const hwc2_config_t config = 0; + hwc2_error_t err = HWC2_ERROR_NONE; + + ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display)); + + ASSERT_NO_FATAL_FAILURE(setActiveConfig(display, config, &err)); + EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code"; +} + +/* TESTCASE: Tests that the HWC2 cannot set an invalid active config */ +TEST_F(Hwc2Test, SET_ACTIVE_CONFIG_bad_config) +{ + for (auto display : mDisplays) { + hwc2_config_t config; + hwc2_error_t err = HWC2_ERROR_NONE; + + ASSERT_NO_FATAL_FAILURE(getInvalidConfig(display, &config)); + + ASSERT_NO_FATAL_FAILURE(setActiveConfig(display, config, &err)); + EXPECT_EQ(err, HWC2_ERROR_BAD_CONFIG) << "returned wrong error code"; + } +} -- cgit v1.2.3-59-g8ed1b From 03c917316507dd1c12cdb15a84f5e41576ab4bde Mon Sep 17 00:00:00 2001 From: Marissa Wall Date: Thu, 15 Dec 2016 12:23:16 -0800 Subject: test-hwc2: power mode support Test: Add "#define HAVE_NO_SURFACE_FLINGER" to frameworks/native/libs/gui/BufferQueueCore.cpp. Recompile and flash. Run "mm" in frameworks/native/services/surfaceflinger/tests/hwc2. Push test-hwc2 to device. Run "adb root && adb shell stop". Run test case. Ex: "./test-hwc2" Change-Id: I4439f8215bb8d0652e6f5ad40f0c4625f7e97f9b --- services/surfaceflinger/tests/hwc2/Hwc2Test.cpp | 195 ++++++++++++++++++++++++ 1 file changed, 195 insertions(+) diff --git a/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp index c50546c94f..c7ed9e4654 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp +++ b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp @@ -60,6 +60,14 @@ public: destroyLayer(display, layer); } + for (auto itr = mActiveDisplays.begin(); itr != mActiveDisplays.end();) { + hwc2_display_t display = *itr; + itr++; + /* Sets power mode to off and removes the display from + * mActiveDisplays */ + setPowerMode(display, HWC2_POWER_MODE_OFF); + } + if (mHwc2Device) hwc2_close(mHwc2Device); } @@ -232,6 +240,48 @@ public: } } + void getDozeSupport(hwc2_display_t display, int32_t* outSupport, + hwc2_error_t* outErr = nullptr) + { + auto pfn = reinterpret_cast( + getFunction(HWC2_FUNCTION_GET_DOZE_SUPPORT)); + ASSERT_TRUE(pfn) << "failed to get function"; + + auto err = static_cast(pfn(mHwc2Device, display, + outSupport)); + if (outErr) { + *outErr = err; + } else { + ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to get doze support on" + " display " << display; + } + } + + void setPowerMode(hwc2_display_t display, hwc2_power_mode_t mode, + hwc2_error_t* outErr = nullptr) + { + auto pfn = reinterpret_cast( + getFunction(HWC2_FUNCTION_SET_POWER_MODE)); + ASSERT_TRUE(pfn) << "failed to get function"; + + auto err = static_cast(pfn(mHwc2Device, display, + mode)); + if (outErr) { + *outErr = err; + if (err != HWC2_ERROR_NONE) + return; + } else { + ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set power mode " + << getPowerModeName(mode) << " on display " << display; + } + + if (mode == HWC2_POWER_MODE_OFF) { + mActiveDisplays.erase(display); + } else { + mActiveDisplays.insert(display); + } + } + protected: hwc2_function_pointer_t getFunction(hwc2_function_descriptor_t descriptor) { @@ -359,6 +409,10 @@ protected: /* Store all created layers that have not been destroyed. If an ASSERT_* * fails, then destroy the layers on exit */ std::set> mLayers; + + /* Store the power mode state. If it is not HWC2_POWER_MODE_OFF when + * tearing down the test cases, change it to HWC2_POWER_MODE_OFF */ + std::set mActiveDisplays; }; void hwc2TestHotplugCallback(hwc2_callback_data_t callbackData, @@ -872,3 +926,144 @@ TEST_F(Hwc2Test, SET_ACTIVE_CONFIG_bad_config) EXPECT_EQ(err, HWC2_ERROR_BAD_CONFIG) << "returned wrong error code"; } } + +/* TESTCASE: Tests that the HWC2 returns a valid value for getDozeSupport. */ +TEST_F(Hwc2Test, GET_DOZE_SUPPORT) +{ + for (auto display : mDisplays) { + int32_t support = -1; + + ASSERT_NO_FATAL_FAILURE(getDozeSupport(display, &support)); + + EXPECT_TRUE(support == 0 || support == 1) << "invalid doze support value"; + } +} + +/* TESTCASE: Tests that the HWC2 cannot get doze support for a bad display. */ +TEST_F(Hwc2Test, GET_DOZE_SUPPORT_bad_display) +{ + hwc2_display_t display; + int32_t support = -1; + hwc2_error_t err = HWC2_ERROR_NONE; + + ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display)); + + ASSERT_NO_FATAL_FAILURE(getDozeSupport(display, &support, &err)); + + EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code"; +} + +/* TESTCASE: Tests that the HWC2 can set all supported power modes */ +TEST_F(Hwc2Test, SET_POWER_MODE) +{ + for (auto display : mDisplays) { + ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_ON)); + ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_OFF)); + + int32_t support = -1; + ASSERT_NO_FATAL_FAILURE(getDozeSupport(display, &support)); + if (support != 1) + return; + + ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_DOZE)); + ASSERT_NO_FATAL_FAILURE(setPowerMode(display, + HWC2_POWER_MODE_DOZE_SUSPEND)); + + ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_OFF)); + } +} + +/* TESTCASE: Tests that the HWC2 cannot set a power mode for a bad display. */ +TEST_F(Hwc2Test, SET_POWER_MODE_bad_display) +{ + hwc2_display_t display; + hwc2_error_t err = HWC2_ERROR_NONE; + + ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display)); + + ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_ON, &err)); + EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code"; + + ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_OFF, &err)); + EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code"; + + int32_t support = -1; + ASSERT_NO_FATAL_FAILURE(getDozeSupport(display, &support, &err)); + if (support != 1) + return; + + ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_DOZE, &err)); + EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code"; + + ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_DOZE_SUSPEND, + &err)); + EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code"; +} + +/* TESTCASE: Tests that the HWC2 cannot set an invalid power mode value. */ +TEST_F(Hwc2Test, SET_POWER_MODE_bad_parameter) +{ + for (auto display : mDisplays) { + hwc2_power_mode_t mode = static_cast( + HWC2_POWER_MODE_DOZE_SUSPEND + 1); + hwc2_error_t err = HWC2_ERROR_NONE; + + ASSERT_NO_FATAL_FAILURE(setPowerMode(display, mode, &err)); + EXPECT_EQ(err, HWC2_ERROR_BAD_PARAMETER) << "returned wrong error code " + << mode; + } +} + +/* TESTCASE: Tests that the HWC2 will return unsupported if it does not support + * an optional power mode. */ +TEST_F(Hwc2Test, SET_POWER_MODE_unsupported) +{ + for (auto display : mDisplays) { + int32_t support = -1; + hwc2_error_t err = HWC2_ERROR_NONE; + + ASSERT_NO_FATAL_FAILURE(getDozeSupport(display, &support, &err)); + if (support == 1) + return; + + ASSERT_EQ(support, 0) << "invalid doze support value"; + + ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_DOZE, + &err)); + EXPECT_EQ(err, HWC2_ERROR_UNSUPPORTED) << "returned wrong error code"; + + ASSERT_NO_FATAL_FAILURE(setPowerMode(display, + HWC2_POWER_MODE_DOZE_SUSPEND, &err)); + EXPECT_EQ(err, HWC2_ERROR_UNSUPPORTED) << "returned wrong error code"; + } +} + +/* TESTCASE: Tests that the HWC2 can set the same power mode multiple times. */ +TEST_F(Hwc2Test, SET_POWER_MODE_stress) +{ + for (auto display : mDisplays) { + ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_OFF)); + ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_OFF)); + + ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_ON)); + ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_ON)); + + ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_OFF)); + ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_OFF)); + + int32_t support = -1; + ASSERT_NO_FATAL_FAILURE(getDozeSupport(display, &support)); + if (support != 1) + return; + + ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_DOZE)); + ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_DOZE)); + + ASSERT_NO_FATAL_FAILURE(setPowerMode(display, + HWC2_POWER_MODE_DOZE_SUSPEND)); + ASSERT_NO_FATAL_FAILURE(setPowerMode(display, + HWC2_POWER_MODE_DOZE_SUSPEND)); + + ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_OFF)); + } +} -- cgit v1.2.3-59-g8ed1b From 572a1eedae1d15a8544c95f0284e5b1216a187d2 Mon Sep 17 00:00:00 2001 From: Marissa Wall Date: Thu, 15 Dec 2016 12:24:13 -0800 Subject: test-hwc2: enable vsync Test: Add "#define HAVE_NO_SURFACE_FLINGER" to frameworks/native/libs/gui/BufferQueueCore.cpp. Recompile and flash. Run "mm" in frameworks/native/services/surfaceflinger/tests/hwc2. Push test-hwc2 to device. Run "adb root && adb shell stop". Run test case. Ex: "./test-hwc2" Change-Id: I704fcf0ef097602440835981a47dc6c3785e332d --- services/surfaceflinger/tests/hwc2/Hwc2Test.cpp | 210 ++++++++++++++++++++++++ 1 file changed, 210 insertions(+) diff --git a/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp index c7ed9e4654..2505cb22e9 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp +++ b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp @@ -28,6 +28,8 @@ void hwc2TestHotplugCallback(hwc2_callback_data_t callbackData, hwc2_display_t display, int32_t connected); +void hwc2TestVsyncCallback(hwc2_callback_data_t callbackData, + hwc2_display_t display, int64_t timestamp); class Hwc2Test : public testing::Test { public: @@ -282,6 +284,31 @@ public: } } + void setVsyncEnabled(hwc2_display_t display, hwc2_vsync_t enabled, + hwc2_error_t* outErr = nullptr) + { + auto pfn = reinterpret_cast( + getFunction(HWC2_FUNCTION_SET_VSYNC_ENABLED)); + ASSERT_TRUE(pfn) << "failed to get function"; + + auto err = static_cast(pfn(mHwc2Device, display, + enabled)); + if (outErr) { + *outErr = err; + } else { + ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set vsync enabled " + << getVsyncName(enabled); + } + } + + void vsyncCallback(hwc2_display_t display, int64_t timestamp) + { + std::lock_guard lock(mVsyncMutex); + mVsyncDisplay = display; + mVsyncTimestamp = timestamp; + mVsyncCv.notify_all(); + } + protected: hwc2_function_pointer_t getFunction(hwc2_function_descriptor_t descriptor) { @@ -393,6 +420,32 @@ protected: *outConfig = config; } + void enableVsync(hwc2_display_t display) + { + ASSERT_NO_FATAL_FAILURE(registerCallback(HWC2_CALLBACK_VSYNC, this, + reinterpret_cast( + hwc2TestVsyncCallback))); + ASSERT_NO_FATAL_FAILURE(setVsyncEnabled(display, HWC2_VSYNC_ENABLE)); + } + + void disableVsync(hwc2_display_t display) + { + ASSERT_NO_FATAL_FAILURE(setVsyncEnabled(display, HWC2_VSYNC_DISABLE)); + } + + void waitForVsync(hwc2_display_t* outDisplay = nullptr, + int64_t* outTimestamp = nullptr) + { + std::unique_lock lock(mVsyncMutex); + ASSERT_EQ(mVsyncCv.wait_for(lock, std::chrono::seconds(3)), + std::cv_status::no_timeout) << "timed out attempting to get" + " vsync callback"; + if (outDisplay) + *outDisplay = mVsyncDisplay; + if (outTimestamp) + *outTimestamp = mVsyncTimestamp; + } + hwc2_device_t* mHwc2Device = nullptr; enum class Hwc2TestHotplugStatus { @@ -413,6 +466,11 @@ protected: /* Store the power mode state. If it is not HWC2_POWER_MODE_OFF when * tearing down the test cases, change it to HWC2_POWER_MODE_OFF */ std::set mActiveDisplays; + + std::mutex mVsyncMutex; + std::condition_variable mVsyncCv; + hwc2_display_t mVsyncDisplay; + int64_t mVsyncTimestamp = -1; }; void hwc2TestHotplugCallback(hwc2_callback_data_t callbackData, @@ -423,6 +481,14 @@ void hwc2TestHotplugCallback(hwc2_callback_data_t callbackData, connection); } +void hwc2TestVsyncCallback(hwc2_callback_data_t callbackData, + hwc2_display_t display, int64_t timestamp) +{ + if (callbackData) + static_cast(callbackData)->vsyncCallback(display, + timestamp); +} + static const std::array requiredFunctions = {{ HWC2_FUNCTION_ACCEPT_DISPLAY_CHANGES, @@ -1067,3 +1133,147 @@ TEST_F(Hwc2Test, SET_POWER_MODE_stress) ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_OFF)); } } + +/* TESTCASE: Tests that the HWC2 can enable and disable vsync on active + * displays */ +TEST_F(Hwc2Test, SET_VSYNC_ENABLED) +{ + for (auto display : mDisplays) { + hwc2_callback_data_t data = reinterpret_cast( + const_cast("data")); + + ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_ON)); + + ASSERT_NO_FATAL_FAILURE(registerCallback(HWC2_CALLBACK_VSYNC, data, + []() { return; })); + + ASSERT_NO_FATAL_FAILURE(setVsyncEnabled(display, HWC2_VSYNC_ENABLE)); + + ASSERT_NO_FATAL_FAILURE(setVsyncEnabled(display, HWC2_VSYNC_DISABLE)); + + ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_OFF)); + } +} + +/* TESTCASE: Tests that the HWC2 issues a valid vsync callback. */ +TEST_F(Hwc2Test, SET_VSYNC_ENABLED_callback) +{ + for (auto display : mDisplays) { + hwc2_display_t receivedDisplay; + int64_t receivedTimestamp; + + ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_ON)); + + ASSERT_NO_FATAL_FAILURE(enableVsync(display)); + + ASSERT_NO_FATAL_FAILURE(waitForVsync(&receivedDisplay, + &receivedTimestamp)); + + EXPECT_EQ(receivedDisplay, display) << "failed to get correct display"; + EXPECT_GE(receivedTimestamp, 0) << "failed to get valid timestamp"; + + ASSERT_NO_FATAL_FAILURE(disableVsync(display)); + + ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_OFF)); + } +} + +/* TESTCASE: Tests that the HWC2 cannot enable a vsync for a bad display */ +TEST_F(Hwc2Test, SET_VSYNC_ENABLED_bad_display) +{ + hwc2_display_t display; + hwc2_callback_data_t data = reinterpret_cast( + const_cast("data")); + hwc2_error_t err = HWC2_ERROR_NONE; + + ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display)); + + ASSERT_NO_FATAL_FAILURE(registerCallback(HWC2_CALLBACK_VSYNC, data, + []() { return; })); + + ASSERT_NO_FATAL_FAILURE(setVsyncEnabled(display, HWC2_VSYNC_ENABLE, &err)); + EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code"; + + ASSERT_NO_FATAL_FAILURE(setVsyncEnabled(display, HWC2_VSYNC_DISABLE, &err)); + EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code"; +} + +/* TESTCASE: Tests that the HWC2 cannot enable an invalid vsync value */ +TEST_F(Hwc2Test, SET_VSYNC_ENABLED_bad_parameter) +{ + for (auto display : mDisplays) { + hwc2_callback_data_t data = reinterpret_cast( + const_cast("data")); + hwc2_error_t err = HWC2_ERROR_NONE; + + ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_ON)); + + ASSERT_NO_FATAL_FAILURE(registerCallback(HWC2_CALLBACK_VSYNC, data, + []() { return; })); + + ASSERT_NO_FATAL_FAILURE(setVsyncEnabled(display, HWC2_VSYNC_INVALID, + &err)); + EXPECT_EQ(err, HWC2_ERROR_BAD_PARAMETER) << "returned wrong error code"; + + ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_OFF)); + } +} + +/* TESTCASE: Tests that the HWC2 can enable and disable a vsync value multiple + * times. */ +TEST_F(Hwc2Test, SET_VSYNC_ENABLED_stress) +{ + for (auto display : mDisplays) { + hwc2_callback_data_t data = reinterpret_cast( + const_cast("data")); + + ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_ON)); + + ASSERT_NO_FATAL_FAILURE(registerCallback(HWC2_CALLBACK_VSYNC, data, + []() { return; })); + + ASSERT_NO_FATAL_FAILURE(setVsyncEnabled(display, HWC2_VSYNC_DISABLE)); + + ASSERT_NO_FATAL_FAILURE(setVsyncEnabled(display, HWC2_VSYNC_ENABLE)); + ASSERT_NO_FATAL_FAILURE(setVsyncEnabled(display, HWC2_VSYNC_ENABLE)); + + ASSERT_NO_FATAL_FAILURE(setVsyncEnabled(display, HWC2_VSYNC_DISABLE)); + ASSERT_NO_FATAL_FAILURE(setVsyncEnabled(display, HWC2_VSYNC_DISABLE)); + + ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_OFF)); + } +} + +/* TESTCASE: Tests that the HWC2 can set a vsync enable value when the display + * is off and no callback is registered. */ +TEST_F(Hwc2Test, SET_VSYNC_ENABLED_no_callback_no_power) +{ + const uint secs = 1; + + for (auto display : mDisplays) { + ASSERT_NO_FATAL_FAILURE(setVsyncEnabled(display, HWC2_VSYNC_ENABLE)); + + sleep(secs); + + ASSERT_NO_FATAL_FAILURE(setVsyncEnabled(display, HWC2_VSYNC_DISABLE)); + } +} + +/* TESTCASE: Tests that the HWC2 can set a vsync enable value when no callback + * is registered. */ +TEST_F(Hwc2Test, SET_VSYNC_ENABLED_no_callback) +{ + const uint secs = 1; + + for (auto display : mDisplays) { + ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_ON)); + + ASSERT_NO_FATAL_FAILURE(setVsyncEnabled(display, HWC2_VSYNC_ENABLE)); + + sleep(secs); + + ASSERT_NO_FATAL_FAILURE(setVsyncEnabled(display, HWC2_VSYNC_DISABLE)); + + ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_OFF)); + } +} -- cgit v1.2.3-59-g8ed1b From dd4087f4eab87607662b7ee87e9e7b1298f7a3fc Mon Sep 17 00:00:00 2001 From: Marissa Wall Date: Thu, 15 Dec 2016 12:24:52 -0800 Subject: test-hwc2: get display name Test: Add "#define HAVE_NO_SURFACE_FLINGER" to frameworks/native/libs/gui/BufferQueueCore.cpp. Recompile and flash. Run "mm" in frameworks/native/services/surfaceflinger/tests/hwc2. Push test-hwc2 to device. Run "adb root && adb shell stop". Run test case. Ex: "./test-hwc2" Change-Id: I935329c0c572368f25aeefdbc913a7044f655aa5 --- services/surfaceflinger/tests/hwc2/Hwc2Test.cpp | 53 +++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp index 2505cb22e9..bc3eb1be8b 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp +++ b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp @@ -309,6 +309,35 @@ public: mVsyncCv.notify_all(); } + void getDisplayName(hwc2_display_t display, std::string* outName, + hwc2_error_t* outErr = nullptr) + { + auto pfn = reinterpret_cast( + getFunction(HWC2_FUNCTION_GET_DISPLAY_NAME)); + ASSERT_TRUE(pfn) << "failed to get function"; + + uint32_t size = 0; + + auto err = static_cast(pfn(mHwc2Device, display, &size, + nullptr)); + + if (err == HWC2_ERROR_NONE) { + std::vector name(size); + + err = static_cast(pfn(mHwc2Device, display, &size, + name.data())); + + outName->assign(name.data()); + } + + if (outErr) { + *outErr = err; + } else { + ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to get display name for " + << display; + } + } + protected: hwc2_function_pointer_t getFunction(hwc2_function_descriptor_t descriptor) { @@ -1277,3 +1306,27 @@ TEST_F(Hwc2Test, SET_VSYNC_ENABLED_no_callback) ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_OFF)); } } + +/* TESTCASE: Tests that the HWC2 returns a display name for each display */ +TEST_F(Hwc2Test, GET_DISPLAY_NAME) +{ + for (auto display : mDisplays) { + std::string name; + + ASSERT_NO_FATAL_FAILURE(getDisplayName(display, &name)); + } +} + +/* TESTCASE: Tests that the HWC2 does not return a display name for a bad + * display */ +TEST_F(Hwc2Test, GET_DISPLAY_NAME_bad_display) +{ + hwc2_display_t display; + std::string name; + hwc2_error_t err = HWC2_ERROR_NONE; + + ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display)); + + ASSERT_NO_FATAL_FAILURE(getDisplayName(display, &name, &err)); + EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code"; +} -- cgit v1.2.3-59-g8ed1b From 6bd8bfde4a965b743d3d4ebff5fdaa3db03a4bbc Mon Sep 17 00:00:00 2001 From: Marissa Wall Date: Thu, 15 Dec 2016 12:25:31 -0800 Subject: test-hwc2: set layer composition type Test: Add "#define HAVE_NO_SURFACE_FLINGER" to frameworks/native/libs/gui/BufferQueueCore.cpp. Recompile and flash. Run "mm" in frameworks/native/services/surfaceflinger/tests/hwc2. Push test-hwc2 to device. Run "adb root && adb shell stop". Run test case. Ex: "./test-hwc2" Change-Id: I9e71d0c01daa70f28031dd8310f2a40d7162a68e --- services/surfaceflinger/tests/hwc2/Android.mk | 5 +- services/surfaceflinger/tests/hwc2/Hwc2Test.cpp | 226 +++++++++++++++++++++ .../surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp | 47 +++++ services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h | 44 ++++ .../tests/hwc2/Hwc2TestProperties.cpp | 49 +++++ .../surfaceflinger/tests/hwc2/Hwc2TestProperties.h | 83 ++++++++ 6 files changed, 453 insertions(+), 1 deletion(-) create mode 100644 services/surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp create mode 100644 services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h create mode 100644 services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp create mode 100644 services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h diff --git a/services/surfaceflinger/tests/hwc2/Android.mk b/services/surfaceflinger/tests/hwc2/Android.mk index 1322293100..66a390df2f 100644 --- a/services/surfaceflinger/tests/hwc2/Android.mk +++ b/services/surfaceflinger/tests/hwc2/Android.mk @@ -27,6 +27,9 @@ LOCAL_CFLAGS += \ -fno-builtin LOCAL_SHARED_LIBRARIES := libcutils libutils libhardware LOCAL_STATIC_LIBRARIES := libbase libadf libadfhwc -LOCAL_SRC_FILES := Hwc2Test.cpp +LOCAL_SRC_FILES := \ + Hwc2Test.cpp \ + Hwc2TestProperties.cpp \ + Hwc2TestLayer.cpp include $(BUILD_NATIVE_TEST) diff --git a/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp index bc3eb1be8b..a50af49ed5 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp +++ b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp @@ -26,6 +26,8 @@ #undef HWC2_INCLUDE_STRINGIFICATION #undef HWC2_USE_CPP11 +#include "Hwc2TestLayer.h" + void hwc2TestHotplugCallback(hwc2_callback_data_t callbackData, hwc2_display_t display, int32_t connected); void hwc2TestVsyncCallback(hwc2_callback_data_t callbackData, @@ -338,6 +340,23 @@ public: } } + void setLayerCompositionType(hwc2_display_t display, hwc2_layer_t layer, + hwc2_composition_t composition, hwc2_error_t* outErr = nullptr) + { + auto pfn = reinterpret_cast( + getFunction(HWC2_FUNCTION_SET_LAYER_COMPOSITION_TYPE)); + ASSERT_TRUE(pfn) << "failed to get function"; + + auto err = static_cast(pfn(mHwc2Device, display, layer, + composition)); + if (outErr) { + *outErr = err; + } else { + ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set layer composition" + " type " << getCompositionName(composition); + } + } + protected: hwc2_function_pointer_t getFunction(hwc2_function_descriptor_t descriptor) { @@ -475,6 +494,152 @@ protected: *outTimestamp = mVsyncTimestamp; } + /* Calls a set property function from Hwc2Test to set a property value from + * Hwc2TestLayer to hwc2_layer_t on hwc2_display_t */ + using TestLayerPropertyFunction = void (*)(Hwc2Test* test, + hwc2_display_t display, hwc2_layer_t layer, + const Hwc2TestLayer& testLayer, hwc2_error_t* outErr); + + /* Calls a set property function from Hwc2Test to set a bad property value + * on hwc2_layer_t on hwc2_display_t */ + using TestLayerPropertyBadLayerFunction = void (*)(Hwc2Test* test, + hwc2_display_t display, hwc2_layer_t layer, + const Hwc2TestLayer& testLayer, hwc2_error_t* outErr); + + /* Calls a set property function from Hwc2Test to set a bad property value + * on hwc2_layer_t on hwc2_display_t */ + using TestLayerPropertyBadParameterFunction = void (*)(Hwc2Test* test, + hwc2_display_t display, hwc2_layer_t layer, hwc2_error_t* outErr); + + /* Advances a property of Hwc2TestLayer */ + using AdvanceProperty = bool (*)(Hwc2TestLayer* testLayer); + + /* For each active display it cycles through each display config and tests + * each property value. It creates a layer, sets the property and then + * destroys the layer */ + void setLayerProperty(Hwc2TestCoverage coverage, + TestLayerPropertyFunction function, AdvanceProperty advance) + { + for (auto display : mDisplays) { + std::vector configs; + + ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs)); + + for (auto config : configs) { + hwc2_layer_t layer; + + ASSERT_NO_FATAL_FAILURE(setActiveConfig(display, config)); + Hwc2TestLayer testLayer(coverage); + + do { + ASSERT_NO_FATAL_FAILURE(createLayer(display, &layer)); + + ASSERT_NO_FATAL_FAILURE(function(this, display, layer, + testLayer, nullptr)); + + ASSERT_NO_FATAL_FAILURE(destroyLayer(display, layer)); + } while (advance(&testLayer)); + } + } + } + + /* For each active display it cycles through each display config and tests + * each property value. It creates a layer, cycles through each property + * value and updates the layer property value and then destroys the layer */ + void setLayerPropertyUpdate(Hwc2TestCoverage coverage, + TestLayerPropertyFunction function, AdvanceProperty advance) + { + for (auto display : mDisplays) { + std::vector configs; + + ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs)); + + for (auto config : configs) { + hwc2_layer_t layer; + + ASSERT_NO_FATAL_FAILURE(setActiveConfig(display, config)); + Hwc2TestLayer testLayer(coverage); + + ASSERT_NO_FATAL_FAILURE(createLayer(display, &layer)); + + do { + ASSERT_NO_FATAL_FAILURE(function(this, display, layer, + testLayer, nullptr)); + } while (advance(&testLayer)); + + ASSERT_NO_FATAL_FAILURE(destroyLayer(display, layer)); + } + } + } + + /* For each active display it cycles through each display config. + * 1) It attempts to set a valid property value to bad layer handle. + * 2) It creates a layer x and attempts to set a valid property value to + * layer x + 1 + * 3) It destroys the layer x and attempts to set a valid property value to + * the destroyed layer x. + */ + void setLayerPropertyBadLayer(Hwc2TestCoverage coverage, + TestLayerPropertyBadLayerFunction function) + { + for (auto display : mDisplays) { + std::vector configs; + + ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs)); + + for (auto config : configs) { + hwc2_layer_t layer = 0; + hwc2_error_t err = HWC2_ERROR_NONE; + + ASSERT_NO_FATAL_FAILURE(setActiveConfig(display, config)); + Hwc2TestLayer testLayer(coverage); + + ASSERT_NO_FATAL_FAILURE(function(this, display, layer, + testLayer, &err)); + EXPECT_EQ(err, HWC2_ERROR_BAD_LAYER) << "returned wrong error code"; + + ASSERT_NO_FATAL_FAILURE(createLayer(display, &layer)); + + ASSERT_NO_FATAL_FAILURE(function(this, display, layer + 1, + testLayer, &err)); + EXPECT_EQ(err, HWC2_ERROR_BAD_LAYER) << "returned wrong error code"; + + ASSERT_NO_FATAL_FAILURE(destroyLayer(display, layer)); + + ASSERT_NO_FATAL_FAILURE(function(this, display, layer, + testLayer, &err)); + EXPECT_EQ(err, HWC2_ERROR_BAD_LAYER) << "returned wrong error code"; + } + } + } + + /* For each active display it cycles through each display config and tests + * each property value. It creates a layer, sets a bad property value and + * then destroys the layer */ + void setLayerPropertyBadParameter(TestLayerPropertyBadParameterFunction function) + { + for (auto display : mDisplays) { + std::vector configs; + + ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs)); + + for (auto config : configs) { + hwc2_layer_t layer; + hwc2_error_t err = HWC2_ERROR_NONE; + + ASSERT_NO_FATAL_FAILURE(setActiveConfig(display, config)); + + ASSERT_NO_FATAL_FAILURE(createLayer(display, &layer)); + + ASSERT_NO_FATAL_FAILURE(function(this, display, layer, &err)); + EXPECT_EQ(err, HWC2_ERROR_BAD_PARAMETER) << "returned wrong" + " error code"; + + ASSERT_NO_FATAL_FAILURE(destroyLayer(display, layer)); + } + } + } + hwc2_device_t* mHwc2Device = nullptr; enum class Hwc2TestHotplugStatus { @@ -518,6 +683,32 @@ void hwc2TestVsyncCallback(hwc2_callback_data_t callbackData, timestamp); } +void setComposition(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer, + const Hwc2TestLayer& testLayer, hwc2_error_t* outErr) +{ + hwc2_composition_t composition = testLayer.getComposition(); + hwc2_error_t err = HWC2_ERROR_NONE; + + ASSERT_NO_FATAL_FAILURE(test->setLayerCompositionType(display, layer, + composition, &err)); + if (outErr) { + *outErr = err; + return; + } + + if (composition != HWC2_COMPOSITION_SIDEBAND) { + EXPECT_EQ(err, HWC2_ERROR_NONE) << "returned wrong error code"; + } else { + EXPECT_TRUE(err == HWC2_ERROR_NONE || err == HWC2_ERROR_UNSUPPORTED) + << "returned wrong error code"; + } +} + +bool advanceComposition(Hwc2TestLayer* testLayer) +{ + return testLayer->advanceComposition(); +} + static const std::array requiredFunctions = {{ HWC2_FUNCTION_ACCEPT_DISPLAY_CHANGES, @@ -1330,3 +1521,38 @@ TEST_F(Hwc2Test, GET_DISPLAY_NAME_bad_display) ASSERT_NO_FATAL_FAILURE(getDisplayName(display, &name, &err)); EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code"; } + +/* TESTCASE: Tests that the HWC2 can set basic composition types. */ +TEST_F(Hwc2Test, SET_LAYER_COMPOSITION_TYPE) +{ + ASSERT_NO_FATAL_FAILURE(setLayerProperty(Hwc2TestCoverage::Complete, + setComposition, advanceComposition)); +} + +/* TESTCASE: Tests that the HWC2 can update a basic composition type on a + * layer. */ +TEST_F(Hwc2Test, SET_LAYER_COMPOSITION_TYPE_update) +{ + ASSERT_NO_FATAL_FAILURE(setLayerPropertyUpdate(Hwc2TestCoverage::Complete, + setComposition, advanceComposition)); +} + +/* TESTCASE: Tests that the HWC2 cannot set a composition type for a bad layer */ +TEST_F(Hwc2Test, SET_LAYER_COMPOSITION_TYPE_bad_layer) +{ + ASSERT_NO_FATAL_FAILURE(setLayerPropertyBadLayer(Hwc2TestCoverage::Default, + setComposition)); +} + +/* TESTCASE: Tests that the HWC2 cannot set a bad composition type */ +TEST_F(Hwc2Test, SET_LAYER_COMPOSITION_TYPE_bad_parameter) +{ + ASSERT_NO_FATAL_FAILURE(setLayerPropertyBadParameter( + [] (Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer, + hwc2_error_t* outErr) { + + ASSERT_NO_FATAL_FAILURE(test->setLayerCompositionType(display, + layer, HWC2_COMPOSITION_INVALID, outErr)); + } + )); +} diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp b/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp new file mode 100644 index 0000000000..09fb9217b8 --- /dev/null +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "Hwc2TestLayer.h" + +Hwc2TestLayer::Hwc2TestLayer(Hwc2TestCoverage coverage) + : mComposition(coverage) { } + +std::string Hwc2TestLayer::dump() const +{ + std::stringstream dmp; + + dmp << "layer: \n"; + dmp << mComposition.dump(); + + return dmp.str(); +} + +void Hwc2TestLayer::reset() +{ + mComposition.reset(); +} + +hwc2_composition_t Hwc2TestLayer::getComposition() const +{ + return mComposition.get(); +} + +bool Hwc2TestLayer::advanceComposition() +{ + return mComposition.advance(); +} diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h b/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h new file mode 100644 index 0000000000..9734ab8057 --- /dev/null +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _HWC2_TEST_LAYER_H +#define _HWC2_TEST_LAYER_H + +#include "Hwc2TestProperties.h" + +#define HWC2_INCLUDE_STRINGIFICATION +#define HWC2_USE_CPP11 +#include +#undef HWC2_INCLUDE_STRINGIFICATION +#undef HWC2_USE_CPP11 + +class Hwc2TestLayer { +public: + Hwc2TestLayer(Hwc2TestCoverage coverage); + + std::string dump() const; + + void reset(); + + hwc2_composition_t getComposition() const; + + bool advanceComposition(); + +private: + Hwc2TestComposition mComposition; +}; + +#endif /* ifndef _HWC2_TEST_LAYER_H */ diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp new file mode 100644 index 0000000000..ef399fd6d4 --- /dev/null +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "Hwc2TestProperties.h" + +Hwc2TestComposition::Hwc2TestComposition(Hwc2TestCoverage coverage) + : Hwc2TestProperty( + (coverage == Hwc2TestCoverage::Complete)? mCompleteCompositions: + (coverage == Hwc2TestCoverage::Basic)? mBasicCompositions: + mDefaultCompositions) { } + +std::string Hwc2TestComposition::dump() const +{ + std::stringstream dmp; + dmp << "\tcomposition: " << getCompositionName(get()) << "\n"; + return dmp.str(); +} + +const std::vector Hwc2TestComposition::mDefaultCompositions = { + HWC2_COMPOSITION_DEVICE, +}; + +const std::vector Hwc2TestComposition::mBasicCompositions = { + HWC2_COMPOSITION_CLIENT, + HWC2_COMPOSITION_DEVICE, +}; + +const std::vector Hwc2TestComposition::mCompleteCompositions = { + HWC2_COMPOSITION_CLIENT, + HWC2_COMPOSITION_DEVICE, + HWC2_COMPOSITION_SOLID_COLOR, + HWC2_COMPOSITION_CURSOR, + HWC2_COMPOSITION_SIDEBAND, +}; diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h new file mode 100644 index 0000000000..74f571e140 --- /dev/null +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _HWC2_TEST_PROPERTIES_H +#define _HWC2_TEST_PROPERTIES_H + +#include + +#define HWC2_INCLUDE_STRINGIFICATION +#define HWC2_USE_CPP11 +#include +#undef HWC2_INCLUDE_STRINGIFICATION +#undef HWC2_USE_CPP11 + +enum class Hwc2TestCoverage { + Default = 0, + Basic, + Complete, +}; + + +template +class Hwc2TestProperty { +public: + Hwc2TestProperty(const std::vector& list) + : mList(list) { } + + virtual ~Hwc2TestProperty() { }; + + virtual void reset() + { + mListIdx = 0; + } + + virtual bool advance() + { + if (mListIdx + 1 < mList.size()) { + mListIdx++; + return true; + } + reset(); + return false; + } + + virtual T get() const + { + return mList.at(mListIdx); + } + + virtual std::string dump() const = 0; + +protected: + const std::vector& mList; + size_t mListIdx = 0; +}; + + +class Hwc2TestComposition : public Hwc2TestProperty { +public: + Hwc2TestComposition(Hwc2TestCoverage coverage); + + std::string dump() const override; + +protected: + static const std::vector mDefaultCompositions; + static const std::vector mBasicCompositions; + static const std::vector mCompleteCompositions; +}; + +#endif /* ifndef _HWC2_TEST_PROPERTIES_H */ -- cgit v1.2.3-59-g8ed1b From ffc67daf8b834ff2206d221ce15809cd5f21be55 Mon Sep 17 00:00:00 2001 From: Marissa Wall Date: Thu, 15 Dec 2016 12:26:09 -0800 Subject: test-hwc2: set layer blend mode Test: Add "#define HAVE_NO_SURFACE_FLINGER" to frameworks/native/libs/gui/BufferQueueCore.cpp. Recompile and flash. Run "mm" in frameworks/native/services/surfaceflinger/tests/hwc2. Push test-hwc2 to device. Run "adb root && adb shell stop". Run test case. Ex: "./test-hwc2" Change-Id: Id5a7a568fb81ac9aff388d04077a12765cc135a3 --- services/surfaceflinger/tests/hwc2/Hwc2Test.cpp | 63 ++++++++++++++++++++++ .../surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp | 22 ++++++-- services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h | 7 +++ .../tests/hwc2/Hwc2TestProperties.cpp | 31 +++++++++-- .../surfaceflinger/tests/hwc2/Hwc2TestProperties.h | 47 +++++++++++++--- 5 files changed, 156 insertions(+), 14 deletions(-) diff --git a/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp index a50af49ed5..c24e6d74c2 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp +++ b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp @@ -357,6 +357,23 @@ public: } } + void setLayerBlendMode(hwc2_display_t display, hwc2_layer_t layer, + hwc2_blend_mode_t mode, hwc2_error_t* outErr = nullptr) + { + auto pfn = reinterpret_cast( + getFunction(HWC2_FUNCTION_SET_LAYER_BLEND_MODE)); + ASSERT_TRUE(pfn) << "failed to get function"; + + auto err = static_cast(pfn(mHwc2Device, display, layer, + mode)); + if (outErr) { + *outErr = err; + } else { + ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set layer blend mode " + << getBlendModeName(mode); + } + } + protected: hwc2_function_pointer_t getFunction(hwc2_function_descriptor_t descriptor) { @@ -683,6 +700,13 @@ void hwc2TestVsyncCallback(hwc2_callback_data_t callbackData, timestamp); } +void setBlendMode(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer, + const Hwc2TestLayer& testLayer, hwc2_error_t* outErr) +{ + EXPECT_NO_FATAL_FAILURE(test->setLayerBlendMode(display, layer, + testLayer.getBlendMode(), outErr)); +} + void setComposition(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer, const Hwc2TestLayer& testLayer, hwc2_error_t* outErr) { @@ -704,6 +728,11 @@ void setComposition(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer, } } +bool advanceBlendMode(Hwc2TestLayer* testLayer) +{ + return testLayer->advanceBlendMode(); +} + bool advanceComposition(Hwc2TestLayer* testLayer) { return testLayer->advanceComposition(); @@ -1556,3 +1585,37 @@ TEST_F(Hwc2Test, SET_LAYER_COMPOSITION_TYPE_bad_parameter) } )); } + +/* TESTCASE: Tests that the HWC2 can set a blend mode value of a layer. */ +TEST_F(Hwc2Test, SET_LAYER_BLEND_MODE) +{ + ASSERT_NO_FATAL_FAILURE(setLayerProperty(Hwc2TestCoverage::Complete, + setBlendMode, advanceBlendMode)); +} + +/* TESTCASE: Tests that the HWC2 can update a blend mode value of a layer. */ +TEST_F(Hwc2Test, SET_LAYER_BLEND_MODE_update) +{ + ASSERT_NO_FATAL_FAILURE(setLayerPropertyUpdate(Hwc2TestCoverage::Complete, + setBlendMode, advanceBlendMode)); +} + +/* TESTCASE: Tests that the HWC2 cannot set a blend mode for a bad layer. */ +TEST_F(Hwc2Test, SET_LAYER_BLEND_MODE_bad_layer) +{ + ASSERT_NO_FATAL_FAILURE(setLayerPropertyBadLayer(Hwc2TestCoverage::Default, + setBlendMode)); +} + +/* TESTCASE: Tests that the HWC2 cannot set an invalid blend mode. */ +TEST_F(Hwc2Test, SET_LAYER_BLEND_MODE_bad_parameter) +{ + ASSERT_NO_FATAL_FAILURE(setLayerPropertyBadParameter( + [] (Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer, + hwc2_error_t* outErr) { + + ASSERT_NO_FATAL_FAILURE(test->setLayerBlendMode(display, + layer, HWC2_BLEND_MODE_INVALID, outErr)); + } + )); +} diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp b/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp index 09fb9217b8..2ea61b809b 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp @@ -19,21 +19,32 @@ #include "Hwc2TestLayer.h" Hwc2TestLayer::Hwc2TestLayer(Hwc2TestCoverage coverage) - : mComposition(coverage) { } + : mBlendMode(coverage), + mComposition(coverage) { } std::string Hwc2TestLayer::dump() const { std::stringstream dmp; dmp << "layer: \n"; - dmp << mComposition.dump(); + + for (auto property : mProperties) { + dmp << property->dump(); + } return dmp.str(); } void Hwc2TestLayer::reset() { - mComposition.reset(); + for (auto property : mProperties) { + property->reset(); + } +} + +hwc2_blend_mode_t Hwc2TestLayer::getBlendMode() const +{ + return mBlendMode.get(); } hwc2_composition_t Hwc2TestLayer::getComposition() const @@ -41,6 +52,11 @@ hwc2_composition_t Hwc2TestLayer::getComposition() const return mComposition.get(); } +bool Hwc2TestLayer::advanceBlendMode() +{ + return mBlendMode.advance(); +} + bool Hwc2TestLayer::advanceComposition() { return mComposition.advance(); diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h b/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h index 9734ab8057..a4d6d1d24e 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h @@ -33,11 +33,18 @@ public: void reset(); + hwc2_blend_mode_t getBlendMode() const; hwc2_composition_t getComposition() const; + bool advanceBlendMode(); bool advanceComposition(); private: + std::array mProperties = {{ + &mBlendMode, &mComposition + }}; + + Hwc2TestBlendMode mBlendMode; Hwc2TestComposition mComposition; }; diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp index ef399fd6d4..ee0e8d4f2b 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp @@ -18,10 +18,35 @@ #include "Hwc2TestProperties.h" +Hwc2TestBlendMode::Hwc2TestBlendMode(Hwc2TestCoverage coverage) + : Hwc2TestProperty(coverage, mCompleteBlendModes, mBasicBlendModes, + mDefaultBlendModes) { } + +std::string Hwc2TestBlendMode::dump() const +{ + std::stringstream dmp; + dmp << "\tblend mode: " << getBlendModeName(get()) << "\n"; + return dmp.str(); +} + +const std::vector Hwc2TestBlendMode::mDefaultBlendModes = { + HWC2_BLEND_MODE_NONE, +}; + +const std::vector Hwc2TestBlendMode::mBasicBlendModes = { + HWC2_BLEND_MODE_NONE, + HWC2_BLEND_MODE_PREMULTIPLIED, +}; + +const std::vector Hwc2TestBlendMode::mCompleteBlendModes = { + HWC2_BLEND_MODE_NONE, + HWC2_BLEND_MODE_PREMULTIPLIED, + HWC2_BLEND_MODE_COVERAGE, +}; + + Hwc2TestComposition::Hwc2TestComposition(Hwc2TestCoverage coverage) - : Hwc2TestProperty( - (coverage == Hwc2TestCoverage::Complete)? mCompleteCompositions: - (coverage == Hwc2TestCoverage::Basic)? mBasicCompositions: + : Hwc2TestProperty(coverage, mCompleteCompositions, mBasicCompositions, mDefaultCompositions) { } std::string Hwc2TestComposition::dump() const diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h index 74f571e140..3375d86447 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h @@ -17,6 +17,7 @@ #ifndef _HWC2_TEST_PROPERTIES_H #define _HWC2_TEST_PROPERTIES_H +#include #include #define HWC2_INCLUDE_STRINGIFICATION @@ -32,20 +33,39 @@ enum class Hwc2TestCoverage { }; +class Hwc2TestContainer { +public: + virtual ~Hwc2TestContainer() = default; + + /* Resets the container */ + virtual void reset() = 0; + + /* Attempts to advance to the next valid value. Returns true if one can be + * found */ + virtual bool advance() = 0; + + virtual std::string dump() const = 0; +}; + + template -class Hwc2TestProperty { +class Hwc2TestProperty : public Hwc2TestContainer { public: + Hwc2TestProperty(Hwc2TestCoverage coverage, + const std::vector& completeList, const std::vector& basicList, + const std::vector& defaultList) + : Hwc2TestProperty((coverage == Hwc2TestCoverage::Complete)? completeList: + (coverage == Hwc2TestCoverage::Basic)? basicList : defaultList) { } + Hwc2TestProperty(const std::vector& list) : mList(list) { } - virtual ~Hwc2TestProperty() { }; - - virtual void reset() + void reset() override { mListIdx = 0; } - virtual bool advance() + bool advance() override { if (mListIdx + 1 < mList.size()) { mListIdx++; @@ -55,19 +75,30 @@ public: return false; } - virtual T get() const + T get() const { return mList.at(mListIdx); } - virtual std::string dump() const = 0; - protected: const std::vector& mList; size_t mListIdx = 0; }; +class Hwc2TestBlendMode : public Hwc2TestProperty { +public: + Hwc2TestBlendMode(Hwc2TestCoverage coverage); + + std::string dump() const override; + +protected: + static const std::vector mDefaultBlendModes; + static const std::vector mBasicBlendModes; + static const std::vector mCompleteBlendModes; +}; + + class Hwc2TestComposition : public Hwc2TestProperty { public: Hwc2TestComposition(Hwc2TestCoverage coverage); -- cgit v1.2.3-59-g8ed1b From b72b5c9ef4a6235c5bc2c4a3cceb23baf963815b Mon Sep 17 00:00:00 2001 From: Marissa Wall Date: Thu, 15 Dec 2016 12:26:39 -0800 Subject: test-hwc2: set layer dataspace Test: Add "#define HAVE_NO_SURFACE_FLINGER" to frameworks/native/libs/gui/BufferQueueCore.cpp. Recompile and flash. Run "mm" in frameworks/native/services/surfaceflinger/tests/hwc2. Push test-hwc2 to device. Run "adb root && adb shell stop". Run test case. Ex: "./test-hwc2" Change-Id: Ia5bc9e53815d519e2016f3db12d69c6cc70a9b26 --- services/surfaceflinger/tests/hwc2/Hwc2Test.cpp | 49 ++++++++++++++++ .../surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp | 13 ++++- services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h | 11 ++-- .../tests/hwc2/Hwc2TestProperties.cpp | 66 ++++++++++++++++++++++ .../surfaceflinger/tests/hwc2/Hwc2TestProperties.h | 13 +++++ 5 files changed, 147 insertions(+), 5 deletions(-) diff --git a/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp index c24e6d74c2..5d6baaa903 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp +++ b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp @@ -374,6 +374,22 @@ public: } } + void setLayerDataspace(hwc2_display_t display, hwc2_layer_t layer, + android_dataspace_t dataspace, hwc2_error_t* outErr = nullptr) + { + auto pfn = reinterpret_cast( + getFunction(HWC2_FUNCTION_SET_LAYER_DATASPACE)); + ASSERT_TRUE(pfn) << "failed to get function"; + + auto err = static_cast(pfn(mHwc2Device, display, + layer, dataspace)); + if (outErr) { + *outErr = err; + } else { + ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set layer dataspace"; + } + } + protected: hwc2_function_pointer_t getFunction(hwc2_function_descriptor_t descriptor) { @@ -728,6 +744,13 @@ void setComposition(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer, } } +void setDataspace(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer, + const Hwc2TestLayer& testLayer, hwc2_error_t* outErr) +{ + EXPECT_NO_FATAL_FAILURE(test->setLayerDataspace(display, layer, + testLayer.getDataspace(), outErr)); +} + bool advanceBlendMode(Hwc2TestLayer* testLayer) { return testLayer->advanceBlendMode(); @@ -738,6 +761,11 @@ bool advanceComposition(Hwc2TestLayer* testLayer) return testLayer->advanceComposition(); } +bool advanceDataspace(Hwc2TestLayer* testLayer) +{ + return testLayer->advanceDataspace(); +} + static const std::array requiredFunctions = {{ HWC2_FUNCTION_ACCEPT_DISPLAY_CHANGES, @@ -1619,3 +1647,24 @@ TEST_F(Hwc2Test, SET_LAYER_BLEND_MODE_bad_parameter) } )); } + +/* TESTCASE: Tests that the HWC2 can set the dataspace of a layer. */ +TEST_F(Hwc2Test, SET_LAYER_DATASPACE) +{ + ASSERT_NO_FATAL_FAILURE(setLayerProperty(Hwc2TestCoverage::Complete, + setDataspace, advanceDataspace)); +} + +/* TESTCASE: Tests that the HWC2 can update the dataspace of a layer. */ +TEST_F(Hwc2Test, SET_LAYER_DATASPACE_update) +{ + ASSERT_NO_FATAL_FAILURE(setLayerPropertyUpdate(Hwc2TestCoverage::Complete, + setDataspace, advanceDataspace)); +} + +/* TESTCASE: Tests that the HWC2 cannot set a dataspace for a bad layer. */ +TEST_F(Hwc2Test, SET_LAYER_DATASPACE_bad_layer) +{ + ASSERT_NO_FATAL_FAILURE(setLayerPropertyBadLayer(Hwc2TestCoverage::Default, + setDataspace)); +} diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp b/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp index 2ea61b809b..d99f2fd74a 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp @@ -20,7 +20,8 @@ Hwc2TestLayer::Hwc2TestLayer(Hwc2TestCoverage coverage) : mBlendMode(coverage), - mComposition(coverage) { } + mComposition(coverage), + mDataspace(coverage) { } std::string Hwc2TestLayer::dump() const { @@ -52,6 +53,11 @@ hwc2_composition_t Hwc2TestLayer::getComposition() const return mComposition.get(); } +android_dataspace_t Hwc2TestLayer::getDataspace() const +{ + return mDataspace.get(); +} + bool Hwc2TestLayer::advanceBlendMode() { return mBlendMode.advance(); @@ -61,3 +67,8 @@ bool Hwc2TestLayer::advanceComposition() { return mComposition.advance(); } + +bool Hwc2TestLayer::advanceDataspace() +{ + return mDataspace.advance(); +} diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h b/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h index a4d6d1d24e..b07fe7b99f 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h @@ -33,19 +33,22 @@ public: void reset(); - hwc2_blend_mode_t getBlendMode() const; - hwc2_composition_t getComposition() const; + hwc2_blend_mode_t getBlendMode() const; + hwc2_composition_t getComposition() const; + android_dataspace_t getDataspace() const; bool advanceBlendMode(); bool advanceComposition(); + bool advanceDataspace(); private: - std::array mProperties = {{ - &mBlendMode, &mComposition + std::array mProperties = {{ + &mBlendMode, &mComposition, &mDataspace }}; Hwc2TestBlendMode mBlendMode; Hwc2TestComposition mComposition; + Hwc2TestDataspace mDataspace; }; #endif /* ifndef _HWC2_TEST_LAYER_H */ diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp index ee0e8d4f2b..2075d63cc9 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp @@ -72,3 +72,69 @@ const std::vector Hwc2TestComposition::mCompleteCompositions HWC2_COMPOSITION_CURSOR, HWC2_COMPOSITION_SIDEBAND, }; + + +Hwc2TestDataspace::Hwc2TestDataspace(Hwc2TestCoverage coverage) + : Hwc2TestProperty(coverage, completeDataspaces, basicDataspaces, + defaultDataspaces) { } + +std::string Hwc2TestDataspace::dump() const +{ + std::stringstream dmp; + dmp << "\tdataspace: " << get() << "\n"; + return dmp.str(); +} + +const std::vector Hwc2TestDataspace::defaultDataspaces = { + HAL_DATASPACE_UNKNOWN, +}; + +const std::vector Hwc2TestDataspace::basicDataspaces = { + HAL_DATASPACE_UNKNOWN, + HAL_DATASPACE_V0_SRGB, +}; + +const std::vector Hwc2TestDataspace::completeDataspaces = { + HAL_DATASPACE_UNKNOWN, + HAL_DATASPACE_ARBITRARY, + HAL_DATASPACE_STANDARD_SHIFT, + HAL_DATASPACE_STANDARD_MASK, + HAL_DATASPACE_STANDARD_UNSPECIFIED, + HAL_DATASPACE_STANDARD_BT709, + HAL_DATASPACE_STANDARD_BT601_625, + HAL_DATASPACE_STANDARD_BT601_625_UNADJUSTED, + HAL_DATASPACE_STANDARD_BT601_525, + HAL_DATASPACE_STANDARD_BT601_525_UNADJUSTED, + HAL_DATASPACE_STANDARD_BT2020, + HAL_DATASPACE_STANDARD_BT2020_CONSTANT_LUMINANCE, + HAL_DATASPACE_STANDARD_BT470M, + HAL_DATASPACE_STANDARD_FILM, + HAL_DATASPACE_TRANSFER_SHIFT, + HAL_DATASPACE_TRANSFER_MASK, + HAL_DATASPACE_TRANSFER_UNSPECIFIED, + HAL_DATASPACE_TRANSFER_LINEAR, + HAL_DATASPACE_TRANSFER_SRGB, + HAL_DATASPACE_TRANSFER_SMPTE_170M, + HAL_DATASPACE_TRANSFER_GAMMA2_2, + HAL_DATASPACE_TRANSFER_GAMMA2_8, + HAL_DATASPACE_TRANSFER_ST2084, + HAL_DATASPACE_TRANSFER_HLG, + HAL_DATASPACE_RANGE_SHIFT, + HAL_DATASPACE_RANGE_MASK, + HAL_DATASPACE_RANGE_UNSPECIFIED, + HAL_DATASPACE_RANGE_FULL, + HAL_DATASPACE_RANGE_LIMITED, + HAL_DATASPACE_SRGB_LINEAR, + HAL_DATASPACE_V0_SRGB_LINEAR, + HAL_DATASPACE_SRGB, + HAL_DATASPACE_V0_SRGB, + HAL_DATASPACE_JFIF, + HAL_DATASPACE_V0_JFIF, + HAL_DATASPACE_BT601_625, + HAL_DATASPACE_V0_BT601_625, + HAL_DATASPACE_BT601_525, + HAL_DATASPACE_V0_BT601_525, + HAL_DATASPACE_BT709, + HAL_DATASPACE_V0_BT709, + HAL_DATASPACE_DEPTH, +}; diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h index 3375d86447..236843ef78 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h @@ -111,4 +111,17 @@ protected: static const std::vector mCompleteCompositions; }; + +class Hwc2TestDataspace : public Hwc2TestProperty { +public: + Hwc2TestDataspace(Hwc2TestCoverage coverage); + + std::string dump() const override; + +protected: + static const std::vector defaultDataspaces; + static const std::vector basicDataspaces; + static const std::vector completeDataspaces; +}; + #endif /* ifndef _HWC2_TEST_PROPERTIES_H */ -- cgit v1.2.3-59-g8ed1b From 2b1f53060ea8587a428f826cf7890354ff124722 Mon Sep 17 00:00:00 2001 From: Marissa Wall Date: Thu, 15 Dec 2016 12:27:20 -0800 Subject: test-hwc2: set layer plane alpha Test: Add "#define HAVE_NO_SURFACE_FLINGER" to frameworks/native/libs/gui/BufferQueueCore.cpp. Recompile and flash. Run "mm" in frameworks/native/services/surfaceflinger/tests/hwc2. Push test-hwc2 to device. Run "adb root && adb shell stop". Run test case. Ex: "./test-hwc2" Change-Id: I48146953f745dc650ead5a6e9d6f456cf5a9d7ef --- services/surfaceflinger/tests/hwc2/Hwc2Test.cpp | 58 ++++++++++++++++++++++ .../surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp | 13 ++++- services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h | 7 ++- .../tests/hwc2/Hwc2TestProperties.cpp | 24 +++++++++ .../surfaceflinger/tests/hwc2/Hwc2TestProperties.h | 13 +++++ 5 files changed, 112 insertions(+), 3 deletions(-) diff --git a/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp index 5d6baaa903..407841136d 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp +++ b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp @@ -390,6 +390,23 @@ public: } } + void setLayerPlaneAlpha(hwc2_display_t display, hwc2_layer_t layer, + float alpha, hwc2_error_t* outErr = nullptr) + { + auto pfn = reinterpret_cast( + getFunction(HWC2_FUNCTION_SET_LAYER_PLANE_ALPHA)); + ASSERT_TRUE(pfn) << "failed to get function"; + + auto err = static_cast(pfn(mHwc2Device, display, layer, + alpha)); + if (outErr) { + *outErr = err; + } else { + ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set layer plane alpha " + << alpha; + } + } + protected: hwc2_function_pointer_t getFunction(hwc2_function_descriptor_t descriptor) { @@ -751,6 +768,15 @@ void setDataspace(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer, testLayer.getDataspace(), outErr)); } +void setPlaneAlpha(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer, + const Hwc2TestLayer& testLayer, hwc2_error_t *outErr) +{ + ASSERT_NO_FATAL_FAILURE(test->setLayerBlendMode(display, layer, + testLayer.getBlendMode())); + EXPECT_NO_FATAL_FAILURE(test->setLayerPlaneAlpha(display, layer, + testLayer.getPlaneAlpha(), outErr)); +} + bool advanceBlendMode(Hwc2TestLayer* testLayer) { return testLayer->advanceBlendMode(); @@ -766,6 +792,11 @@ bool advanceDataspace(Hwc2TestLayer* testLayer) return testLayer->advanceDataspace(); } +bool advancePlaneAlpha(Hwc2TestLayer* testLayer) +{ + return testLayer->advancePlaneAlpha(); +} + static const std::array requiredFunctions = {{ HWC2_FUNCTION_ACCEPT_DISPLAY_CHANGES, @@ -1668,3 +1699,30 @@ TEST_F(Hwc2Test, SET_LAYER_DATASPACE_bad_layer) ASSERT_NO_FATAL_FAILURE(setLayerPropertyBadLayer(Hwc2TestCoverage::Default, setDataspace)); } + +/* TESTCASE: Tests that the HWC2 can set the plane alpha of a layer. */ +TEST_F(Hwc2Test, SET_LAYER_PLANE_ALPHA) +{ + ASSERT_NO_FATAL_FAILURE(setLayerProperty(Hwc2TestCoverage::Complete, + setPlaneAlpha, advancePlaneAlpha)); +} + +/* TESTCASE: Tests that the HWC2 can update the plane alpha of a layer. */ +TEST_F(Hwc2Test, SET_LAYER_PLANE_ALPHA_update) +{ + ASSERT_NO_FATAL_FAILURE(setLayerPropertyUpdate(Hwc2TestCoverage::Complete, + setPlaneAlpha, advancePlaneAlpha)); +} + +/* TESTCASE: Tests that the HWC2 cannot set a plane alpha for a bad layer. */ +TEST_F(Hwc2Test, SET_LAYER_PLANE_ALPHA_bad_layer) +{ + ASSERT_NO_FATAL_FAILURE(setLayerPropertyBadLayer(Hwc2TestCoverage::Default, + [] (Hwc2Test* test, hwc2_display_t display, hwc2_layer_t badLayer, + const Hwc2TestLayer& testLayer, hwc2_error_t *outErr) { + + EXPECT_NO_FATAL_FAILURE(test->setLayerPlaneAlpha(display, + badLayer, testLayer.getPlaneAlpha(), outErr)); + } + )); +} diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp b/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp index d99f2fd74a..647f0ff0e2 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp @@ -21,7 +21,8 @@ Hwc2TestLayer::Hwc2TestLayer(Hwc2TestCoverage coverage) : mBlendMode(coverage), mComposition(coverage), - mDataspace(coverage) { } + mDataspace(coverage), + mPlaneAlpha(coverage) { } std::string Hwc2TestLayer::dump() const { @@ -58,6 +59,11 @@ android_dataspace_t Hwc2TestLayer::getDataspace() const return mDataspace.get(); } +float Hwc2TestLayer::getPlaneAlpha() const +{ + return mPlaneAlpha.get(); +} + bool Hwc2TestLayer::advanceBlendMode() { return mBlendMode.advance(); @@ -72,3 +78,8 @@ bool Hwc2TestLayer::advanceDataspace() { return mDataspace.advance(); } + +bool Hwc2TestLayer::advancePlaneAlpha() +{ + return mPlaneAlpha.advance(); +} diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h b/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h index b07fe7b99f..5ba2cfc8af 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h @@ -36,19 +36,22 @@ public: hwc2_blend_mode_t getBlendMode() const; hwc2_composition_t getComposition() const; android_dataspace_t getDataspace() const; + float getPlaneAlpha() const; bool advanceBlendMode(); bool advanceComposition(); bool advanceDataspace(); + bool advancePlaneAlpha(); private: - std::array mProperties = {{ - &mBlendMode, &mComposition, &mDataspace + std::array mProperties = {{ + &mBlendMode, &mComposition, &mDataspace, &mPlaneAlpha }}; Hwc2TestBlendMode mBlendMode; Hwc2TestComposition mComposition; Hwc2TestDataspace mDataspace; + Hwc2TestPlaneAlpha mPlaneAlpha; }; #endif /* ifndef _HWC2_TEST_LAYER_H */ diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp index 2075d63cc9..8477949f99 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp @@ -138,3 +138,27 @@ const std::vector Hwc2TestDataspace::completeDataspaces = { HAL_DATASPACE_V0_BT709, HAL_DATASPACE_DEPTH, }; + + +Hwc2TestPlaneAlpha::Hwc2TestPlaneAlpha(Hwc2TestCoverage coverage) + : Hwc2TestProperty(coverage, mCompletePlaneAlphas, mBasicPlaneAlphas, + mDefaultPlaneAlphas) { } + +std::string Hwc2TestPlaneAlpha::dump() const +{ + std::stringstream dmp; + dmp << "\tplane alpha: " << get() << "\n"; + return dmp.str(); +} + +const std::vector Hwc2TestPlaneAlpha::mDefaultPlaneAlphas = { + 1.0f, +}; + +const std::vector Hwc2TestPlaneAlpha::mBasicPlaneAlphas = { + 1.0f, 0.0f, +}; + +const std::vector Hwc2TestPlaneAlpha::mCompletePlaneAlphas = { + 1.0f, 0.75f, 0.5f, 0.25f, 0.0f, +}; diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h index 236843ef78..f54c8c814e 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h @@ -124,4 +124,17 @@ protected: static const std::vector completeDataspaces; }; + +class Hwc2TestPlaneAlpha : public Hwc2TestProperty { +public: + Hwc2TestPlaneAlpha(Hwc2TestCoverage coverage); + + std::string dump() const override; + +protected: + static const std::vector mDefaultPlaneAlphas; + static const std::vector mBasicPlaneAlphas; + static const std::vector mCompletePlaneAlphas; +}; + #endif /* ifndef _HWC2_TEST_PROPERTIES_H */ -- cgit v1.2.3-59-g8ed1b From ac10819373b1ed4901f26c822484a789a7ca4be0 Mon Sep 17 00:00:00 2001 From: Marissa Wall Date: Thu, 15 Dec 2016 12:27:48 -0800 Subject: test-hwc2: set layer transform Test: Add "#define HAVE_NO_SURFACE_FLINGER" to frameworks/native/libs/gui/BufferQueueCore.cpp. Recompile and flash. Run "mm" in frameworks/native/services/surfaceflinger/tests/hwc2. Push test-hwc2 to device. Run "adb root && adb shell stop". Run test case. Ex: "./test-hwc2" Change-Id: I55e318cbddf957d1728435488c6283f8ce77a3d6 --- services/surfaceflinger/tests/hwc2/Hwc2Test.cpp | 50 ++++++++++++++++++++++ .../surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp | 13 +++++- services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h | 7 ++- .../tests/hwc2/Hwc2TestProperties.cpp | 34 +++++++++++++++ .../surfaceflinger/tests/hwc2/Hwc2TestProperties.h | 13 ++++++ 5 files changed, 114 insertions(+), 3 deletions(-) diff --git a/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp index 407841136d..dbce9d5d04 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp +++ b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp @@ -407,6 +407,23 @@ public: } } + void setLayerTransform(hwc2_display_t display, hwc2_layer_t layer, + hwc_transform_t transform, hwc2_error_t* outErr = nullptr) + { + auto pfn = reinterpret_cast( + getFunction(HWC2_FUNCTION_SET_LAYER_TRANSFORM)); + ASSERT_TRUE(pfn) << "failed to get function"; + + auto err = static_cast(pfn(mHwc2Device, display, layer, + transform)); + if (outErr) { + *outErr = err; + } else { + ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set layer transform " + << getTransformName(transform); + } + } + protected: hwc2_function_pointer_t getFunction(hwc2_function_descriptor_t descriptor) { @@ -777,6 +794,13 @@ void setPlaneAlpha(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer, testLayer.getPlaneAlpha(), outErr)); } +void setTransform(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer, + const Hwc2TestLayer& testLayer, hwc2_error_t* outErr) +{ + EXPECT_NO_FATAL_FAILURE(test->setLayerTransform(display, layer, + testLayer.getTransform(), outErr)); +} + bool advanceBlendMode(Hwc2TestLayer* testLayer) { return testLayer->advanceBlendMode(); @@ -797,6 +821,11 @@ bool advancePlaneAlpha(Hwc2TestLayer* testLayer) return testLayer->advancePlaneAlpha(); } +bool advanceTransform(Hwc2TestLayer* testLayer) +{ + return testLayer->advanceTransform(); +} + static const std::array requiredFunctions = {{ HWC2_FUNCTION_ACCEPT_DISPLAY_CHANGES, @@ -1726,3 +1755,24 @@ TEST_F(Hwc2Test, SET_LAYER_PLANE_ALPHA_bad_layer) } )); } + +/* TESTCASE: Tests that the HWC2 can set the transform value of a layer. */ +TEST_F(Hwc2Test, SET_LAYER_TRANSFORM) +{ + ASSERT_NO_FATAL_FAILURE(setLayerProperty(Hwc2TestCoverage::Complete, + setTransform, advanceTransform)); +} + +/* TESTCASE: Tests that the HWC2 can update the transform value of a layer. */ +TEST_F(Hwc2Test, SET_LAYER_TRANSFORM_update) +{ + ASSERT_NO_FATAL_FAILURE(setLayerPropertyUpdate(Hwc2TestCoverage::Complete, + setTransform, advanceTransform)); +} + +/* TESTCASE: Tests that the HWC2 cannot set the transform for a bad layer. */ +TEST_F(Hwc2Test, SET_LAYER_TRANSFORM_bad_layer) +{ + ASSERT_NO_FATAL_FAILURE(setLayerPropertyBadLayer(Hwc2TestCoverage::Default, + setTransform)); +} diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp b/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp index 647f0ff0e2..5445a770c0 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp @@ -22,7 +22,8 @@ Hwc2TestLayer::Hwc2TestLayer(Hwc2TestCoverage coverage) : mBlendMode(coverage), mComposition(coverage), mDataspace(coverage), - mPlaneAlpha(coverage) { } + mPlaneAlpha(coverage), + mTransform(coverage) { } std::string Hwc2TestLayer::dump() const { @@ -64,6 +65,11 @@ float Hwc2TestLayer::getPlaneAlpha() const return mPlaneAlpha.get(); } +hwc_transform_t Hwc2TestLayer::getTransform() const +{ + return mTransform.get(); +} + bool Hwc2TestLayer::advanceBlendMode() { return mBlendMode.advance(); @@ -83,3 +89,8 @@ bool Hwc2TestLayer::advancePlaneAlpha() { return mPlaneAlpha.advance(); } + +bool Hwc2TestLayer::advanceTransform() +{ + return mTransform.advance(); +} diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h b/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h index 5ba2cfc8af..d259ad9b9b 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h @@ -37,21 +37,24 @@ public: hwc2_composition_t getComposition() const; android_dataspace_t getDataspace() const; float getPlaneAlpha() const; + hwc_transform_t getTransform() const; bool advanceBlendMode(); bool advanceComposition(); bool advanceDataspace(); bool advancePlaneAlpha(); + bool advanceTransform(); private: - std::array mProperties = {{ - &mBlendMode, &mComposition, &mDataspace, &mPlaneAlpha + std::array mProperties = {{ + &mBlendMode, &mComposition, &mDataspace, &mPlaneAlpha, &mTransform }}; Hwc2TestBlendMode mBlendMode; Hwc2TestComposition mComposition; Hwc2TestDataspace mDataspace; Hwc2TestPlaneAlpha mPlaneAlpha; + Hwc2TestTransform mTransform; }; #endif /* ifndef _HWC2_TEST_LAYER_H */ diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp index 8477949f99..eb49d3272e 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp @@ -162,3 +162,37 @@ const std::vector Hwc2TestPlaneAlpha::mBasicPlaneAlphas = { const std::vector Hwc2TestPlaneAlpha::mCompletePlaneAlphas = { 1.0f, 0.75f, 0.5f, 0.25f, 0.0f, }; + + +Hwc2TestTransform::Hwc2TestTransform(Hwc2TestCoverage coverage) + : Hwc2TestProperty(coverage, mCompleteTransforms, mBasicTransforms, + mDefaultTransforms) { } + +std::string Hwc2TestTransform::dump() const +{ + std::stringstream dmp; + dmp << "\ttransform: " << getTransformName(get()) << "\n"; + return dmp.str(); +} + +const std::vector Hwc2TestTransform::mDefaultTransforms = { + static_cast(0), +}; + +const std::vector Hwc2TestTransform::mBasicTransforms = { + static_cast(0), + HWC_TRANSFORM_FLIP_H, + HWC_TRANSFORM_FLIP_V, + HWC_TRANSFORM_ROT_90, +}; + +const std::vector Hwc2TestTransform::mCompleteTransforms = { + static_cast(0), + HWC_TRANSFORM_FLIP_H, + HWC_TRANSFORM_FLIP_V, + HWC_TRANSFORM_ROT_90, + HWC_TRANSFORM_ROT_180, + HWC_TRANSFORM_ROT_270, + HWC_TRANSFORM_FLIP_H_ROT_90, + HWC_TRANSFORM_FLIP_V_ROT_90, +}; diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h index f54c8c814e..a96b629a3d 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h @@ -137,4 +137,17 @@ protected: static const std::vector mCompletePlaneAlphas; }; + +class Hwc2TestTransform : public Hwc2TestProperty { +public: + Hwc2TestTransform(Hwc2TestCoverage coverage); + + std::string dump() const override; + +protected: + static const std::vector mDefaultTransforms; + static const std::vector mBasicTransforms; + static const std::vector mCompleteTransforms; +}; + #endif /* ifndef _HWC2_TEST_PROPERTIES_H */ -- cgit v1.2.3-59-g8ed1b From 273b1dfa05287a0016ae1fc230cd3a5b1b7433fa Mon Sep 17 00:00:00 2001 From: Marissa Wall Date: Thu, 15 Dec 2016 12:28:47 -0800 Subject: test-hwc2: set layer z order Test: Add "#define HAVE_NO_SURFACE_FLINGER" to frameworks/native/libs/gui/BufferQueueCore.cpp. Recompile and flash. Run "mm" in frameworks/native/services/surfaceflinger/tests/hwc2. Push test-hwc2 to device. Run "adb root && adb shell stop". Run test case. Ex: "./test-hwc2" Change-Id: I2c51df36d62f9d809583003b81c24dbd7a744301 --- services/surfaceflinger/tests/hwc2/Android.mk | 3 +- services/surfaceflinger/tests/hwc2/Hwc2Test.cpp | 110 +++++++++++++++++++++ .../surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp | 12 ++- services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h | 5 +- .../surfaceflinger/tests/hwc2/Hwc2TestLayers.cpp | 55 +++++++++++ .../surfaceflinger/tests/hwc2/Hwc2TestLayers.h | 46 +++++++++ 6 files changed, 227 insertions(+), 4 deletions(-) create mode 100644 services/surfaceflinger/tests/hwc2/Hwc2TestLayers.cpp create mode 100644 services/surfaceflinger/tests/hwc2/Hwc2TestLayers.h diff --git a/services/surfaceflinger/tests/hwc2/Android.mk b/services/surfaceflinger/tests/hwc2/Android.mk index 66a390df2f..08103fc981 100644 --- a/services/surfaceflinger/tests/hwc2/Android.mk +++ b/services/surfaceflinger/tests/hwc2/Android.mk @@ -30,6 +30,7 @@ LOCAL_STATIC_LIBRARIES := libbase libadf libadfhwc LOCAL_SRC_FILES := \ Hwc2Test.cpp \ Hwc2TestProperties.cpp \ - Hwc2TestLayer.cpp + Hwc2TestLayer.cpp \ + Hwc2TestLayers.cpp include $(BUILD_NATIVE_TEST) diff --git a/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp index dbce9d5d04..041f5d7f6d 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp +++ b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp @@ -27,6 +27,7 @@ #undef HWC2_USE_CPP11 #include "Hwc2TestLayer.h" +#include "Hwc2TestLayers.h" void hwc2TestHotplugCallback(hwc2_callback_data_t callbackData, hwc2_display_t display, int32_t connected); @@ -424,6 +425,23 @@ public: } } + void setLayerZOrder(hwc2_display_t display, hwc2_layer_t layer, + uint32_t zOrder, hwc2_error_t* outErr = nullptr) + { + auto pfn = reinterpret_cast( + getFunction(HWC2_FUNCTION_SET_LAYER_Z_ORDER)); + ASSERT_TRUE(pfn) << "failed to get function"; + + auto err = static_cast(pfn(mHwc2Device, display, layer, + zOrder)); + if (outErr) { + *outErr = err; + } else { + ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set layer z order " + << zOrder; + } + } + protected: hwc2_function_pointer_t getFunction(hwc2_function_descriptor_t descriptor) { @@ -567,6 +585,12 @@ protected: hwc2_display_t display, hwc2_layer_t layer, const Hwc2TestLayer& testLayer, hwc2_error_t* outErr); + /* Calls a set property function from Hwc2Test to set property values from + * Hwc2TestLayers to hwc2_layer_t on hwc2_display_t */ + using TestLayerPropertiesFunction = void (*)(Hwc2Test* test, + hwc2_display_t display, hwc2_layer_t layer, + const Hwc2TestLayers& testLayers); + /* Calls a set property function from Hwc2Test to set a bad property value * on hwc2_layer_t on hwc2_display_t */ using TestLayerPropertyBadLayerFunction = void (*)(Hwc2Test* test, @@ -639,6 +663,36 @@ protected: } } + /* For each active display it cycles through each display config and tests + * each property value. It creates multiple layers, calls the + * TestLayerPropertiesFunction to set property values and then + * destroys the layers */ + void setLayerProperties(Hwc2TestCoverage coverage, size_t layerCnt, + TestLayerPropertiesFunction function) + { + for (auto display : mDisplays) { + std::vector configs; + + ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs)); + + for (auto config : configs) { + std::vector layers; + + ASSERT_NO_FATAL_FAILURE(setActiveConfig(display, config)); + + ASSERT_NO_FATAL_FAILURE(createLayers(display, &layers, layerCnt)); + Hwc2TestLayers testLayers(layers, coverage); + + for (auto layer : layers) { + EXPECT_NO_FATAL_FAILURE(function(this, display, layer, + testLayers)); + } + + ASSERT_NO_FATAL_FAILURE(destroyLayers(display, std::move(layers))); + } + } + } + /* For each active display it cycles through each display config. * 1) It attempts to set a valid property value to bad layer handle. * 2) It creates a layer x and attempts to set a valid property value to @@ -801,6 +855,13 @@ void setTransform(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer, testLayer.getTransform(), outErr)); } +void setZOrder(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer, + const Hwc2TestLayer& testLayer, hwc2_error_t* outErr) +{ + EXPECT_NO_FATAL_FAILURE(test->setLayerZOrder(display, layer, + testLayer.getZOrder(), outErr)); +} + bool advanceBlendMode(Hwc2TestLayer* testLayer) { return testLayer->advanceBlendMode(); @@ -1776,3 +1837,52 @@ TEST_F(Hwc2Test, SET_LAYER_TRANSFORM_bad_layer) ASSERT_NO_FATAL_FAILURE(setLayerPropertyBadLayer(Hwc2TestCoverage::Default, setTransform)); } + +/* TESTCASE: Tests that the HWC2 can set the z order of a layer. */ +TEST_F(Hwc2Test, SET_LAYER_Z_ORDER) +{ + ASSERT_NO_FATAL_FAILURE(setLayerProperties(Hwc2TestCoverage::Complete, 10, + [] (Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer, + const Hwc2TestLayers& testLayers) { + + EXPECT_NO_FATAL_FAILURE(test->setLayerZOrder(display, layer, + testLayers.getZOrder(layer))); + } + )); +} + +/* TESTCASE: Tests that the HWC2 can update the z order of a layer. */ +TEST_F(Hwc2Test, SET_LAYER_Z_ORDER_update) +{ + const std::vector zOrders = { static_cast(0), + static_cast(1), static_cast(UINT32_MAX / 4), + static_cast(UINT32_MAX / 2), + static_cast(UINT32_MAX) }; + + for (auto display : mDisplays) { + std::vector configs; + + ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs)); + + for (auto config : configs) { + hwc2_layer_t layer; + + ASSERT_NO_FATAL_FAILURE(setActiveConfig(display, config)); + + ASSERT_NO_FATAL_FAILURE(createLayer(display, &layer)); + + for (uint32_t zOrder : zOrders) { + EXPECT_NO_FATAL_FAILURE(setLayerZOrder(display, layer, zOrder)); + } + + ASSERT_NO_FATAL_FAILURE(destroyLayer(display, layer)); + } + } +} + +/* TESTCASE: Tests that the HWC2 cannot set the z order of a bad layer. */ +TEST_F(Hwc2Test, SET_LAYER_Z_ORDER_bad_layer) +{ + ASSERT_NO_FATAL_FAILURE(setLayerPropertyBadLayer(Hwc2TestCoverage::Default, + setZOrder)); +} diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp b/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp index 5445a770c0..b9ca9c3b03 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp @@ -18,12 +18,13 @@ #include "Hwc2TestLayer.h" -Hwc2TestLayer::Hwc2TestLayer(Hwc2TestCoverage coverage) +Hwc2TestLayer::Hwc2TestLayer(Hwc2TestCoverage coverage, uint32_t zOrder) : mBlendMode(coverage), mComposition(coverage), mDataspace(coverage), mPlaneAlpha(coverage), - mTransform(coverage) { } + mTransform(coverage), + mZOrder(zOrder) { } std::string Hwc2TestLayer::dump() const { @@ -35,6 +36,8 @@ std::string Hwc2TestLayer::dump() const dmp << property->dump(); } + dmp << "\tz order: " << mZOrder << "\n"; + return dmp.str(); } @@ -70,6 +73,11 @@ hwc_transform_t Hwc2TestLayer::getTransform() const return mTransform.get(); } +uint32_t Hwc2TestLayer::getZOrder() const +{ + return mZOrder; +} + bool Hwc2TestLayer::advanceBlendMode() { return mBlendMode.advance(); diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h b/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h index d259ad9b9b..855f7bbbd8 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h @@ -27,7 +27,7 @@ class Hwc2TestLayer { public: - Hwc2TestLayer(Hwc2TestCoverage coverage); + Hwc2TestLayer(Hwc2TestCoverage coverage, uint32_t zOrder = 0); std::string dump() const; @@ -38,6 +38,7 @@ public: android_dataspace_t getDataspace() const; float getPlaneAlpha() const; hwc_transform_t getTransform() const; + uint32_t getZOrder() const; bool advanceBlendMode(); bool advanceComposition(); @@ -55,6 +56,8 @@ private: Hwc2TestDataspace mDataspace; Hwc2TestPlaneAlpha mPlaneAlpha; Hwc2TestTransform mTransform; + + uint32_t mZOrder; }; #endif /* ifndef _HWC2_TEST_LAYER_H */ diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.cpp b/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.cpp new file mode 100644 index 0000000000..b2318b1d70 --- /dev/null +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.cpp @@ -0,0 +1,55 @@ +/* * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include "Hwc2TestLayers.h" + +Hwc2TestLayers::Hwc2TestLayers(const std::vector& layers, + Hwc2TestCoverage coverage) +{ + uint32_t nextZOrder = 0; + + for (auto layer : layers) { + mTestLayers.emplace(std::piecewise_construct, + std::forward_as_tuple(layer), + std::forward_as_tuple(coverage, nextZOrder++)); + } +} + +std::string Hwc2TestLayers::dump() const +{ + std::stringstream dmp; + for (auto& testLayer : mTestLayers) { + dmp << testLayer.second.dump(); + } + return dmp.str(); +} + +void Hwc2TestLayers::reset() +{ + for (auto& testLayer : mTestLayers) { + testLayer.second.reset(); + } +} + +uint32_t Hwc2TestLayers::getZOrder(hwc2_layer_t layer) const +{ + if (mTestLayers.count(layer) == 0) { + []() { GTEST_FAIL(); }(); + } + return mTestLayers.at(layer).getZOrder(); +} diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.h b/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.h new file mode 100644 index 0000000000..fcc903a19e --- /dev/null +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _HWC2_TEST_LAYERS_H +#define _HWC2_TEST_LAYERS_H + +#include + +#define HWC2_INCLUDE_STRINGIFICATION +#define HWC2_USE_CPP11 +#include +#undef HWC2_INCLUDE_STRINGIFICATION +#undef HWC2_USE_CPP11 + +#include "Hwc2TestProperties.h" +#include "Hwc2TestLayer.h" + +class Hwc2TestLayers { +public: + Hwc2TestLayers(const std::vector& layers, + Hwc2TestCoverage coverage); + + std::string dump() const; + + void reset(); + + uint32_t getZOrder(hwc2_layer_t layer) const; + +private: + std::map mTestLayers; +}; + +#endif /* ifndef _HWC2_TEST_LAYERS_H */ -- cgit v1.2.3-59-g8ed1b From 600a73b6110d6fdcebe072a9d8e2dbbe6de1c6b7 Mon Sep 17 00:00:00 2001 From: Marissa Wall Date: Thu, 15 Dec 2016 12:30:39 -0800 Subject: test-hwc2: set layer display frame Test: Add "#define HAVE_NO_SURFACE_FLINGER" to frameworks/native/libs/gui/BufferQueueCore.cpp. Recompile and flash. Run "mm" in frameworks/native/services/surfaceflinger/tests/hwc2. Push test-hwc2 to device. Run "adb root && adb shell stop". Run test case. Ex: "./test-hwc2" Change-Id: I4431ad0d207924b9fcde2c4c2f34382ec8ddc4d8 --- services/surfaceflinger/tests/hwc2/Hwc2Test.cpp | 89 +++++++++++++++++++++- .../surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp | 14 +++- services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h | 11 ++- .../surfaceflinger/tests/hwc2/Hwc2TestLayers.cpp | 4 +- .../surfaceflinger/tests/hwc2/Hwc2TestLayers.h | 2 +- .../tests/hwc2/Hwc2TestProperties.cpp | 60 +++++++++++++++ .../surfaceflinger/tests/hwc2/Hwc2TestProperties.h | 25 ++++++ 7 files changed, 194 insertions(+), 11 deletions(-) diff --git a/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp index 041f5d7f6d..c092f222be 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp +++ b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp @@ -391,6 +391,23 @@ public: } } + void setLayerDisplayFrame(hwc2_display_t display, hwc2_layer_t layer, + const hwc_rect_t& displayFrame, hwc2_error_t* outErr = nullptr) + { + auto pfn = reinterpret_cast( + getFunction(HWC2_FUNCTION_SET_LAYER_DISPLAY_FRAME)); + ASSERT_TRUE(pfn) << "failed to get function"; + + auto err = static_cast(pfn(mHwc2Device, display, layer, + displayFrame)); + if (outErr) { + *outErr = err; + } else { + ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set layer display" + " frame"; + } + } + void setLayerPlaneAlpha(hwc2_display_t display, hwc2_layer_t layer, float alpha, hwc2_error_t* outErr = nullptr) { @@ -618,9 +635,12 @@ protected: for (auto config : configs) { hwc2_layer_t layer; + Area displayArea; ASSERT_NO_FATAL_FAILURE(setActiveConfig(display, config)); - Hwc2TestLayer testLayer(coverage); + ASSERT_NO_FATAL_FAILURE(getActiveDisplayArea(display, + &displayArea)); + Hwc2TestLayer testLayer(coverage, displayArea); do { ASSERT_NO_FATAL_FAILURE(createLayer(display, &layer)); @@ -647,9 +667,12 @@ protected: for (auto config : configs) { hwc2_layer_t layer; + Area displayArea; ASSERT_NO_FATAL_FAILURE(setActiveConfig(display, config)); - Hwc2TestLayer testLayer(coverage); + ASSERT_NO_FATAL_FAILURE(getActiveDisplayArea(display, + &displayArea)); + Hwc2TestLayer testLayer(coverage, displayArea); ASSERT_NO_FATAL_FAILURE(createLayer(display, &layer)); @@ -677,11 +700,14 @@ protected: for (auto config : configs) { std::vector layers; + Area displayArea; ASSERT_NO_FATAL_FAILURE(setActiveConfig(display, config)); + ASSERT_NO_FATAL_FAILURE(getActiveDisplayArea(display, + &displayArea)); ASSERT_NO_FATAL_FAILURE(createLayers(display, &layers, layerCnt)); - Hwc2TestLayers testLayers(layers, coverage); + Hwc2TestLayers testLayers(layers, coverage, displayArea); for (auto layer : layers) { EXPECT_NO_FATAL_FAILURE(function(this, display, layer, @@ -710,10 +736,13 @@ protected: for (auto config : configs) { hwc2_layer_t layer = 0; + Area displayArea; hwc2_error_t err = HWC2_ERROR_NONE; ASSERT_NO_FATAL_FAILURE(setActiveConfig(display, config)); - Hwc2TestLayer testLayer(coverage); + ASSERT_NO_FATAL_FAILURE(getActiveDisplayArea(display, + &displayArea)); + Hwc2TestLayer testLayer(coverage, displayArea); ASSERT_NO_FATAL_FAILURE(function(this, display, layer, testLayer, &err)); @@ -761,6 +790,25 @@ protected: } } + void getActiveConfigAttribute(hwc2_display_t display, + hwc2_attribute_t attribute, int32_t* outValue) + { + hwc2_config_t config; + ASSERT_NO_FATAL_FAILURE(getActiveConfig(display, &config)); + ASSERT_NO_FATAL_FAILURE(getDisplayAttribute(display, config, + attribute, outValue)); + ASSERT_GE(*outValue, 0) << "failed to get valid " + << getAttributeName(attribute); + } + + void getActiveDisplayArea(hwc2_display_t display, Area* displayArea) + { + ASSERT_NO_FATAL_FAILURE(getActiveConfigAttribute(display, + HWC2_ATTRIBUTE_WIDTH, &displayArea->width)); + ASSERT_NO_FATAL_FAILURE(getActiveConfigAttribute(display, + HWC2_ATTRIBUTE_HEIGHT, &displayArea->height)); + } + hwc2_device_t* mHwc2Device = nullptr; enum class Hwc2TestHotplugStatus { @@ -839,6 +887,13 @@ void setDataspace(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer, testLayer.getDataspace(), outErr)); } +void setDisplayFrame(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer, + const Hwc2TestLayer& testLayer, hwc2_error_t* outErr) +{ + EXPECT_NO_FATAL_FAILURE(test->setLayerDisplayFrame(display, layer, + testLayer.getDisplayFrame(), outErr)); +} + void setPlaneAlpha(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer, const Hwc2TestLayer& testLayer, hwc2_error_t *outErr) { @@ -877,6 +932,11 @@ bool advanceDataspace(Hwc2TestLayer* testLayer) return testLayer->advanceDataspace(); } +bool advanceDisplayFrame(Hwc2TestLayer* testLayer) +{ + return testLayer->advanceDisplayFrame(); +} + bool advancePlaneAlpha(Hwc2TestLayer* testLayer) { return testLayer->advancePlaneAlpha(); @@ -1790,6 +1850,27 @@ TEST_F(Hwc2Test, SET_LAYER_DATASPACE_bad_layer) setDataspace)); } +/* TESTCASE: Tests that the HWC2 can set the display frame of a layer. */ +TEST_F(Hwc2Test, SET_LAYER_DISPLAY_FRAME) +{ + ASSERT_NO_FATAL_FAILURE(setLayerProperty(Hwc2TestCoverage::Complete, + setDisplayFrame, advanceDisplayFrame)); +} + +/* TESTCASE: Tests that the HWC2 can update the display frame of a layer. */ +TEST_F(Hwc2Test, SET_LAYER_DISPLAY_FRAME_update) +{ + ASSERT_NO_FATAL_FAILURE(setLayerPropertyUpdate(Hwc2TestCoverage::Complete, + setDisplayFrame, advanceDisplayFrame)); +} + +/* TESTCASE: Tests that the HWC2 cannot set the display frame of a bad layer. */ +TEST_F(Hwc2Test, SET_LAYER_DISPLAY_FRAME_bad_layer) +{ + ASSERT_NO_FATAL_FAILURE(setLayerPropertyBadLayer(Hwc2TestCoverage::Default, + setDisplayFrame)); +} + /* TESTCASE: Tests that the HWC2 can set the plane alpha of a layer. */ TEST_F(Hwc2Test, SET_LAYER_PLANE_ALPHA) { diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp b/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp index b9ca9c3b03..261fe976a1 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp @@ -18,10 +18,12 @@ #include "Hwc2TestLayer.h" -Hwc2TestLayer::Hwc2TestLayer(Hwc2TestCoverage coverage, uint32_t zOrder) +Hwc2TestLayer::Hwc2TestLayer(Hwc2TestCoverage coverage, const Area& displayArea, + uint32_t zOrder) : mBlendMode(coverage), mComposition(coverage), mDataspace(coverage), + mDisplayFrame(coverage, displayArea), mPlaneAlpha(coverage), mTransform(coverage), mZOrder(zOrder) { } @@ -63,6 +65,11 @@ android_dataspace_t Hwc2TestLayer::getDataspace() const return mDataspace.get(); } +hwc_rect_t Hwc2TestLayer::getDisplayFrame() const +{ + return mDisplayFrame.get(); +} + float Hwc2TestLayer::getPlaneAlpha() const { return mPlaneAlpha.get(); @@ -93,6 +100,11 @@ bool Hwc2TestLayer::advanceDataspace() return mDataspace.advance(); } +bool Hwc2TestLayer::advanceDisplayFrame() +{ + return mDisplayFrame.advance(); +} + bool Hwc2TestLayer::advancePlaneAlpha() { return mPlaneAlpha.advance(); diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h b/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h index 855f7bbbd8..e24ff77404 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h @@ -27,7 +27,8 @@ class Hwc2TestLayer { public: - Hwc2TestLayer(Hwc2TestCoverage coverage, uint32_t zOrder = 0); + Hwc2TestLayer(Hwc2TestCoverage coverage, const Area& displayArea, + uint32_t zOrder = 0); std::string dump() const; @@ -36,6 +37,7 @@ public: hwc2_blend_mode_t getBlendMode() const; hwc2_composition_t getComposition() const; android_dataspace_t getDataspace() const; + hwc_rect_t getDisplayFrame() const; float getPlaneAlpha() const; hwc_transform_t getTransform() const; uint32_t getZOrder() const; @@ -43,17 +45,20 @@ public: bool advanceBlendMode(); bool advanceComposition(); bool advanceDataspace(); + bool advanceDisplayFrame(); bool advancePlaneAlpha(); bool advanceTransform(); private: - std::array mProperties = {{ - &mBlendMode, &mComposition, &mDataspace, &mPlaneAlpha, &mTransform + std::array mProperties = {{ + &mBlendMode, &mComposition, &mDataspace, &mDisplayFrame, &mPlaneAlpha, + &mTransform }}; Hwc2TestBlendMode mBlendMode; Hwc2TestComposition mComposition; Hwc2TestDataspace mDataspace; + Hwc2TestDisplayFrame mDisplayFrame; Hwc2TestPlaneAlpha mPlaneAlpha; Hwc2TestTransform mTransform; diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.cpp b/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.cpp index b2318b1d70..02a9df1d47 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.cpp +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.cpp @@ -19,14 +19,14 @@ #include "Hwc2TestLayers.h" Hwc2TestLayers::Hwc2TestLayers(const std::vector& layers, - Hwc2TestCoverage coverage) + Hwc2TestCoverage coverage, const Area& displayArea) { uint32_t nextZOrder = 0; for (auto layer : layers) { mTestLayers.emplace(std::piecewise_construct, std::forward_as_tuple(layer), - std::forward_as_tuple(coverage, nextZOrder++)); + std::forward_as_tuple(coverage, displayArea, nextZOrder++)); } } diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.h b/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.h index fcc903a19e..1625352b85 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.h +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.h @@ -31,7 +31,7 @@ class Hwc2TestLayers { public: Hwc2TestLayers(const std::vector& layers, - Hwc2TestCoverage coverage); + Hwc2TestCoverage coverage, const Area& displayArea); std::string dump() const; diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp index eb49d3272e..e793c11836 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp @@ -140,6 +140,66 @@ const std::vector Hwc2TestDataspace::completeDataspaces = { }; +Hwc2TestDisplayFrame::Hwc2TestDisplayFrame(Hwc2TestCoverage coverage, + const Area& displayArea) + : Hwc2TestProperty(mDisplayFrames), + mFrectScalars((coverage == Hwc2TestCoverage::Complete)? mCompleteFrectScalars: + (coverage == Hwc2TestCoverage::Basic)? mBasicFrectScalars: + mDefaultFrectScalars), + mDisplayArea(displayArea) +{ + update(); +} + +std::string Hwc2TestDisplayFrame::dump() const +{ + std::stringstream dmp; + const hwc_rect_t& displayFrame = get(); + dmp << "\tdisplay frame: left " << displayFrame.left << ", top " + << displayFrame.top << ", right " << displayFrame.right + << ", bottom " << displayFrame.bottom << "\n"; + return dmp.str(); +} + +void Hwc2TestDisplayFrame::update() +{ + mDisplayFrames.clear(); + + if (mDisplayArea.width == 0 && mDisplayArea.height == 0) { + mDisplayFrames.push_back({0, 0, 0, 0}); + return; + } + + for (const auto& frectScalar : mFrectScalars) { + mDisplayFrames.push_back({ + static_cast(frectScalar.left * mDisplayArea.width), + static_cast(frectScalar.top * mDisplayArea.height), + static_cast(frectScalar.right * mDisplayArea.width), + static_cast(frectScalar.bottom * mDisplayArea.height)}); + } +} + +const std::vector Hwc2TestDisplayFrame::mDefaultFrectScalars = { + {0.0, 0.0, 1.0, 1.0}, +}; + +const std::vector Hwc2TestDisplayFrame::mBasicFrectScalars = { + {0.0, 0.0, 1.0, 1.0}, + {0.0, 0.0, 1.0, 0.05}, + {0.0, 0.95, 1.0, 1.0}, +}; + +const std::vector Hwc2TestDisplayFrame::mCompleteFrectScalars = { + {0.0, 0.0, 1.0, 1.0}, + {0.0, 0.05, 1.0, 0.95}, + {0.0, 0.05, 1.0, 1.0}, + {0.0, 0.0, 1.0, 0.05}, + {0.0, 0.95, 1.0, 1.0}, + {0.25, 0.0, 0.75, 0.35}, + {0.25, 0.25, 0.75, 0.75}, +}; + + Hwc2TestPlaneAlpha::Hwc2TestPlaneAlpha(Hwc2TestCoverage coverage) : Hwc2TestProperty(coverage, mCompletePlaneAlphas, mBasicPlaneAlphas, mDefaultPlaneAlphas) { } diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h index a96b629a3d..25c6ad8717 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h @@ -32,6 +32,11 @@ enum class Hwc2TestCoverage { Complete, }; +typedef struct { + int32_t width; + int32_t height; +} Area; + class Hwc2TestContainer { public: @@ -125,6 +130,26 @@ protected: }; +class Hwc2TestDisplayFrame : public Hwc2TestProperty { +public: + Hwc2TestDisplayFrame(Hwc2TestCoverage coverage, const Area& displayArea); + + std::string dump() const override; + +protected: + void update(); + + const std::vector& mFrectScalars; + const static std::vector mDefaultFrectScalars; + const static std::vector mBasicFrectScalars; + const static std::vector mCompleteFrectScalars; + + Area mDisplayArea; + + std::vector mDisplayFrames; +}; + + class Hwc2TestPlaneAlpha : public Hwc2TestProperty { public: Hwc2TestPlaneAlpha(Hwc2TestCoverage coverage); -- cgit v1.2.3-59-g8ed1b From c57468f1f6dfc870bea10e814a686793e64f6cf3 Mon Sep 17 00:00:00 2001 From: Marissa Wall Date: Thu, 15 Dec 2016 12:31:12 -0800 Subject: test-hwc2: set layer source crop Test: Add "#define HAVE_NO_SURFACE_FLINGER" to frameworks/native/libs/gui/BufferQueueCore.cpp. Recompile and flash. Run "mm" in frameworks/native/services/surfaceflinger/tests/hwc2. Push test-hwc2 to device. Run "adb root && adb shell stop". Run test case. Ex: "./test-hwc2" Change-Id: If3079efd7a035d1d182f04c56dc55300cdcedc47 --- services/surfaceflinger/tests/hwc2/Hwc2Test.cpp | 51 ++++++++ .../surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp | 22 +++- services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h | 11 +- .../tests/hwc2/Hwc2TestProperties.cpp | 128 +++++++++++++++++++++ .../surfaceflinger/tests/hwc2/Hwc2TestProperties.h | 54 +++++++++ 5 files changed, 262 insertions(+), 4 deletions(-) diff --git a/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp index c092f222be..b060be90bd 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp +++ b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp @@ -425,6 +425,22 @@ public: } } + void setLayerSourceCrop(hwc2_display_t display, hwc2_layer_t layer, + const hwc_frect_t& sourceCrop, hwc2_error_t* outErr = nullptr) + { + auto pfn = reinterpret_cast( + getFunction(HWC2_FUNCTION_SET_LAYER_SOURCE_CROP)); + ASSERT_TRUE(pfn) << "failed to get function"; + + auto err = static_cast(pfn(mHwc2Device, display, layer, + sourceCrop)); + if (outErr) { + *outErr = err; + } else { + ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set layer source crop"; + } + } + void setLayerTransform(hwc2_display_t display, hwc2_layer_t layer, hwc_transform_t transform, hwc2_error_t* outErr = nullptr) { @@ -903,6 +919,13 @@ void setPlaneAlpha(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer, testLayer.getPlaneAlpha(), outErr)); } +void setSourceCrop(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer, + const Hwc2TestLayer& testLayer, hwc2_error_t* outErr) +{ + EXPECT_NO_FATAL_FAILURE(test->setLayerSourceCrop(display, layer, + testLayer.getSourceCrop(), outErr)); +} + void setTransform(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer, const Hwc2TestLayer& testLayer, hwc2_error_t* outErr) { @@ -942,6 +965,13 @@ bool advancePlaneAlpha(Hwc2TestLayer* testLayer) return testLayer->advancePlaneAlpha(); } +bool advanceSourceCrop(Hwc2TestLayer* testLayer) +{ + if (testLayer->advanceSourceCrop()) + return true; + return testLayer->advanceBufferArea(); +} + bool advanceTransform(Hwc2TestLayer* testLayer) { return testLayer->advanceTransform(); @@ -1898,6 +1928,27 @@ TEST_F(Hwc2Test, SET_LAYER_PLANE_ALPHA_bad_layer) )); } +/* TESTCASE: Tests that the HWC2 can set the source crop of a layer. */ +TEST_F(Hwc2Test, SET_LAYER_SOURCE_CROP) +{ + ASSERT_NO_FATAL_FAILURE(setLayerProperty(Hwc2TestCoverage::Complete, + setSourceCrop, advanceSourceCrop)); +} + +/* TESTCASE: Tests that the HWC2 can update the source crop of a layer. */ +TEST_F(Hwc2Test, SET_LAYER_SOURCE_CROP_update) +{ + ASSERT_NO_FATAL_FAILURE(setLayerPropertyUpdate(Hwc2TestCoverage::Complete, + setSourceCrop, advanceSourceCrop)); +} + +/* TESTCASE: Tests that the HWC2 cannot set the source crop of a bad layer. */ +TEST_F(Hwc2Test, SET_LAYER_SOURCE_CROP_bad_layer) +{ + ASSERT_NO_FATAL_FAILURE(setLayerPropertyBadLayer(Hwc2TestCoverage::Default, + setSourceCrop)); +} + /* TESTCASE: Tests that the HWC2 can set the transform value of a layer. */ TEST_F(Hwc2Test, SET_LAYER_TRANSFORM) { diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp b/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp index 261fe976a1..cdf4392684 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp @@ -21,12 +21,17 @@ Hwc2TestLayer::Hwc2TestLayer(Hwc2TestCoverage coverage, const Area& displayArea, uint32_t zOrder) : mBlendMode(coverage), + mBufferArea(coverage, displayArea), mComposition(coverage), mDataspace(coverage), mDisplayFrame(coverage, displayArea), mPlaneAlpha(coverage), + mSourceCrop(coverage), mTransform(coverage), - mZOrder(zOrder) { } + mZOrder(zOrder) +{ + mBufferArea.setDependent(&mSourceCrop); +} std::string Hwc2TestLayer::dump() const { @@ -75,6 +80,11 @@ float Hwc2TestLayer::getPlaneAlpha() const return mPlaneAlpha.get(); } +hwc_frect_t Hwc2TestLayer::getSourceCrop() const +{ + return mSourceCrop.get(); +} + hwc_transform_t Hwc2TestLayer::getTransform() const { return mTransform.get(); @@ -90,6 +100,11 @@ bool Hwc2TestLayer::advanceBlendMode() return mBlendMode.advance(); } +bool Hwc2TestLayer::advanceBufferArea() +{ + return mBufferArea.advance(); +} + bool Hwc2TestLayer::advanceComposition() { return mComposition.advance(); @@ -110,6 +125,11 @@ bool Hwc2TestLayer::advancePlaneAlpha() return mPlaneAlpha.advance(); } +bool Hwc2TestLayer::advanceSourceCrop() +{ + return mSourceCrop.advance(); +} + bool Hwc2TestLayer::advanceTransform() { return mTransform.advance(); diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h b/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h index e24ff77404..86d40cc584 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h @@ -39,27 +39,32 @@ public: android_dataspace_t getDataspace() const; hwc_rect_t getDisplayFrame() const; float getPlaneAlpha() const; + hwc_frect_t getSourceCrop() const; hwc_transform_t getTransform() const; uint32_t getZOrder() const; bool advanceBlendMode(); + bool advanceBufferArea(); bool advanceComposition(); bool advanceDataspace(); bool advanceDisplayFrame(); bool advancePlaneAlpha(); + bool advanceSourceCrop(); bool advanceTransform(); private: - std::array mProperties = {{ - &mBlendMode, &mComposition, &mDataspace, &mDisplayFrame, &mPlaneAlpha, - &mTransform + std::array mProperties = {{ + &mBlendMode, &mComposition, &mDataspace, &mDisplayFrame, &mPlaneAlpha, + &mSourceCrop, &mTransform }}; Hwc2TestBlendMode mBlendMode; + Hwc2TestBufferArea mBufferArea; Hwc2TestComposition mComposition; Hwc2TestDataspace mDataspace; Hwc2TestDisplayFrame mDisplayFrame; Hwc2TestPlaneAlpha mPlaneAlpha; + Hwc2TestSourceCrop mSourceCrop; Hwc2TestTransform mTransform; uint32_t mZOrder; diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp index e793c11836..0073857378 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp @@ -18,6 +18,70 @@ #include "Hwc2TestProperties.h" +Hwc2TestBufferArea::Hwc2TestBufferArea(Hwc2TestCoverage coverage, + const Area& displayArea) + : Hwc2TestProperty(mBufferAreas), + mScalars((coverage == Hwc2TestCoverage::Complete)? mCompleteScalars: + (coverage == Hwc2TestCoverage::Basic)? mBasicScalars: + mDefaultScalars), + mDisplayArea(displayArea) +{ + update(); +} + +std::string Hwc2TestBufferArea::dump() const +{ + std::stringstream dmp; + const Area& curr = get(); + dmp << "\tbuffer area: width " << curr.width << ", height " << curr.height + << "\n"; + return dmp.str(); +} + +void Hwc2TestBufferArea::setDependent(Hwc2TestSourceCrop* sourceCrop) +{ + mSourceCrop = sourceCrop; + updateDependents(); +} + +void Hwc2TestBufferArea::update() +{ + mBufferAreas.clear(); + + if (mDisplayArea.width == 0 && mDisplayArea.height == 0) { + mBufferAreas.push_back({0, 0}); + return; + } + + for (auto scalar : mScalars) { + mBufferAreas.push_back({static_cast(scalar * mDisplayArea.width), + static_cast(scalar * mDisplayArea.height)}); + } + + updateDependents(); +} + +void Hwc2TestBufferArea::updateDependents() +{ + const Area& curr = get(); + + if (mSourceCrop) + mSourceCrop->updateBufferArea(curr); +} + +const std::vector Hwc2TestBufferArea::mDefaultScalars = { + 1.0f, +}; + +const std::vector Hwc2TestBufferArea::mBasicScalars = { + 1.0f, 0.5f, +}; + +const std::vector Hwc2TestBufferArea::mCompleteScalars = { + 1.0f, 0.75f, 0.5f +}; + + Hwc2TestBlendMode::Hwc2TestBlendMode(Hwc2TestCoverage coverage) : Hwc2TestProperty(coverage, mCompleteBlendModes, mBasicBlendModes, mDefaultBlendModes) { } @@ -224,6 +288,70 @@ const std::vector Hwc2TestPlaneAlpha::mCompletePlaneAlphas = { }; +Hwc2TestSourceCrop::Hwc2TestSourceCrop(Hwc2TestCoverage coverage, + const Area& bufferArea) + : Hwc2TestProperty(mSourceCrops), + mFrectScalars((coverage == Hwc2TestCoverage::Complete)? mCompleteFrectScalars: + (coverage == Hwc2TestCoverage::Basic)? mBasicFrectScalars: + mDefaultFrectScalars), + mBufferArea(bufferArea) +{ + update(); +} + +std::string Hwc2TestSourceCrop::dump() const +{ + std::stringstream dmp; + const hwc_frect_t& sourceCrop = get(); + dmp << "\tsource crop: left " << sourceCrop.left << ", top " + << sourceCrop.top << ", right " << sourceCrop.right << ", bottom " + << sourceCrop.bottom << "\n"; + return dmp.str(); +} + +void Hwc2TestSourceCrop::updateBufferArea(const Area& bufferArea) +{ + mBufferArea = bufferArea; + update(); +} + +void Hwc2TestSourceCrop::update() +{ + mSourceCrops.clear(); + + if (mBufferArea.width == 0 && mBufferArea.height == 0) { + mSourceCrops.push_back({0, 0, 0, 0}); + return; + } + + for (const auto& frectScalar : mFrectScalars) { + mSourceCrops.push_back({ + frectScalar.left * mBufferArea.width, + frectScalar.top * mBufferArea.height, + frectScalar.right * mBufferArea.width, + frectScalar.bottom * mBufferArea.height}); + } +} + +const std::vector Hwc2TestSourceCrop::mDefaultFrectScalars = { + {0.0, 0.0, 1.0, 1.0}, +}; + +const std::vector Hwc2TestSourceCrop::mBasicFrectScalars = { + {0.0, 0.0, 1.0, 1.0}, + {0.0, 0.0, 0.5, 0.5}, + {0.5, 0.5, 1.0, 1.0}, +}; + +const std::vector Hwc2TestSourceCrop::mCompleteFrectScalars = { + {0.0, 0.0, 1.0, 1.0}, + {0.0, 0.0, 0.5, 0.5}, + {0.5, 0.5, 1.0, 1.0}, + {0.0, 0.0, 0.25, 0.25}, + {0.25, 0.25, 0.75, 0.75}, +}; + + Hwc2TestTransform::Hwc2TestTransform(Hwc2TestCoverage coverage) : Hwc2TestProperty(coverage, mCompleteTransforms, mBasicTransforms, mDefaultTransforms) { } diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h index 25c6ad8717..9df532ecb0 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h @@ -74,9 +74,11 @@ public: { if (mListIdx + 1 < mList.size()) { mListIdx++; + updateDependents(); return true; } reset(); + updateDependents(); return false; } @@ -86,11 +88,41 @@ public: } protected: + /* If a derived class has dependents, override this function */ + virtual void updateDependents() { } + const std::vector& mList; size_t mListIdx = 0; }; +class Hwc2TestSourceCrop; + +class Hwc2TestBufferArea : public Hwc2TestProperty { +public: + Hwc2TestBufferArea(Hwc2TestCoverage coverage, const Area& displayArea); + + std::string dump() const override; + + void setDependent(Hwc2TestSourceCrop* sourceCrop); + +protected: + void update(); + void updateDependents() override; + + const std::vector& mScalars; + static const std::vector mDefaultScalars; + static const std::vector mBasicScalars; + static const std::vector mCompleteScalars; + + Area mDisplayArea; + + Hwc2TestSourceCrop* mSourceCrop = nullptr; + + std::vector mBufferAreas; +}; + + class Hwc2TestBlendMode : public Hwc2TestProperty { public: Hwc2TestBlendMode(Hwc2TestCoverage coverage); @@ -163,6 +195,28 @@ protected: }; +class Hwc2TestSourceCrop : public Hwc2TestProperty { +public: + Hwc2TestSourceCrop(Hwc2TestCoverage coverage, const Area& bufferArea = {0, 0}); + + std::string dump() const override; + + void updateBufferArea(const Area& bufferArea); + +protected: + void update(); + + const std::vector& mFrectScalars; + const static std::vector mDefaultFrectScalars; + const static std::vector mBasicFrectScalars; + const static std::vector mCompleteFrectScalars; + + Area mBufferArea; + + std::vector mSourceCrops; +}; + + class Hwc2TestTransform : public Hwc2TestProperty { public: Hwc2TestTransform(Hwc2TestCoverage coverage); -- cgit v1.2.3-59-g8ed1b From ee24278db26505369c0e917d2a83e7e9fda36e4c Mon Sep 17 00:00:00 2001 From: Marissa Wall Date: Thu, 15 Dec 2016 12:30:12 -0800 Subject: test-hwc2: set layer color Test: Add "#define HAVE_NO_SURFACE_FLINGER" to frameworks/native/libs/gui/BufferQueueCore.cpp. Recompile and flash. Run "mm" in frameworks/native/services/surfaceflinger/tests/hwc2. Push test-hwc2 to device. Run "adb root && adb shell stop". Run test case. Ex: "./test-hwc2" Change-Id: Ic280f91189a4d6ddd67a33901244714f3c0a46dd --- services/surfaceflinger/tests/hwc2/Hwc2Test.cpp | 82 +++++++++++++++++++++ .../surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp | 12 +++ services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h | 9 ++- .../tests/hwc2/Hwc2TestProperties.cpp | 86 ++++++++++++++++++++++ .../surfaceflinger/tests/hwc2/Hwc2TestProperties.h | 31 ++++++++ 5 files changed, 217 insertions(+), 3 deletions(-) diff --git a/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp index b060be90bd..bba97b8991 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp +++ b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp @@ -375,6 +375,22 @@ public: } } + void setLayerColor(hwc2_display_t display, hwc2_layer_t layer, + hwc_color_t color, hwc2_error_t* outErr = nullptr) + { + auto pfn = reinterpret_cast( + getFunction(HWC2_FUNCTION_SET_LAYER_COLOR)); + ASSERT_TRUE(pfn) << "failed to get function"; + + auto err = static_cast(pfn(mHwc2Device, display, layer, + color)); + if (outErr) { + *outErr = err; + } else { + ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set layer color"; + } + } + void setLayerDataspace(hwc2_display_t display, hwc2_layer_t layer, android_dataspace_t dataspace, hwc2_error_t* outErr = nullptr) { @@ -875,6 +891,19 @@ void setBlendMode(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer, testLayer.getBlendMode(), outErr)); } +void setColor(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer, + const Hwc2TestLayer& testLayer, hwc2_error_t* outErr) +{ + ASSERT_NO_FATAL_FAILURE(test->setLayerCompositionType(display, + layer, HWC2_COMPOSITION_SOLID_COLOR)); + ASSERT_NO_FATAL_FAILURE(test->setLayerPlaneAlpha(display, + layer, testLayer.getPlaneAlpha())); + ASSERT_NO_FATAL_FAILURE(test->setLayerBlendMode(display, + layer, testLayer.getBlendMode())); + EXPECT_NO_FATAL_FAILURE(test->setLayerColor(display, layer, + testLayer.getColor(), outErr)); +} + void setComposition(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer, const Hwc2TestLayer& testLayer, hwc2_error_t* outErr) { @@ -945,6 +974,17 @@ bool advanceBlendMode(Hwc2TestLayer* testLayer) return testLayer->advanceBlendMode(); } +bool advanceColor(Hwc2TestLayer* testLayer) +{ + /* Color depends on blend mode so advance blend mode last so color is not + * force to update as often */ + if (testLayer->advancePlaneAlpha()) + return true; + if (testLayer->advanceColor()) + return true; + return testLayer->advanceBlendMode(); +} + bool advanceComposition(Hwc2TestLayer* testLayer) { return testLayer->advanceComposition(); @@ -1859,6 +1899,48 @@ TEST_F(Hwc2Test, SET_LAYER_BLEND_MODE_bad_parameter) )); } +/* TESTCASE: Tests that the HWC2 can set the color of a layer. */ +TEST_F(Hwc2Test, SET_LAYER_COLOR) +{ + ASSERT_NO_FATAL_FAILURE(setLayerProperty(Hwc2TestCoverage::Complete, + setColor, advanceColor)); +} + +/* TESTCASE: Tests that the HWC2 can update the color of a layer. */ +TEST_F(Hwc2Test, SET_LAYER_COLOR_update) +{ + ASSERT_NO_FATAL_FAILURE(setLayerPropertyUpdate(Hwc2TestCoverage::Complete, + setColor, advanceColor)); +} + +/* TESTCASE: Tests that the HWC2 can set the color of a layer when the + * composition type has not been set to HWC2_COMPOSITION_SOLID_COLOR. */ +TEST_F(Hwc2Test, SET_LAYER_COLOR_composition_type_unset) +{ + ASSERT_NO_FATAL_FAILURE(setLayerProperty(Hwc2TestCoverage::Basic, + [] (Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer, + const Hwc2TestLayer& testLayer, hwc2_error_t* outErr) { + + EXPECT_NO_FATAL_FAILURE(test->setLayerColor(display, layer, + testLayer.getColor(), outErr)); + }, + + advanceColor)); +} + +/* TESTCASE: Tests that the HWC2 cannot set the color of a bad layer. */ +TEST_F(Hwc2Test, SET_LAYER_COLOR_bad_layer) +{ + ASSERT_NO_FATAL_FAILURE(setLayerPropertyBadLayer(Hwc2TestCoverage::Default, + [] (Hwc2Test* test, hwc2_display_t display, hwc2_layer_t badLayer, + const Hwc2TestLayer& testLayer, hwc2_error_t* outErr) { + + EXPECT_NO_FATAL_FAILURE(test->setLayerColor(display, badLayer, + testLayer.getColor(), outErr)); + } + )); +} + /* TESTCASE: Tests that the HWC2 can set the dataspace of a layer. */ TEST_F(Hwc2Test, SET_LAYER_DATASPACE) { diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp b/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp index cdf4392684..caf3987701 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp @@ -22,6 +22,7 @@ Hwc2TestLayer::Hwc2TestLayer(Hwc2TestCoverage coverage, const Area& displayArea, uint32_t zOrder) : mBlendMode(coverage), mBufferArea(coverage, displayArea), + mColor(coverage), mComposition(coverage), mDataspace(coverage), mDisplayFrame(coverage, displayArea), @@ -31,6 +32,7 @@ Hwc2TestLayer::Hwc2TestLayer(Hwc2TestCoverage coverage, const Area& displayArea, mZOrder(zOrder) { mBufferArea.setDependent(&mSourceCrop); + mBlendMode.setDependent(&mColor); } std::string Hwc2TestLayer::dump() const @@ -60,6 +62,11 @@ hwc2_blend_mode_t Hwc2TestLayer::getBlendMode() const return mBlendMode.get(); } +hwc_color_t Hwc2TestLayer::getColor() const +{ + return mColor.get(); +} + hwc2_composition_t Hwc2TestLayer::getComposition() const { return mComposition.get(); @@ -105,6 +112,11 @@ bool Hwc2TestLayer::advanceBufferArea() return mBufferArea.advance(); } +bool Hwc2TestLayer::advanceColor() +{ + return mColor.advance(); +} + bool Hwc2TestLayer::advanceComposition() { return mComposition.advance(); diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h b/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h index 86d40cc584..f548ea6f7c 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h @@ -35,6 +35,7 @@ public: void reset(); hwc2_blend_mode_t getBlendMode() const; + hwc_color_t getColor() const; hwc2_composition_t getComposition() const; android_dataspace_t getDataspace() const; hwc_rect_t getDisplayFrame() const; @@ -45,6 +46,7 @@ public: bool advanceBlendMode(); bool advanceBufferArea(); + bool advanceColor(); bool advanceComposition(); bool advanceDataspace(); bool advanceDisplayFrame(); @@ -53,13 +55,14 @@ public: bool advanceTransform(); private: - std::array mProperties = {{ - &mBlendMode, &mComposition, &mDataspace, &mDisplayFrame, &mPlaneAlpha, - &mSourceCrop, &mTransform + std::array mProperties = {{ + &mBlendMode, &mColor, &mComposition, &mDataspace, &mDisplayFrame, + &mPlaneAlpha, &mSourceCrop, &mTransform }}; Hwc2TestBlendMode mBlendMode; Hwc2TestBufferArea mBufferArea; + Hwc2TestColor mColor; Hwc2TestComposition mComposition; Hwc2TestDataspace mDataspace; Hwc2TestDisplayFrame mDisplayFrame; diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp index 0073857378..1e404409b4 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp @@ -93,6 +93,18 @@ std::string Hwc2TestBlendMode::dump() const return dmp.str(); } +void Hwc2TestBlendMode::setDependent(Hwc2TestColor* color) +{ + mColor = color; + updateDependents(); +} + +void Hwc2TestBlendMode::updateDependents() +{ + if (mColor) + mColor->updateBlendMode(get()); +} + const std::vector Hwc2TestBlendMode::mDefaultBlendModes = { HWC2_BLEND_MODE_NONE, }; @@ -109,6 +121,80 @@ const std::vector Hwc2TestBlendMode::mCompleteBlendModes = { }; +Hwc2TestColor::Hwc2TestColor(Hwc2TestCoverage coverage, + hwc2_blend_mode_t blendMode) + : Hwc2TestProperty(mColors), + mBaseColors((coverage == Hwc2TestCoverage::Complete)? mCompleteBaseColors: + (coverage == Hwc2TestCoverage::Basic)? mBasicBaseColors: + mDefaultBaseColors), + mBlendMode(blendMode) +{ + update(); +} + +std::string Hwc2TestColor::dump() const +{ + std::stringstream dmp; + const hwc_color_t& color = get(); + dmp << "\tcolor: r " << std::to_string(color.r) << ", g " + << std::to_string(color.g) << ", b " << std::to_string(color.b) + << ", a " << std::to_string(color.a) << "\n"; + return dmp.str(); +} + +void Hwc2TestColor::updateBlendMode(hwc2_blend_mode_t blendMode) +{ + mBlendMode = blendMode; + update(); +} + +void Hwc2TestColor::update() +{ + if (mBlendMode != HWC2_BLEND_MODE_PREMULTIPLIED) { + mColors = mBaseColors; + return; + } + + mColors.clear(); + + for (const hwc_color_t& baseColor : mBaseColors) { + if (baseColor.a >= baseColor.r && baseColor.a >= baseColor.g + && baseColor.a >= baseColor.b) { + mColors.push_back(baseColor); + } + } + +} + +const std::vector Hwc2TestColor::mDefaultBaseColors = { + {UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX}, +}; + +const std::vector Hwc2TestColor::mBasicBaseColors = { + {UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX}, + { 0, 0, 0, 0}, +}; + +const std::vector Hwc2TestColor::mCompleteBaseColors = { + {UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX}, + {UINT8_MAX, UINT8_MAX, UINT8_MAX, 0}, + {UINT8_MAX, UINT8_MAX, 0, UINT8_MAX}, + {UINT8_MAX, UINT8_MAX, 0, 0}, + {UINT8_MAX, 0, UINT8_MAX, UINT8_MAX}, + {UINT8_MAX, 0, UINT8_MAX, 0}, + {UINT8_MAX, 0, 0, UINT8_MAX}, + {UINT8_MAX, 0, 0, 0}, + { 0, UINT8_MAX, UINT8_MAX, UINT8_MAX}, + { 0, UINT8_MAX, UINT8_MAX, 0}, + { 0, UINT8_MAX, 0, UINT8_MAX}, + { 0, UINT8_MAX, 0, 0}, + { 0, 0, UINT8_MAX, UINT8_MAX}, + { 0, 0, UINT8_MAX, 0}, + { 0, 0, 0, UINT8_MAX}, + { 0, 0, 0, 0}, +}; + + Hwc2TestComposition::Hwc2TestComposition(Hwc2TestCoverage coverage) : Hwc2TestProperty(coverage, mCompleteCompositions, mBasicCompositions, mDefaultCompositions) { } diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h index 9df532ecb0..870f1ccad3 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h @@ -123,19 +123,50 @@ protected: }; +class Hwc2TestColor; + class Hwc2TestBlendMode : public Hwc2TestProperty { public: Hwc2TestBlendMode(Hwc2TestCoverage coverage); std::string dump() const override; + void setDependent(Hwc2TestColor* color); + protected: + void updateDependents() override; + + Hwc2TestColor* mColor = nullptr; + static const std::vector mDefaultBlendModes; static const std::vector mBasicBlendModes; static const std::vector mCompleteBlendModes; }; +class Hwc2TestColor : public Hwc2TestProperty { +public: + Hwc2TestColor(Hwc2TestCoverage coverage, + hwc2_blend_mode_t blendMode = HWC2_BLEND_MODE_NONE); + + std::string dump() const override; + + void updateBlendMode(hwc2_blend_mode_t blendMode); + +protected: + void update(); + + std::vector mBaseColors; + static const std::vector mDefaultBaseColors; + static const std::vector mBasicBaseColors; + static const std::vector mCompleteBaseColors; + + hwc2_blend_mode_t mBlendMode; + + std::vector mColors; +}; + + class Hwc2TestComposition : public Hwc2TestProperty { public: Hwc2TestComposition(Hwc2TestCoverage coverage); -- cgit v1.2.3-59-g8ed1b From 2a0aaf9f5a3daeb0525249eda40242bb63f56468 Mon Sep 17 00:00:00 2001 From: Marissa Wall Date: Thu, 15 Dec 2016 12:31:37 -0800 Subject: test-hwc2: set cursor position Test: Add "#define HAVE_NO_SURFACE_FLINGER" to frameworks/native/libs/gui/BufferQueueCore.cpp. Recompile and flash. Run "mm" in frameworks/native/services/surfaceflinger/tests/hwc2. Push test-hwc2 to device. Run "adb root && adb shell stop". Run test case. Ex: "./test-hwc2" Change-Id: I4b265826befcf33c3f71b52bfabc076c48efed5f --- services/surfaceflinger/tests/hwc2/Hwc2Test.cpp | 92 ++++++++++++++++++++++ .../surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp | 11 +++ services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h | 2 + 3 files changed, 105 insertions(+) diff --git a/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp index bba97b8991..2a97a8c422 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp +++ b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp @@ -358,6 +358,22 @@ public: } } + void setCursorPosition(hwc2_display_t display, hwc2_layer_t layer, + int32_t x, int32_t y, hwc2_error_t* outErr = nullptr) + { + auto pfn = reinterpret_cast( + getFunction(HWC2_FUNCTION_SET_CURSOR_POSITION)); + ASSERT_TRUE(pfn) << "failed to get function"; + + auto err = static_cast(pfn(mHwc2Device, display, layer, x, + y)); + if (outErr) { + *outErr = err; + } else { + ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set cursor position"; + } + } + void setLayerBlendMode(hwc2_display_t display, hwc2_layer_t layer, hwc2_blend_mode_t mode, hwc2_error_t* outErr = nullptr) { @@ -925,6 +941,17 @@ void setComposition(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer, } } +void setCursorPosition(Hwc2Test* test, hwc2_display_t display, + hwc2_layer_t layer, const Hwc2TestLayer& testLayer, hwc2_error_t* outErr) +{ + ASSERT_NO_FATAL_FAILURE(test->setLayerCompositionType(display, + layer, HWC2_COMPOSITION_CURSOR)); + + const hwc_rect_t cursorPosition = testLayer.getCursorPosition(); + EXPECT_NO_FATAL_FAILURE(test->setCursorPosition(display, layer, + cursorPosition.left, cursorPosition.top, outErr)); +} + void setDataspace(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer, const Hwc2TestLayer& testLayer, hwc2_error_t* outErr) { @@ -990,6 +1017,11 @@ bool advanceComposition(Hwc2TestLayer* testLayer) return testLayer->advanceComposition(); } +bool advanceCursorPosition(Hwc2TestLayer* testLayer) +{ + return testLayer->advanceCursorPosition(); +} + bool advanceDataspace(Hwc2TestLayer* testLayer) { return testLayer->advanceDataspace(); @@ -1865,6 +1897,66 @@ TEST_F(Hwc2Test, SET_LAYER_COMPOSITION_TYPE_bad_parameter) )); } +/* TESTCASE: Tests that the HWC2 can set the cursor position of a layer. */ +TEST_F(Hwc2Test, SET_CURSOR_POSITION) +{ + ASSERT_NO_FATAL_FAILURE(setLayerProperty(Hwc2TestCoverage::Complete, + ::setCursorPosition, advanceCursorPosition)); +} + +/* TESTCASE: Tests that the HWC2 can update the cursor position of a layer. */ +TEST_F(Hwc2Test, SET_CURSOR_POSITION_update) +{ + ASSERT_NO_FATAL_FAILURE(setLayerPropertyUpdate(Hwc2TestCoverage::Complete, + ::setCursorPosition, advanceCursorPosition)); +} + +/* TESTCASE: Tests that the HWC2 can set the cursor position of a layer when the + * composition type has not been set to HWC2_COMPOSITION_CURSOR. */ +TEST_F(Hwc2Test, SET_CURSOR_POSITION_composition_type_unset) +{ + ASSERT_NO_FATAL_FAILURE(setLayerProperty(Hwc2TestCoverage::Complete, + [] (Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer, + const Hwc2TestLayer& testLayer, hwc2_error_t* outErr) { + + const hwc_rect_t cursorPosition = testLayer.getCursorPosition(); + EXPECT_NO_FATAL_FAILURE(test->setCursorPosition(display, layer, + cursorPosition.left, cursorPosition.top, outErr)); + }, + + advanceCursorPosition)); +} + +/* TESTCASE: Tests that the HWC2 cannot set the cursor position of a bad + * display. */ +TEST_F(Hwc2Test, SET_CURSOR_POSITION_bad_display) +{ + hwc2_display_t display; + hwc2_layer_t layer = 0; + int32_t x = 0, y = 0; + hwc2_error_t err = HWC2_ERROR_NONE; + + ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display)); + + ASSERT_NO_FATAL_FAILURE(setCursorPosition(display, layer, x, y, &err)); + EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code"; +} + +/* TESTCASE: Tests that the HWC2 cannot set the cursor position of a bad layer. */ +TEST_F(Hwc2Test, SET_CURSOR_POSITION_bad_layer) +{ + ASSERT_NO_FATAL_FAILURE(setLayerPropertyBadLayer(Hwc2TestCoverage::Default, + [] (Hwc2Test* test, hwc2_display_t display, hwc2_layer_t badLayer, + const Hwc2TestLayer& testLayer, hwc2_error_t* outErr) { + + const hwc_rect_t cursorPosition = testLayer.getCursorPosition(); + EXPECT_NO_FATAL_FAILURE(test->setCursorPosition(display, + badLayer, cursorPosition.left, cursorPosition.top, + outErr)); + } + )); +} + /* TESTCASE: Tests that the HWC2 can set a blend mode value of a layer. */ TEST_F(Hwc2Test, SET_LAYER_BLEND_MODE) { diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp b/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp index caf3987701..2a5a1af8bf 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp @@ -72,6 +72,12 @@ hwc2_composition_t Hwc2TestLayer::getComposition() const return mComposition.get(); } +/* The cursor position corresponds to {displayFrame.left, displayFrame.top} */ +hwc_rect_t Hwc2TestLayer::getCursorPosition() const +{ + return mDisplayFrame.get(); +} + android_dataspace_t Hwc2TestLayer::getDataspace() const { return mDataspace.get(); @@ -122,6 +128,11 @@ bool Hwc2TestLayer::advanceComposition() return mComposition.advance(); } +bool Hwc2TestLayer::advanceCursorPosition() +{ + return mDisplayFrame.advance(); +} + bool Hwc2TestLayer::advanceDataspace() { return mDataspace.advance(); diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h b/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h index f548ea6f7c..2cf2029295 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h @@ -37,6 +37,7 @@ public: hwc2_blend_mode_t getBlendMode() const; hwc_color_t getColor() const; hwc2_composition_t getComposition() const; + hwc_rect_t getCursorPosition() const; android_dataspace_t getDataspace() const; hwc_rect_t getDisplayFrame() const; float getPlaneAlpha() const; @@ -48,6 +49,7 @@ public: bool advanceBufferArea(); bool advanceColor(); bool advanceComposition(); + bool advanceCursorPosition(); bool advanceDataspace(); bool advanceDisplayFrame(); bool advancePlaneAlpha(); -- cgit v1.2.3-59-g8ed1b From ad761818a4426b4e6a0696ba90e05056aa35553c Mon Sep 17 00:00:00 2001 From: Marissa Wall Date: Thu, 15 Dec 2016 12:32:24 -0800 Subject: test-hwc2: set layer surface damage Test: Add "#define HAVE_NO_SURFACE_FLINGER" to frameworks/native/libs/gui/BufferQueueCore.cpp. Recompile and flash. Run "mm" in frameworks/native/services/surfaceflinger/tests/hwc2. Push test-hwc2 to device. Run "adb root && adb shell stop". Run test case. Ex: "./test-hwc2" Change-Id: Ie30032c7285d76d26e51b36b0cfded909f4c3480 --- services/surfaceflinger/tests/hwc2/Android.mk | 2 +- services/surfaceflinger/tests/hwc2/Hwc2Test.cpp | 52 ++++++++++ .../surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp | 12 +++ services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h | 7 +- .../tests/hwc2/Hwc2TestProperties.cpp | 112 ++++++++++++++++++++- .../surfaceflinger/tests/hwc2/Hwc2TestProperties.h | 27 +++++ 6 files changed, 208 insertions(+), 4 deletions(-) diff --git a/services/surfaceflinger/tests/hwc2/Android.mk b/services/surfaceflinger/tests/hwc2/Android.mk index 08103fc981..18437a9783 100644 --- a/services/surfaceflinger/tests/hwc2/Android.mk +++ b/services/surfaceflinger/tests/hwc2/Android.mk @@ -25,7 +25,7 @@ LOCAL_CFLAGS += \ -Wall -Wextra \ -Werror \ -fno-builtin -LOCAL_SHARED_LIBRARIES := libcutils libutils libhardware +LOCAL_SHARED_LIBRARIES := libcutils libutils libhardware liblog LOCAL_STATIC_LIBRARIES := libbase libadf libadfhwc LOCAL_SRC_FILES := \ Hwc2Test.cpp \ diff --git a/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp index 2a97a8c422..f441089f37 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp +++ b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp @@ -473,6 +473,23 @@ public: } } + void setLayerSurfaceDamage(hwc2_display_t display, hwc2_layer_t layer, + const hwc_region_t& surfaceDamage, hwc2_error_t* outErr = nullptr) + { + auto pfn = reinterpret_cast( + getFunction(HWC2_FUNCTION_SET_LAYER_SURFACE_DAMAGE)); + ASSERT_TRUE(pfn) << "failed to get function"; + + auto err = static_cast(pfn(mHwc2Device, display, layer, + surfaceDamage)); + if (outErr) { + *outErr = err; + } else { + ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set layer surface" + " damage"; + } + } + void setLayerTransform(hwc2_display_t display, hwc2_layer_t layer, hwc_transform_t transform, hwc2_error_t* outErr = nullptr) { @@ -982,6 +999,13 @@ void setSourceCrop(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer, testLayer.getSourceCrop(), outErr)); } +void setSurfaceDamage(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer, + const Hwc2TestLayer& testLayer, hwc2_error_t* outErr) +{ + EXPECT_NO_FATAL_FAILURE(test->setLayerSurfaceDamage(display, layer, + testLayer.getSurfaceDamage(), outErr)); +} + void setTransform(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer, const Hwc2TestLayer& testLayer, hwc2_error_t* outErr) { @@ -1044,6 +1068,13 @@ bool advanceSourceCrop(Hwc2TestLayer* testLayer) return testLayer->advanceBufferArea(); } +bool advanceSurfaceDamage(Hwc2TestLayer* testLayer) +{ + if (testLayer->advanceSurfaceDamage()) + return true; + return testLayer->advanceBufferArea(); +} + bool advanceTransform(Hwc2TestLayer* testLayer) { return testLayer->advanceTransform(); @@ -2123,6 +2154,27 @@ TEST_F(Hwc2Test, SET_LAYER_SOURCE_CROP_bad_layer) setSourceCrop)); } +/* TESTCASE: Tests that the HWC2 can set the surface damage of a layer. */ +TEST_F(Hwc2Test, SET_LAYER_SURFACE_DAMAGE) +{ + ASSERT_NO_FATAL_FAILURE(setLayerProperty(Hwc2TestCoverage::Complete, + setSurfaceDamage, advanceSurfaceDamage)); +} + +/* TESTCASE: Tests that the HWC2 can update the surface damage of a layer. */ +TEST_F(Hwc2Test, SET_LAYER_SURFACE_DAMAGE_update) +{ + ASSERT_NO_FATAL_FAILURE(setLayerPropertyUpdate(Hwc2TestCoverage::Complete, + setSurfaceDamage, advanceSurfaceDamage)); +} + +/* TESTCASE: Tests that the HWC2 cannot set the surface damage of a bad layer. */ +TEST_F(Hwc2Test, SET_LAYER_SURFACE_DAMAGE_bad_layer) +{ + ASSERT_NO_FATAL_FAILURE(setLayerPropertyBadLayer(Hwc2TestCoverage::Default, + setSurfaceDamage)); +} + /* TESTCASE: Tests that the HWC2 can set the transform value of a layer. */ TEST_F(Hwc2Test, SET_LAYER_TRANSFORM) { diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp b/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp index 2a5a1af8bf..01d48c4c66 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp @@ -28,10 +28,12 @@ Hwc2TestLayer::Hwc2TestLayer(Hwc2TestCoverage coverage, const Area& displayArea, mDisplayFrame(coverage, displayArea), mPlaneAlpha(coverage), mSourceCrop(coverage), + mSurfaceDamage(coverage), mTransform(coverage), mZOrder(zOrder) { mBufferArea.setDependent(&mSourceCrop); + mBufferArea.setDependent(&mSurfaceDamage); mBlendMode.setDependent(&mColor); } @@ -98,6 +100,11 @@ hwc_frect_t Hwc2TestLayer::getSourceCrop() const return mSourceCrop.get(); } +hwc_region_t Hwc2TestLayer::getSurfaceDamage() const +{ + return mSurfaceDamage.get(); +} + hwc_transform_t Hwc2TestLayer::getTransform() const { return mTransform.get(); @@ -153,6 +160,11 @@ bool Hwc2TestLayer::advanceSourceCrop() return mSourceCrop.advance(); } +bool Hwc2TestLayer::advanceSurfaceDamage() +{ + return mSurfaceDamage.advance(); +} + bool Hwc2TestLayer::advanceTransform() { return mTransform.advance(); diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h b/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h index 2cf2029295..f5b2c392a3 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h @@ -42,6 +42,7 @@ public: hwc_rect_t getDisplayFrame() const; float getPlaneAlpha() const; hwc_frect_t getSourceCrop() const; + hwc_region_t getSurfaceDamage() const; hwc_transform_t getTransform() const; uint32_t getZOrder() const; @@ -54,12 +55,13 @@ public: bool advanceDisplayFrame(); bool advancePlaneAlpha(); bool advanceSourceCrop(); + bool advanceSurfaceDamage(); bool advanceTransform(); private: - std::array mProperties = {{ + std::array mProperties = {{ &mBlendMode, &mColor, &mComposition, &mDataspace, &mDisplayFrame, - &mPlaneAlpha, &mSourceCrop, &mTransform + &mPlaneAlpha, &mSourceCrop, &mSurfaceDamage, &mTransform }}; Hwc2TestBlendMode mBlendMode; @@ -70,6 +72,7 @@ private: Hwc2TestDisplayFrame mDisplayFrame; Hwc2TestPlaneAlpha mPlaneAlpha; Hwc2TestSourceCrop mSourceCrop; + Hwc2TestSurfaceDamage mSurfaceDamage; Hwc2TestTransform mTransform; uint32_t mZOrder; diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp index 1e404409b4..8ef3d59d9e 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp @@ -15,6 +15,7 @@ */ #include +#include #include "Hwc2TestProperties.h" @@ -41,7 +42,17 @@ std::string Hwc2TestBufferArea::dump() const void Hwc2TestBufferArea::setDependent(Hwc2TestSourceCrop* sourceCrop) { mSourceCrop = sourceCrop; - updateDependents(); + if (mSourceCrop) { + mSourceCrop->updateBufferArea(get()); + } +} + +void Hwc2TestBufferArea::setDependent(Hwc2TestSurfaceDamage* surfaceDamage) +{ + mSurfaceDamage = surfaceDamage; + if (mSurfaceDamage) { + mSurfaceDamage->updateBufferArea(get()); + } } void Hwc2TestBufferArea::update() @@ -67,6 +78,8 @@ void Hwc2TestBufferArea::updateDependents() if (mSourceCrop) mSourceCrop->updateBufferArea(curr); + if (mSurfaceDamage) + mSurfaceDamage->updateBufferArea(curr); } const std::vector Hwc2TestBufferArea::mDefaultScalars = { @@ -438,6 +451,103 @@ const std::vector Hwc2TestSourceCrop::mCompleteFrectScalars = { }; +Hwc2TestSurfaceDamage::Hwc2TestSurfaceDamage(Hwc2TestCoverage coverage) + : Hwc2TestProperty(mSurfaceDamages), + mRegionScalars((coverage == Hwc2TestCoverage::Complete)? mCompleteRegionScalars: + (coverage == Hwc2TestCoverage::Basic)? mBasicRegionScalars: + mDefaultRegionScalars) +{ + update(); +} + +Hwc2TestSurfaceDamage::~Hwc2TestSurfaceDamage() +{ + freeSurfaceDamages(); +} + +std::string Hwc2TestSurfaceDamage::dump() const +{ + std::stringstream dmp; + + const hwc_region_t& curr = get(); + dmp << "\tsurface damage: region count " << curr.numRects << "\n"; + for (size_t i = 0; i < curr.numRects; i++) { + const hwc_rect_t& rect = curr.rects[i]; + dmp << "\t\trect: left " << rect.left << ", top " << rect.top + << ", right " << rect.right << ", bottom " << rect.bottom << "\n"; + } + + return dmp.str(); +} + +void Hwc2TestSurfaceDamage::updateBufferArea(const Area& bufferArea) +{ + mBufferArea = bufferArea; + update(); +} + +void Hwc2TestSurfaceDamage::update() +{ + freeSurfaceDamages(); + + if (mBufferArea.width == 0 && mBufferArea.height == 0) { + mSurfaceDamages.push_back({0, nullptr}); + return; + } + + hwc_region_t damage; + + for (const auto& regionScalar : mRegionScalars) { + damage.numRects = regionScalar.size(); + + if (damage.numRects > 0) { + hwc_rect_t* rects = new hwc_rect_t[damage.numRects]; + if (!rects) { + ALOGW("failed to allocate new hwc_rect_t array"); + continue; + } + + for (size_t i = 0; i < damage.numRects; i++) { + rects[i].left = regionScalar[i].left * mBufferArea.width; + rects[i].top = regionScalar[i].top * mBufferArea.height; + rects[i].right = regionScalar[i].right * mBufferArea.width; + rects[i].bottom = regionScalar[i].bottom * mBufferArea.height; + } + + damage.rects = static_cast(rects); + } else { + damage.rects = nullptr; + } + + mSurfaceDamages.push_back(damage); + } +} + +void Hwc2TestSurfaceDamage::freeSurfaceDamages() +{ + for (const auto& surfaceDamage : mSurfaceDamages) { + if (surfaceDamage.numRects > 0 && surfaceDamage.rects) + delete[] surfaceDamage.rects; + } + mSurfaceDamages.clear(); +} + +const std::vector> Hwc2TestSurfaceDamage::mDefaultRegionScalars = { + {{}}, +}; + +const std::vector> Hwc2TestSurfaceDamage::mBasicRegionScalars = { + {{}}, + {{0.0, 0.0, 1.0, 1.0}}, +}; + +const std::vector> Hwc2TestSurfaceDamage::mCompleteRegionScalars = { + {{}}, + {{0.0, 0.0, 1.0, 1.0}}, + {{0.0, 0.0, 0.5, 0.5}, {0.5, 0.5, 1.0, 1.0}}, +}; + + Hwc2TestTransform::Hwc2TestTransform(Hwc2TestCoverage coverage) : Hwc2TestProperty(coverage, mCompleteTransforms, mBasicTransforms, mDefaultTransforms) { } diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h index 870f1ccad3..6f3bd0f438 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h @@ -97,6 +97,7 @@ protected: class Hwc2TestSourceCrop; +class Hwc2TestSurfaceDamage; class Hwc2TestBufferArea : public Hwc2TestProperty { public: @@ -105,6 +106,7 @@ public: std::string dump() const override; void setDependent(Hwc2TestSourceCrop* sourceCrop); + void setDependent(Hwc2TestSurfaceDamage* surfaceDamage); protected: void update(); @@ -118,6 +120,7 @@ protected: Area mDisplayArea; Hwc2TestSourceCrop* mSourceCrop = nullptr; + Hwc2TestSurfaceDamage* mSurfaceDamage = nullptr; std::vector mBufferAreas; }; @@ -248,6 +251,30 @@ protected: }; +class Hwc2TestSurfaceDamage : public Hwc2TestProperty { +public: + Hwc2TestSurfaceDamage(Hwc2TestCoverage coverage); + ~Hwc2TestSurfaceDamage(); + + std::string dump() const override; + + void updateBufferArea(const Area& bufferArea); + +protected: + void update(); + void freeSurfaceDamages(); + + const std::vector> &mRegionScalars; + const static std::vector> mDefaultRegionScalars; + const static std::vector> mBasicRegionScalars; + const static std::vector> mCompleteRegionScalars; + + Area mBufferArea = {0, 0}; + + std::vector mSurfaceDamages; +}; + + class Hwc2TestTransform : public Hwc2TestProperty { public: Hwc2TestTransform(Hwc2TestCoverage coverage); -- cgit v1.2.3-59-g8ed1b From 5a240aaf0e3a1dd52be6a8d0811ec727369a210d Mon Sep 17 00:00:00 2001 From: Marissa Wall Date: Thu, 15 Dec 2016 12:34:06 -0800 Subject: test-hwc2: set layer buffer Test: Add "#define HAVE_NO_SURFACE_FLINGER" to frameworks/native/libs/gui/BufferQueueCore.cpp. Recompile and flash. Run "mm" in frameworks/native/services/surfaceflinger/tests/hwc2. Push test-hwc2 to device. Run "adb root && adb shell stop". Run test case. Ex: "./test-hwc2" Change-Id: Ie42d1fd4c2d0248c4a3ecf09a9b5871d501f6172 --- services/surfaceflinger/tests/hwc2/Android.mk | 22 +- services/surfaceflinger/tests/hwc2/Hwc2Test.cpp | 191 ++++++--- .../surfaceflinger/tests/hwc2/Hwc2TestBuffer.cpp | 452 +++++++++++++++++++++ .../surfaceflinger/tests/hwc2/Hwc2TestBuffer.h | 58 +++ .../surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp | 10 + services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h | 8 + .../tests/hwc2/Hwc2TestProperties.cpp | 17 + .../surfaceflinger/tests/hwc2/Hwc2TestProperties.h | 3 + 8 files changed, 711 insertions(+), 50 deletions(-) create mode 100644 services/surfaceflinger/tests/hwc2/Hwc2TestBuffer.cpp create mode 100644 services/surfaceflinger/tests/hwc2/Hwc2TestBuffer.h diff --git a/services/surfaceflinger/tests/hwc2/Android.mk b/services/surfaceflinger/tests/hwc2/Android.mk index 18437a9783..79c3e9271e 100644 --- a/services/surfaceflinger/tests/hwc2/Android.mk +++ b/services/surfaceflinger/tests/hwc2/Android.mk @@ -24,13 +24,27 @@ LOCAL_CFLAGS += \ -g \ -Wall -Wextra \ -Werror \ - -fno-builtin -LOCAL_SHARED_LIBRARIES := libcutils libutils libhardware liblog -LOCAL_STATIC_LIBRARIES := libbase libadf libadfhwc + -fno-builtin \ + -DEGL_EGLEXT_PROTOTYPES \ + -DGL_GLEXT_PROTOTYPES +LOCAL_SHARED_LIBRARIES := \ + libcutils \ + libutils \ + libhardware \ + libEGL \ + libGLESv2 \ + libui \ + libgui \ + liblog +LOCAL_STATIC_LIBRARIES := \ + libbase \ + libadf \ + libadfhwc LOCAL_SRC_FILES := \ Hwc2Test.cpp \ Hwc2TestProperties.cpp \ Hwc2TestLayer.cpp \ - Hwc2TestLayers.cpp + Hwc2TestLayers.cpp \ + Hwc2TestBuffer.cpp include $(BUILD_NATIVE_TEST) diff --git a/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp index f441089f37..931cfc6c32 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp +++ b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include #define HWC2_INCLUDE_STRINGIFICATION @@ -391,6 +392,23 @@ public: } } + void setLayerBuffer(hwc2_display_t display, hwc2_layer_t layer, + buffer_handle_t buffer, int32_t acquireFence, + hwc2_error_t* outErr = nullptr) + { + auto pfn = reinterpret_cast( + getFunction(HWC2_FUNCTION_SET_LAYER_BUFFER)); + ASSERT_TRUE(pfn) << "failed to get function"; + + auto err = static_cast(pfn(mHwc2Device, display, layer, + buffer, acquireFence)); + if (outErr) { + *outErr = err; + } else { + ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set layer buffer"; + } + } + void setLayerColor(hwc2_display_t display, hwc2_layer_t layer, hwc_color_t color, hwc2_error_t* outErr = nullptr) { @@ -665,19 +683,19 @@ protected: * Hwc2TestLayer to hwc2_layer_t on hwc2_display_t */ using TestLayerPropertyFunction = void (*)(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer, - const Hwc2TestLayer& testLayer, hwc2_error_t* outErr); + Hwc2TestLayer* testLayer, hwc2_error_t* outErr); /* Calls a set property function from Hwc2Test to set property values from * Hwc2TestLayers to hwc2_layer_t on hwc2_display_t */ using TestLayerPropertiesFunction = void (*)(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer, - const Hwc2TestLayers& testLayers); + Hwc2TestLayers* testLayers); /* Calls a set property function from Hwc2Test to set a bad property value * on hwc2_layer_t on hwc2_display_t */ using TestLayerPropertyBadLayerFunction = void (*)(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer, - const Hwc2TestLayer& testLayer, hwc2_error_t* outErr); + Hwc2TestLayer* testLayer, hwc2_error_t* outErr); /* Calls a set property function from Hwc2Test to set a bad property value * on hwc2_layer_t on hwc2_display_t */ @@ -711,7 +729,7 @@ protected: ASSERT_NO_FATAL_FAILURE(createLayer(display, &layer)); ASSERT_NO_FATAL_FAILURE(function(this, display, layer, - testLayer, nullptr)); + &testLayer, nullptr)); ASSERT_NO_FATAL_FAILURE(destroyLayer(display, layer)); } while (advance(&testLayer)); @@ -743,7 +761,7 @@ protected: do { ASSERT_NO_FATAL_FAILURE(function(this, display, layer, - testLayer, nullptr)); + &testLayer, nullptr)); } while (advance(&testLayer)); ASSERT_NO_FATAL_FAILURE(destroyLayer(display, layer)); @@ -776,7 +794,7 @@ protected: for (auto layer : layers) { EXPECT_NO_FATAL_FAILURE(function(this, display, layer, - testLayers)); + &testLayers)); } ASSERT_NO_FATAL_FAILURE(destroyLayers(display, std::move(layers))); @@ -810,19 +828,19 @@ protected: Hwc2TestLayer testLayer(coverage, displayArea); ASSERT_NO_FATAL_FAILURE(function(this, display, layer, - testLayer, &err)); + &testLayer, &err)); EXPECT_EQ(err, HWC2_ERROR_BAD_LAYER) << "returned wrong error code"; ASSERT_NO_FATAL_FAILURE(createLayer(display, &layer)); ASSERT_NO_FATAL_FAILURE(function(this, display, layer + 1, - testLayer, &err)); + &testLayer, &err)); EXPECT_EQ(err, HWC2_ERROR_BAD_LAYER) << "returned wrong error code"; ASSERT_NO_FATAL_FAILURE(destroyLayer(display, layer)); ASSERT_NO_FATAL_FAILURE(function(this, display, layer, - testLayer, &err)); + &testLayer, &err)); EXPECT_EQ(err, HWC2_ERROR_BAD_LAYER) << "returned wrong error code"; } } @@ -918,29 +936,50 @@ void hwc2TestVsyncCallback(hwc2_callback_data_t callbackData, } void setBlendMode(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer, - const Hwc2TestLayer& testLayer, hwc2_error_t* outErr) + Hwc2TestLayer* testLayer, hwc2_error_t* outErr) { EXPECT_NO_FATAL_FAILURE(test->setLayerBlendMode(display, layer, - testLayer.getBlendMode(), outErr)); + testLayer->getBlendMode(), outErr)); +} + +void setBuffer(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer, + Hwc2TestLayer* testLayer, hwc2_error_t* outErr) +{ + buffer_handle_t handle; + android::base::unique_fd acquireFence; + hwc2_composition_t composition = testLayer->getComposition(); + + if (composition == HWC2_COMPOSITION_CLIENT + || composition == HWC2_COMPOSITION_SOLID_COLOR + || composition == HWC2_COMPOSITION_SIDEBAND) + return; + + if (testLayer->getBuffer(&handle, &acquireFence) < 0) + return; + + ASSERT_NO_FATAL_FAILURE(test->setLayerCompositionType(display, layer, + composition)); + EXPECT_NO_FATAL_FAILURE(test->setLayerBuffer(display, layer, + handle, acquireFence, outErr)); } void setColor(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer, - const Hwc2TestLayer& testLayer, hwc2_error_t* outErr) + Hwc2TestLayer* testLayer, hwc2_error_t* outErr) { ASSERT_NO_FATAL_FAILURE(test->setLayerCompositionType(display, layer, HWC2_COMPOSITION_SOLID_COLOR)); ASSERT_NO_FATAL_FAILURE(test->setLayerPlaneAlpha(display, - layer, testLayer.getPlaneAlpha())); + layer, testLayer->getPlaneAlpha())); ASSERT_NO_FATAL_FAILURE(test->setLayerBlendMode(display, - layer, testLayer.getBlendMode())); + layer, testLayer->getBlendMode())); EXPECT_NO_FATAL_FAILURE(test->setLayerColor(display, layer, - testLayer.getColor(), outErr)); + testLayer->getColor(), outErr)); } void setComposition(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer, - const Hwc2TestLayer& testLayer, hwc2_error_t* outErr) + Hwc2TestLayer* testLayer, hwc2_error_t* outErr) { - hwc2_composition_t composition = testLayer.getComposition(); + hwc2_composition_t composition = testLayer->getComposition(); hwc2_error_t err = HWC2_ERROR_NONE; ASSERT_NO_FATAL_FAILURE(test->setLayerCompositionType(display, layer, @@ -959,65 +998,65 @@ void setComposition(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer, } void setCursorPosition(Hwc2Test* test, hwc2_display_t display, - hwc2_layer_t layer, const Hwc2TestLayer& testLayer, hwc2_error_t* outErr) + hwc2_layer_t layer, Hwc2TestLayer* testLayer, hwc2_error_t* outErr) { ASSERT_NO_FATAL_FAILURE(test->setLayerCompositionType(display, layer, HWC2_COMPOSITION_CURSOR)); - const hwc_rect_t cursorPosition = testLayer.getCursorPosition(); + const hwc_rect_t cursorPosition = testLayer->getCursorPosition(); EXPECT_NO_FATAL_FAILURE(test->setCursorPosition(display, layer, cursorPosition.left, cursorPosition.top, outErr)); } void setDataspace(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer, - const Hwc2TestLayer& testLayer, hwc2_error_t* outErr) + Hwc2TestLayer* testLayer, hwc2_error_t* outErr) { EXPECT_NO_FATAL_FAILURE(test->setLayerDataspace(display, layer, - testLayer.getDataspace(), outErr)); + testLayer->getDataspace(), outErr)); } void setDisplayFrame(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer, - const Hwc2TestLayer& testLayer, hwc2_error_t* outErr) + Hwc2TestLayer* testLayer, hwc2_error_t* outErr) { EXPECT_NO_FATAL_FAILURE(test->setLayerDisplayFrame(display, layer, - testLayer.getDisplayFrame(), outErr)); + testLayer->getDisplayFrame(), outErr)); } void setPlaneAlpha(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer, - const Hwc2TestLayer& testLayer, hwc2_error_t *outErr) + Hwc2TestLayer* testLayer, hwc2_error_t *outErr) { ASSERT_NO_FATAL_FAILURE(test->setLayerBlendMode(display, layer, - testLayer.getBlendMode())); + testLayer->getBlendMode())); EXPECT_NO_FATAL_FAILURE(test->setLayerPlaneAlpha(display, layer, - testLayer.getPlaneAlpha(), outErr)); + testLayer->getPlaneAlpha(), outErr)); } void setSourceCrop(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer, - const Hwc2TestLayer& testLayer, hwc2_error_t* outErr) + Hwc2TestLayer* testLayer, hwc2_error_t* outErr) { EXPECT_NO_FATAL_FAILURE(test->setLayerSourceCrop(display, layer, - testLayer.getSourceCrop(), outErr)); + testLayer->getSourceCrop(), outErr)); } void setSurfaceDamage(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer, - const Hwc2TestLayer& testLayer, hwc2_error_t* outErr) + Hwc2TestLayer* testLayer, hwc2_error_t* outErr) { EXPECT_NO_FATAL_FAILURE(test->setLayerSurfaceDamage(display, layer, - testLayer.getSurfaceDamage(), outErr)); + testLayer->getSurfaceDamage(), outErr)); } void setTransform(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer, - const Hwc2TestLayer& testLayer, hwc2_error_t* outErr) + Hwc2TestLayer* testLayer, hwc2_error_t* outErr) { EXPECT_NO_FATAL_FAILURE(test->setLayerTransform(display, layer, - testLayer.getTransform(), outErr)); + testLayer->getTransform(), outErr)); } void setZOrder(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer, - const Hwc2TestLayer& testLayer, hwc2_error_t* outErr) + Hwc2TestLayer* testLayer, hwc2_error_t* outErr) { EXPECT_NO_FATAL_FAILURE(test->setLayerZOrder(display, layer, - testLayer.getZOrder(), outErr)); + testLayer->getZOrder(), outErr)); } bool advanceBlendMode(Hwc2TestLayer* testLayer) @@ -1025,6 +1064,13 @@ bool advanceBlendMode(Hwc2TestLayer* testLayer) return testLayer->advanceBlendMode(); } +bool advanceBuffer(Hwc2TestLayer* testLayer) +{ + if (testLayer->advanceComposition()) + return true; + return testLayer->advanceBufferArea(); +} + bool advanceColor(Hwc2TestLayer* testLayer) { /* Color depends on blend mode so advance blend mode last so color is not @@ -1948,9 +1994,9 @@ TEST_F(Hwc2Test, SET_CURSOR_POSITION_composition_type_unset) { ASSERT_NO_FATAL_FAILURE(setLayerProperty(Hwc2TestCoverage::Complete, [] (Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer, - const Hwc2TestLayer& testLayer, hwc2_error_t* outErr) { + Hwc2TestLayer* testLayer, hwc2_error_t* outErr) { - const hwc_rect_t cursorPosition = testLayer.getCursorPosition(); + const hwc_rect_t cursorPosition = testLayer->getCursorPosition(); EXPECT_NO_FATAL_FAILURE(test->setCursorPosition(display, layer, cursorPosition.left, cursorPosition.top, outErr)); }, @@ -1978,9 +2024,9 @@ TEST_F(Hwc2Test, SET_CURSOR_POSITION_bad_layer) { ASSERT_NO_FATAL_FAILURE(setLayerPropertyBadLayer(Hwc2TestCoverage::Default, [] (Hwc2Test* test, hwc2_display_t display, hwc2_layer_t badLayer, - const Hwc2TestLayer& testLayer, hwc2_error_t* outErr) { + Hwc2TestLayer* testLayer, hwc2_error_t* outErr) { - const hwc_rect_t cursorPosition = testLayer.getCursorPosition(); + const hwc_rect_t cursorPosition = testLayer->getCursorPosition(); EXPECT_NO_FATAL_FAILURE(test->setCursorPosition(display, badLayer, cursorPosition.left, cursorPosition.top, outErr)); @@ -2022,6 +2068,59 @@ TEST_F(Hwc2Test, SET_LAYER_BLEND_MODE_bad_parameter) )); } +/* TESTCASE: Tests that the HWC2 can set the buffer of a layer. */ +TEST_F(Hwc2Test, SET_LAYER_BUFFER) +{ + ASSERT_NO_FATAL_FAILURE(setLayerProperty(Hwc2TestCoverage::Complete, + setBuffer, advanceBuffer)); +} + +/* TESTCASE: Tests that the HWC2 can update the buffer of a layer. */ +TEST_F(Hwc2Test, SET_LAYER_BUFFER_update) +{ + ASSERT_NO_FATAL_FAILURE(setLayerPropertyUpdate(Hwc2TestCoverage::Complete, + setBuffer, advanceBuffer)); +} + +/* TESTCASE: Tests that the HWC2 cannot set the buffer of a bad layer. */ +TEST_F(Hwc2Test, SET_LAYER_BUFFER_bad_layer) +{ + ASSERT_NO_FATAL_FAILURE(setLayerPropertyBadLayer(Hwc2TestCoverage::Default, + [] (Hwc2Test* test, hwc2_display_t display, hwc2_layer_t badLayer, + Hwc2TestLayer* testLayer, hwc2_error_t* outErr) { + + buffer_handle_t handle = nullptr; + android::base::unique_fd acquireFence; + + /* If there is not available buffer for the given buffer + * properties, it should not fail this test case */ + if (testLayer->getBuffer(&handle, &acquireFence) == 0) { + *outErr = HWC2_ERROR_BAD_LAYER; + return; + } + + ASSERT_NO_FATAL_FAILURE(test->setLayerBuffer(display, badLayer, + handle, acquireFence, outErr)); + } + )); +} + +/* TESTCASE: Tests that the HWC2 can set an invalid buffer for a layer. */ +TEST_F(Hwc2Test, SET_LAYER_BUFFER_bad_parameter) +{ + ASSERT_NO_FATAL_FAILURE(setLayerPropertyBadParameter( + [] (Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer, + hwc2_error_t* outErr) { + + buffer_handle_t handle = nullptr; + int32_t acquireFence = -1; + + ASSERT_NO_FATAL_FAILURE(test->setLayerBuffer(display, layer, + handle, acquireFence, outErr)); + } + )); +} + /* TESTCASE: Tests that the HWC2 can set the color of a layer. */ TEST_F(Hwc2Test, SET_LAYER_COLOR) { @@ -2042,10 +2141,10 @@ TEST_F(Hwc2Test, SET_LAYER_COLOR_composition_type_unset) { ASSERT_NO_FATAL_FAILURE(setLayerProperty(Hwc2TestCoverage::Basic, [] (Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer, - const Hwc2TestLayer& testLayer, hwc2_error_t* outErr) { + Hwc2TestLayer* testLayer, hwc2_error_t* outErr) { EXPECT_NO_FATAL_FAILURE(test->setLayerColor(display, layer, - testLayer.getColor(), outErr)); + testLayer->getColor(), outErr)); }, advanceColor)); @@ -2056,10 +2155,10 @@ TEST_F(Hwc2Test, SET_LAYER_COLOR_bad_layer) { ASSERT_NO_FATAL_FAILURE(setLayerPropertyBadLayer(Hwc2TestCoverage::Default, [] (Hwc2Test* test, hwc2_display_t display, hwc2_layer_t badLayer, - const Hwc2TestLayer& testLayer, hwc2_error_t* outErr) { + Hwc2TestLayer* testLayer, hwc2_error_t* outErr) { EXPECT_NO_FATAL_FAILURE(test->setLayerColor(display, badLayer, - testLayer.getColor(), outErr)); + testLayer->getColor(), outErr)); } )); } @@ -2125,10 +2224,10 @@ TEST_F(Hwc2Test, SET_LAYER_PLANE_ALPHA_bad_layer) { ASSERT_NO_FATAL_FAILURE(setLayerPropertyBadLayer(Hwc2TestCoverage::Default, [] (Hwc2Test* test, hwc2_display_t display, hwc2_layer_t badLayer, - const Hwc2TestLayer& testLayer, hwc2_error_t *outErr) { + Hwc2TestLayer* testLayer, hwc2_error_t *outErr) { EXPECT_NO_FATAL_FAILURE(test->setLayerPlaneAlpha(display, - badLayer, testLayer.getPlaneAlpha(), outErr)); + badLayer, testLayer->getPlaneAlpha(), outErr)); } )); } @@ -2201,10 +2300,10 @@ TEST_F(Hwc2Test, SET_LAYER_Z_ORDER) { ASSERT_NO_FATAL_FAILURE(setLayerProperties(Hwc2TestCoverage::Complete, 10, [] (Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer, - const Hwc2TestLayers& testLayers) { + Hwc2TestLayers* testLayers) { EXPECT_NO_FATAL_FAILURE(test->setLayerZOrder(display, layer, - testLayers.getZOrder(layer))); + testLayers->getZOrder(layer))); } )); } diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestBuffer.cpp b/services/surfaceflinger/tests/hwc2/Hwc2TestBuffer.cpp new file mode 100644 index 0000000000..c9d8f4fdb7 --- /dev/null +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestBuffer.cpp @@ -0,0 +1,452 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include + +#include "Hwc2TestBuffer.h" +#include "Hwc2TestLayers.h" + +using namespace android; + +/* Returns a fence from egl */ +typedef void (*FenceCallback)(int32_t fence, void* callbackArgs); + +/* Returns fence to fence generator */ +static void setFence(int32_t fence, void* fenceGenerator); + + +/* Used to receive the surfaces and fences from egl. The egl buffers are thrown + * away. The fences are sent to the requester via a callback */ +class Hwc2TestSurfaceManager { +public: + /* Listens for a new frame, detaches the buffer and returns the fence + * through saved callback. */ + class BufferListener : public ConsumerBase::FrameAvailableListener { + public: + BufferListener(sp consumer, + FenceCallback callback, void* callbackArgs) + : mConsumer(consumer), + mCallback(callback), + mCallbackArgs(callbackArgs) { } + + void onFrameAvailable(const BufferItem& /*item*/) + { + BufferItem item; + + if (mConsumer->acquireBuffer(&item, 0)) + return; + if (mConsumer->detachBuffer(item.mSlot)) + return; + + mCallback(item.mFence->dup(), mCallbackArgs); + } + + private: + sp mConsumer; + FenceCallback mCallback; + void* mCallbackArgs; + }; + + /* Creates a buffer listener that waits on a new frame from the buffer + * queue. */ + void initialize(const Area& bufferArea, android_pixel_format_t format, + FenceCallback callback, void* callbackArgs) + { + sp producer; + sp consumer; + BufferQueue::createBufferQueue(&producer, &consumer); + + consumer->setDefaultBufferSize(bufferArea.width, bufferArea.height); + consumer->setDefaultBufferFormat(format); + + mBufferItemConsumer = new BufferItemConsumer(consumer, 0); + + mListener = new BufferListener(consumer, callback, callbackArgs); + mBufferItemConsumer->setFrameAvailableListener(mListener); + + mSurface = new Surface(producer, true); + } + + /* Used by Egl manager. The surface is never displayed. */ + sp getSurface() const + { + return mSurface; + } + +private: + sp mBufferItemConsumer; + sp mListener; + /* Used by Egl manager. The surface is never displayed */ + sp mSurface; +}; + + +/* Used to generate valid fences. It is not possible to create a dummy sync + * fence for testing. Egl can generate buffers along with a valid fence. + * The buffer cannot be guaranteed to be the same format across all devices so + * a CPU filled buffer is used instead. The Egl fence is used along with the + * CPU filled buffer. */ +class Hwc2TestEglManager { +public: + Hwc2TestEglManager() + : mEglDisplay(EGL_NO_DISPLAY), + mEglSurface(EGL_NO_SURFACE), + mEglContext(EGL_NO_CONTEXT) { } + + ~Hwc2TestEglManager() + { + cleanup(); + } + + int initialize(sp surface) + { + mSurface = surface; + + mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); + if (mEglDisplay == EGL_NO_DISPLAY) return false; + + EGLint major; + EGLint minor; + if (!eglInitialize(mEglDisplay, &major, &minor)) { + ALOGW("Could not initialize EGL"); + return false; + } + + /* We're going to use a 1x1 pbuffer surface later on + * The configuration distance doesn't really matter for what we're + * trying to do */ + EGLint configAttrs[] = { + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, + EGL_RED_SIZE, 8, + EGL_GREEN_SIZE, 8, + EGL_BLUE_SIZE, 8, + EGL_ALPHA_SIZE, 0, + EGL_DEPTH_SIZE, 24, + EGL_STENCIL_SIZE, 0, + EGL_NONE + }; + + EGLConfig configs[1]; + EGLint configCnt; + if (!eglChooseConfig(mEglDisplay, configAttrs, configs, 1, + &configCnt)) { + ALOGW("Could not select EGL configuration"); + eglReleaseThread(); + eglTerminate(mEglDisplay); + return false; + } + + if (configCnt <= 0) { + ALOGW("Could not find EGL configuration"); + eglReleaseThread(); + eglTerminate(mEglDisplay); + return false; + } + + /* These objects are initialized below but the default "null" values are + * used to cleanup properly at any point in the initialization sequence */ + EGLint attrs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; + mEglContext = eglCreateContext(mEglDisplay, configs[0], EGL_NO_CONTEXT, + attrs); + if (mEglContext == EGL_NO_CONTEXT) { + ALOGW("Could not create EGL context"); + cleanup(); + return false; + } + + EGLint surfaceAttrs[] = { EGL_NONE }; + mEglSurface = eglCreateWindowSurface(mEglDisplay, configs[0], + mSurface.get(), surfaceAttrs); + if (mEglSurface == EGL_NO_SURFACE) { + ALOGW("Could not create EGL surface"); + cleanup(); + return false; + } + + if (!eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) { + ALOGW("Could not change current EGL context"); + cleanup(); + return false; + } + + return true; + } + + void makeCurrent() const + { + eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext); + } + + void present() const + { + eglSwapBuffers(mEglDisplay, mEglSurface); + } + +private: + void cleanup() + { + if (mEglDisplay == EGL_NO_DISPLAY) + return; + if (mEglSurface != EGL_NO_SURFACE) + eglDestroySurface(mEglDisplay, mEglSurface); + if (mEglContext != EGL_NO_CONTEXT) + eglDestroyContext(mEglDisplay, mEglContext); + + eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, + EGL_NO_CONTEXT); + eglReleaseThread(); + eglTerminate(mEglDisplay); + } + + sp mSurface; + EGLDisplay mEglDisplay; + EGLSurface mEglSurface; + EGLContext mEglContext; +}; + + +static const std::array triangles = {{ + { 1.0f, 1.0f }, + { -1.0f, 1.0f }, + { 1.0f, -1.0f }, + { -1.0f, -1.0f }, +}}; + +class Hwc2TestFenceGenerator { +public: + + Hwc2TestFenceGenerator() + { + mSurfaceManager.initialize({1, 1}, HAL_PIXEL_FORMAT_RGBA_8888, + setFence, this); + + if (!mEglManager.initialize(mSurfaceManager.getSurface())) + return; + + mEglManager.makeCurrent(); + + glClearColor(0.0, 0.0, 0.0, 1.0); + glEnableVertexAttribArray(0); + } + + ~Hwc2TestFenceGenerator() + { + if (mFence >= 0) + close(mFence); + mFence = -1; + + mEglManager.makeCurrent(); + } + + /* It is not possible to simply generate a fence. The easiest way is to + * generate a buffer using egl and use the associated fence. The buffer + * cannot be guaranteed to be a certain format across all devices using this + * method. Instead the buffer is generated using the CPU */ + int32_t get() + { + if (mFence >= 0) { + return dup(mFence); + } + + std::unique_lock lock(mMutex); + + /* If the pending is still set to false and times out, we cannot recover. + * Set an error and return */ + while (mPending != false) { + if (mCv.wait_for(lock, std::chrono::seconds(2)) == std::cv_status::timeout) + return -ETIME; + } + + /* Generate a fence. The fence will be returned through the setFence + * callback */ + mEglManager.makeCurrent(); + + glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, triangles.data()); + glClear(GL_COLOR_BUFFER_BIT); + + mEglManager.present(); + + /* Wait for the setFence callback */ + while (mPending != true) { + if (mCv.wait_for(lock, std::chrono::seconds(2)) == std::cv_status::timeout) + return -ETIME; + } + + mPending = false; + + return dup(mFence); + } + + /* Callback that sets the fence */ + void set(int32_t fence) + { + mFence = fence; + mPending = true; + + mCv.notify_all(); + } + +private: + + Hwc2TestSurfaceManager mSurfaceManager; + Hwc2TestEglManager mEglManager; + + std::mutex mMutex; + std::condition_variable mCv; + + int32_t mFence = -1; + bool mPending = false; +}; + + +static void setFence(int32_t fence, void* fenceGenerator) +{ + static_cast(fenceGenerator)->set(fence); +} + + +Hwc2TestBuffer::Hwc2TestBuffer() + : mFenceGenerator(new Hwc2TestFenceGenerator()) { } + +Hwc2TestBuffer::~Hwc2TestBuffer() = default; + +/* When the buffer changes sizes, save the new size and invalidate the current + * buffer */ +void Hwc2TestBuffer::updateBufferArea(const Area& bufferArea) +{ + if (mBufferArea.width == bufferArea.width + && mBufferArea.height == bufferArea.height) + return; + + mBufferArea.width = bufferArea.width; + mBufferArea.height = bufferArea.height; + + mValidBuffer = false; +} + +/* Returns a valid buffer handle and fence. The handle is filled using the CPU + * to ensure the correct format across all devices. The fence is created using + * egl. */ +int Hwc2TestBuffer::get(buffer_handle_t* outHandle, int32_t* outFence) +{ + if (mBufferArea.width == -1 || mBufferArea.height == -1) + return -EINVAL; + + /* If the current buffer is valid, the previous buffer can be reused. + * Otherwise, create new buffer */ + if (!mValidBuffer) { + int ret = generateBuffer(); + if (ret) + return ret; + } + + *outFence = mFenceGenerator->get(); + *outHandle = mHandle; + + mValidBuffer = true; + + return 0; +} + +/* CPU fills a buffer to guarantee the correct buffer format across all + * devices */ +int Hwc2TestBuffer::generateBuffer() +{ + int ret; + + /* Create new graphic buffer with correct dimensions */ + mGraphicBuffer = mGraphicBufferAlloc.createGraphicBuffer( + mBufferArea.width, mBufferArea.height, mFormat, + GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_HW_RENDER, + "hwc2_test_buffer", &ret); + if (ret) + return ret; + + /* Locks the buffer for writing */ + uint8_t* img; + mGraphicBuffer->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img)); + + uint32_t stride = mGraphicBuffer->getStride(); + + /* Iterate from the top row of the buffer to the bottom row */ + for (int32_t y = 0; y < mBufferArea.height; y++) { + + /* Will be used as R, G and B values for pixel colors */ + uint8_t max = 255; + uint8_t min = 0; + + /* Divide the rows into 3 sections. The first section will contain + * the lighest colors. The last section will contain the darkest + * colors. */ + if (y < mBufferArea.height * 1.0 / 3.0) { + min = 255 / 2; + } else if (y >= mBufferArea.height * 2.0 / 3.0) { + max = 255 / 2; + } + + /* Divide the columns into 3 sections. The first section is red, + * the second is green and the third is blue */ + int32_t x = 0; + for (; x < mBufferArea.width / 3; x++) { + setColor(x, y, mFormat, stride, img, max, min, min, 255); + } + + for (; x < mBufferArea.width * 2 / 3; x++) { + setColor(x, y, mFormat, stride, img, min, max, min, 255); + } + + for (; x < mBufferArea.width; x++) { + setColor(x, y, mFormat, stride, img, min, min, max, 255); + } + } + + /* Unlock the buffer for reading */ + mGraphicBuffer->unlock(); + + mHandle = mGraphicBuffer->handle; + + return 0; +} + +/* Sets the pixel of a buffer given the location, format, stride and color. + * Currently only supports RGBA_8888 */ +void Hwc2TestBuffer::setColor(int32_t x, int32_t y, + android_pixel_format_t format, uint32_t stride, uint8_t* img, uint8_t r, + uint8_t g, uint8_t b, uint8_t a) +{ + switch (format) { + case HAL_PIXEL_FORMAT_RGBA_8888: + img[(y * stride + x) * 4 + 0] = r; + img[(y * stride + x) * 4 + 1] = g; + img[(y * stride + x) * 4 + 2] = b; + img[(y * stride + x) * 4 + 3] = a; + break; + default: + break; + } +} diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestBuffer.h b/services/surfaceflinger/tests/hwc2/Hwc2TestBuffer.h new file mode 100644 index 0000000000..721540fa42 --- /dev/null +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestBuffer.h @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _HWC2_TEST_BUFFER_H +#define _HWC2_TEST_BUFFER_H + +#include +#include + +#include +#include + +#include "Hwc2TestProperties.h" + +class Hwc2TestFenceGenerator; + +class Hwc2TestBuffer { +public: + Hwc2TestBuffer(); + ~Hwc2TestBuffer(); + + void updateBufferArea(const Area& bufferArea); + + int get(buffer_handle_t* outHandle, int32_t* outFence); + +protected: + int generateBuffer(); + + void setColor(int32_t x, int32_t y, android_pixel_format_t format, + uint32_t stride, uint8_t* img, uint8_t r, uint8_t g, uint8_t b, + uint8_t a); + + android::GraphicBufferAlloc mGraphicBufferAlloc; + android::sp mGraphicBuffer; + + std::unique_ptr mFenceGenerator; + + Area mBufferArea = {-1, -1}; + const android_pixel_format_t mFormat = HAL_PIXEL_FORMAT_RGBA_8888; + + bool mValidBuffer = false; + buffer_handle_t mHandle = nullptr; +}; + +#endif /* ifndef _HWC2_TEST_BUFFER_H */ diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp b/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp index 01d48c4c66..fcf5768ff0 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp @@ -32,6 +32,7 @@ Hwc2TestLayer::Hwc2TestLayer(Hwc2TestCoverage coverage, const Area& displayArea, mTransform(coverage), mZOrder(zOrder) { + mBufferArea.setDependent(&mBuffer); mBufferArea.setDependent(&mSourceCrop); mBufferArea.setDependent(&mSurfaceDamage); mBlendMode.setDependent(&mColor); @@ -52,6 +53,15 @@ std::string Hwc2TestLayer::dump() const return dmp.str(); } +int Hwc2TestLayer::getBuffer(buffer_handle_t* outHandle, + android::base::unique_fd* outAcquireFence) +{ + int32_t acquireFence; + int ret = mBuffer.get(outHandle, &acquireFence); + outAcquireFence->reset(acquireFence); + return ret; +} + void Hwc2TestLayer::reset() { for (auto property : mProperties) { diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h b/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h index f5b2c392a3..27885abefb 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h @@ -17,6 +17,9 @@ #ifndef _HWC2_TEST_LAYER_H #define _HWC2_TEST_LAYER_H +#include + +#include "Hwc2TestBuffer.h" #include "Hwc2TestProperties.h" #define HWC2_INCLUDE_STRINGIFICATION @@ -32,6 +35,9 @@ public: std::string dump() const; + int getBuffer(buffer_handle_t* outHandle, + android::base::unique_fd* outAcquireFence); + void reset(); hwc2_blend_mode_t getBlendMode() const; @@ -64,6 +70,8 @@ private: &mPlaneAlpha, &mSourceCrop, &mSurfaceDamage, &mTransform }}; + Hwc2TestBuffer mBuffer; + Hwc2TestBlendMode mBlendMode; Hwc2TestBufferArea mBufferArea; Hwc2TestColor mColor; diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp index 8ef3d59d9e..bfd076ffd1 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp @@ -17,6 +17,13 @@ #include #include +#define HWC2_INCLUDE_STRINGIFICATION +#define HWC2_USE_CPP11 +#include +#undef HWC2_INCLUDE_STRINGIFICATION +#undef HWC2_USE_CPP11 + +#include "Hwc2TestBuffer.h" #include "Hwc2TestProperties.h" Hwc2TestBufferArea::Hwc2TestBufferArea(Hwc2TestCoverage coverage, @@ -39,6 +46,14 @@ std::string Hwc2TestBufferArea::dump() const return dmp.str(); } +void Hwc2TestBufferArea::setDependent(Hwc2TestBuffer* buffer) +{ + mBuffer = buffer; + if (buffer) { + buffer->updateBufferArea(get()); + } +} + void Hwc2TestBufferArea::setDependent(Hwc2TestSourceCrop* sourceCrop) { mSourceCrop = sourceCrop; @@ -76,6 +91,8 @@ void Hwc2TestBufferArea::updateDependents() { const Area& curr = get(); + if (mBuffer) + mBuffer->updateBufferArea(curr); if (mSourceCrop) mSourceCrop->updateBufferArea(curr); if (mSurfaceDamage) diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h index 6f3bd0f438..048d6e95bc 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h @@ -96,6 +96,7 @@ protected: }; +class Hwc2TestBuffer; class Hwc2TestSourceCrop; class Hwc2TestSurfaceDamage; @@ -105,6 +106,7 @@ public: std::string dump() const override; + void setDependent(Hwc2TestBuffer* buffer); void setDependent(Hwc2TestSourceCrop* sourceCrop); void setDependent(Hwc2TestSurfaceDamage* surfaceDamage); @@ -119,6 +121,7 @@ protected: Area mDisplayArea; + Hwc2TestBuffer* mBuffer = nullptr; Hwc2TestSourceCrop* mSourceCrop = nullptr; Hwc2TestSurfaceDamage* mSurfaceDamage = nullptr; -- cgit v1.2.3-59-g8ed1b From f7618ed1b4d806e06c872c0fccce57163cf93b6a Mon Sep 17 00:00:00 2001 From: Marissa Wall Date: Thu, 15 Dec 2016 12:34:39 -0800 Subject: test-hwc2: set layer visible region Test: Add "#define HAVE_NO_SURFACE_FLINGER" to frameworks/native/libs/gui/BufferQueueCore.cpp. Recompile and flash. Run "mm" in frameworks/native/services/surfaceflinger/tests/hwc2. Push test-hwc2 to device. Run "adb root && adb shell stop". Run test case. Ex: "./test-hwc2" Change-Id: I0e620fa6763d258d7875da9bf85d41c182e015d2 --- services/surfaceflinger/tests/hwc2/Hwc2Test.cpp | 72 ++++++++++++++++++++-- .../surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp | 36 +++++++++-- services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h | 18 ++++-- .../surfaceflinger/tests/hwc2/Hwc2TestLayers.cpp | 65 ++++++++++++++++++- .../surfaceflinger/tests/hwc2/Hwc2TestLayers.h | 7 ++- .../tests/hwc2/Hwc2TestProperties.cpp | 57 +++++++++++++++++ .../surfaceflinger/tests/hwc2/Hwc2TestProperties.h | 17 +++++ 7 files changed, 253 insertions(+), 19 deletions(-) diff --git a/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp index 931cfc6c32..024ba77795 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp +++ b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp @@ -525,6 +525,23 @@ public: } } + void setLayerVisibleRegion(hwc2_display_t display, hwc2_layer_t layer, + const hwc_region_t& visibleRegion, hwc2_error_t* outErr = nullptr) + { + auto pfn = reinterpret_cast( + getFunction(HWC2_FUNCTION_SET_LAYER_VISIBLE_REGION)); + ASSERT_TRUE(pfn) << "failed to get function"; + + auto err = static_cast(pfn(mHwc2Device, display, layer, + visibleRegion)); + if (outErr) { + *outErr = err; + } else { + ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set layer visible" + " region"; + } + } + void setLayerZOrder(hwc2_display_t display, hwc2_layer_t layer, uint32_t zOrder, hwc2_error_t* outErr = nullptr) { @@ -705,6 +722,9 @@ protected: /* Advances a property of Hwc2TestLayer */ using AdvanceProperty = bool (*)(Hwc2TestLayer* testLayer); + /* Advances properties of Hwc2TestLayers */ + using AdvanceProperties = bool (*)(Hwc2TestLayers* testLayer); + /* For each active display it cycles through each display config and tests * each property value. It creates a layer, sets the property and then * destroys the layer */ @@ -774,7 +794,7 @@ protected: * TestLayerPropertiesFunction to set property values and then * destroys the layers */ void setLayerProperties(Hwc2TestCoverage coverage, size_t layerCnt, - TestLayerPropertiesFunction function) + TestLayerPropertiesFunction function, AdvanceProperties advance) { for (auto display : mDisplays) { std::vector configs; @@ -792,10 +812,12 @@ protected: ASSERT_NO_FATAL_FAILURE(createLayers(display, &layers, layerCnt)); Hwc2TestLayers testLayers(layers, coverage, displayArea); - for (auto layer : layers) { - EXPECT_NO_FATAL_FAILURE(function(this, display, layer, - &testLayers)); - } + do { + for (auto layer : layers) { + EXPECT_NO_FATAL_FAILURE(function(this, display, layer, + &testLayers)); + } + } while (advance(&testLayers)); ASSERT_NO_FATAL_FAILURE(destroyLayers(display, std::move(layers))); } @@ -1052,6 +1074,13 @@ void setTransform(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer, testLayer->getTransform(), outErr)); } +void setVisibleRegion(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer, + Hwc2TestLayer* testLayer, hwc2_error_t* outErr) +{ + EXPECT_NO_FATAL_FAILURE(test->setLayerVisibleRegion(display, layer, + testLayer->getVisibleRegion(), outErr)); +} + void setZOrder(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer, Hwc2TestLayer* testLayer, hwc2_error_t* outErr) { @@ -1126,6 +1155,11 @@ bool advanceTransform(Hwc2TestLayer* testLayer) return testLayer->advanceTransform(); } +bool advanceVisibleRegions(Hwc2TestLayers* testLayers) +{ + return testLayers->advanceVisibleRegions(); +} + static const std::array requiredFunctions = {{ HWC2_FUNCTION_ACCEPT_DISPLAY_CHANGES, @@ -2295,6 +2329,27 @@ TEST_F(Hwc2Test, SET_LAYER_TRANSFORM_bad_layer) setTransform)); } +/* TESTCASE: Tests that the HWC2 can set the visible region of a layer. */ +TEST_F(Hwc2Test, SET_LAYER_VISIBLE_REGION) +{ + ASSERT_NO_FATAL_FAILURE(setLayerProperties(Hwc2TestCoverage::Basic, 5, + [] (Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer, + Hwc2TestLayers* testLayers) { + + EXPECT_NO_FATAL_FAILURE(test->setLayerVisibleRegion(display, + layer, testLayers->getVisibleRegion(layer))); + }, + + advanceVisibleRegions)); +} + +/* TESTCASE: Tests that the HWC2 cannot set the visible region of a bad layer. */ +TEST_F(Hwc2Test, SET_LAYER_VISIBLE_REGION_bad_layer) +{ + ASSERT_NO_FATAL_FAILURE(setLayerPropertyBadLayer(Hwc2TestCoverage::Default, + setVisibleRegion)); +} + /* TESTCASE: Tests that the HWC2 can set the z order of a layer. */ TEST_F(Hwc2Test, SET_LAYER_Z_ORDER) { @@ -2304,6 +2359,13 @@ TEST_F(Hwc2Test, SET_LAYER_Z_ORDER) EXPECT_NO_FATAL_FAILURE(test->setLayerZOrder(display, layer, testLayers->getZOrder(layer))); + }, + + /* TestLayer z orders are set during the construction of TestLayers + * and cannot be updated. There is no need (or ability) to cycle + * through additional z order configurations. */ + [] (Hwc2TestLayers* /*testLayers*/) { + return false; } )); } diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp b/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp index fcf5768ff0..f9c5aa0dc0 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp @@ -18,8 +18,7 @@ #include "Hwc2TestLayer.h" -Hwc2TestLayer::Hwc2TestLayer(Hwc2TestCoverage coverage, const Area& displayArea, - uint32_t zOrder) +Hwc2TestLayer::Hwc2TestLayer(Hwc2TestCoverage coverage, const Area& displayArea) : mBlendMode(coverage), mBufferArea(coverage, displayArea), mColor(coverage), @@ -29,8 +28,7 @@ Hwc2TestLayer::Hwc2TestLayer(Hwc2TestCoverage coverage, const Area& displayArea, mPlaneAlpha(coverage), mSourceCrop(coverage), mSurfaceDamage(coverage), - mTransform(coverage), - mZOrder(zOrder) + mTransform(coverage) { mBufferArea.setDependent(&mBuffer); mBufferArea.setDependent(&mSourceCrop); @@ -48,6 +46,7 @@ std::string Hwc2TestLayer::dump() const dmp << property->dump(); } + dmp << mVisibleRegion.dump(); dmp << "\tz order: " << mZOrder << "\n"; return dmp.str(); @@ -62,8 +61,20 @@ int Hwc2TestLayer::getBuffer(buffer_handle_t* outHandle, return ret; } +void Hwc2TestLayer::setZOrder(uint32_t zOrder) +{ + mZOrder = zOrder; +} + +void Hwc2TestLayer::setVisibleRegion(const android::Region& region) +{ + return mVisibleRegion.set(region); +} + void Hwc2TestLayer::reset() { + mVisibleRegion.release(); + for (auto property : mProperties) { property->reset(); } @@ -74,6 +85,11 @@ hwc2_blend_mode_t Hwc2TestLayer::getBlendMode() const return mBlendMode.get(); } +Area Hwc2TestLayer::getBufferArea() const +{ + return mBufferArea.get(); +} + hwc_color_t Hwc2TestLayer::getColor() const { return mColor.get(); @@ -120,6 +136,11 @@ hwc_transform_t Hwc2TestLayer::getTransform() const return mTransform.get(); } +hwc_region_t Hwc2TestLayer::getVisibleRegion() const +{ + return mVisibleRegion.get(); +} + uint32_t Hwc2TestLayer::getZOrder() const { return mZOrder; @@ -179,3 +200,10 @@ bool Hwc2TestLayer::advanceTransform() { return mTransform.advance(); } + +bool Hwc2TestLayer::advanceVisibleRegion() +{ + if (mPlaneAlpha.advance()) + return true; + return mDisplayFrame.advance(); +} diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h b/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h index 27885abefb..86c36496c7 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h @@ -30,17 +30,20 @@ class Hwc2TestLayer { public: - Hwc2TestLayer(Hwc2TestCoverage coverage, const Area& displayArea, - uint32_t zOrder = 0); + Hwc2TestLayer(Hwc2TestCoverage coverage, const Area& displayArea); std::string dump() const; int getBuffer(buffer_handle_t* outHandle, android::base::unique_fd* outAcquireFence); + void setZOrder(uint32_t zOrder); + void setVisibleRegion(const android::Region& region); + void reset(); hwc2_blend_mode_t getBlendMode() const; + Area getBufferArea() const; hwc_color_t getColor() const; hwc2_composition_t getComposition() const; hwc_rect_t getCursorPosition() const; @@ -50,6 +53,7 @@ public: hwc_frect_t getSourceCrop() const; hwc_region_t getSurfaceDamage() const; hwc_transform_t getTransform() const; + hwc_region_t getVisibleRegion() const; uint32_t getZOrder() const; bool advanceBlendMode(); @@ -63,11 +67,12 @@ public: bool advanceSourceCrop(); bool advanceSurfaceDamage(); bool advanceTransform(); + bool advanceVisibleRegion(); private: - std::array mProperties = {{ - &mBlendMode, &mColor, &mComposition, &mDataspace, &mDisplayFrame, - &mPlaneAlpha, &mSourceCrop, &mSurfaceDamage, &mTransform + std::array mProperties = {{ + &mBlendMode, &mBufferArea, &mColor, &mComposition, &mDataspace, + &mDisplayFrame, &mPlaneAlpha, &mSourceCrop, &mSurfaceDamage, &mTransform }}; Hwc2TestBuffer mBuffer; @@ -82,8 +87,9 @@ private: Hwc2TestSourceCrop mSourceCrop; Hwc2TestSurfaceDamage mSurfaceDamage; Hwc2TestTransform mTransform; + Hwc2TestVisibleRegion mVisibleRegion; - uint32_t mZOrder; + uint32_t mZOrder = UINT32_MAX; }; #endif /* ifndef _HWC2_TEST_LAYER_H */ diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.cpp b/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.cpp index 02a9df1d47..15a5f77a04 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.cpp +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.cpp @@ -21,13 +21,22 @@ Hwc2TestLayers::Hwc2TestLayers(const std::vector& layers, Hwc2TestCoverage coverage, const Area& displayArea) { - uint32_t nextZOrder = 0; - for (auto layer : layers) { mTestLayers.emplace(std::piecewise_construct, std::forward_as_tuple(layer), - std::forward_as_tuple(coverage, displayArea, nextZOrder++)); + std::forward_as_tuple(coverage, displayArea)); + } + + /* Iterate over the layers in order and assign z orders in the same order. + * This allows us to iterate over z orders in the same way when computing + * visible regions */ + uint32_t nextZOrder = layers.size(); + + for (auto& testLayer : mTestLayers) { + testLayer.second.setZOrder(nextZOrder--); } + + setVisibleRegions(); } std::string Hwc2TestLayers::dump() const @@ -44,6 +53,28 @@ void Hwc2TestLayers::reset() for (auto& testLayer : mTestLayers) { testLayer.second.reset(); } + + setVisibleRegions(); +} + +bool Hwc2TestLayers::advanceVisibleRegions() +{ + for (auto& testLayer : mTestLayers) { + if (testLayer.second.advanceVisibleRegion()) { + setVisibleRegions(); + return true; + } + testLayer.second.reset(); + } + return false; +} + +hwc_region_t Hwc2TestLayers::getVisibleRegion(hwc2_layer_t layer) const +{ + if (mTestLayers.count(layer) == 0) { + []() { GTEST_FAIL(); }(); + } + return mTestLayers.at(layer).getVisibleRegion(); } uint32_t Hwc2TestLayers::getZOrder(hwc2_layer_t layer) const @@ -53,3 +84,31 @@ uint32_t Hwc2TestLayers::getZOrder(hwc2_layer_t layer) const } return mTestLayers.at(layer).getZOrder(); } + +void Hwc2TestLayers::setVisibleRegions() +{ + /* The region of the display that is covered by layers above the current + * layer */ + android::Region aboveOpaqueLayers; + + /* Iterate over test layers from max z order to min z order. */ + for (auto& testLayer : mTestLayers) { + android::Region visibleRegion; + + /* Set the visible region of this layer */ + const hwc_rect_t displayFrame = testLayer.second.getDisplayFrame(); + + visibleRegion.set(android::Rect(displayFrame.left, displayFrame.top, + displayFrame.right, displayFrame.bottom)); + + /* Remove the area covered by opaque layers above this layer + * from this layer's visible region */ + visibleRegion.subtractSelf(aboveOpaqueLayers); + + testLayer.second.setVisibleRegion(visibleRegion); + + /* If this layer is opaque, store the region it covers */ + if (testLayer.second.getPlaneAlpha() == 1.0f) + aboveOpaqueLayers.orSelf(visibleRegion); + } +} diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.h b/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.h index 1625352b85..b2468231a6 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.h +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.h @@ -37,9 +37,14 @@ public: void reset(); - uint32_t getZOrder(hwc2_layer_t layer) const; + bool advanceVisibleRegions(); + + hwc_region_t getVisibleRegion(hwc2_layer_t layer) const; + uint32_t getZOrder(hwc2_layer_t layer) const; private: + void setVisibleRegions(); + std::map mTestLayers; }; diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp index bfd076ffd1..a79909a041 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp @@ -16,6 +16,7 @@ #include #include +#include #define HWC2_INCLUDE_STRINGIFICATION #define HWC2_USE_CPP11 @@ -597,3 +598,59 @@ const std::vector Hwc2TestTransform::mCompleteTransforms = { HWC_TRANSFORM_FLIP_H_ROT_90, HWC_TRANSFORM_FLIP_V_ROT_90, }; + + +Hwc2TestVisibleRegion::~Hwc2TestVisibleRegion() +{ + release(); +} + +std::string Hwc2TestVisibleRegion::dump() const +{ + std::stringstream dmp; + + const hwc_region_t& curr = get(); + dmp << "\tvisible region: region count " << curr.numRects << "\n"; + for (size_t i = 0; i < curr.numRects; i++) { + const hwc_rect_t& rect = curr.rects[i]; + dmp << "\t\trect: left " << rect.left << ", top " << rect.top + << ", right " << rect.right << ", bottom " << rect.bottom << "\n"; + } + + return dmp.str(); +} + +void Hwc2TestVisibleRegion::set(const android::Region& visibleRegion) +{ + release(); + + size_t size = 0; + const android::Rect* rects = visibleRegion.getArray(&size); + + mVisibleRegion.numRects = size; + mVisibleRegion.rects = nullptr; + + if (size > 0) { + hwc_rect_t* hwcRects = new hwc_rect_t[size]; + for (size_t i = 0; i < size; i++) { + hwcRects[i].left = rects[i].left; + hwcRects[i].top = rects[i].top; + hwcRects[i].right = rects[i].right; + hwcRects[i].bottom = rects[i].bottom; + } + mVisibleRegion.rects = hwcRects; + } +} + +hwc_region_t Hwc2TestVisibleRegion::get() const +{ + return mVisibleRegion; +} + +void Hwc2TestVisibleRegion::release() +{ + if (mVisibleRegion.numRects > 0 && mVisibleRegion.rects) + delete[] mVisibleRegion.rects; + mVisibleRegion.rects = nullptr; + mVisibleRegion.numRects = 0; +} diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h index 048d6e95bc..9cdf69c394 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h @@ -20,6 +20,8 @@ #include #include +#include + #define HWC2_INCLUDE_STRINGIFICATION #define HWC2_USE_CPP11 #include @@ -290,4 +292,19 @@ protected: static const std::vector mCompleteTransforms; }; + +class Hwc2TestVisibleRegion { +public: + ~Hwc2TestVisibleRegion(); + + std::string dump() const; + + void set(const android::Region& visibleRegion); + hwc_region_t get() const; + void release(); + +protected: + hwc_region_t mVisibleRegion = {0, nullptr}; +}; + #endif /* ifndef _HWC2_TEST_PROPERTIES_H */ -- cgit v1.2.3-59-g8ed1b From 1cd789cd2b300427467586f4ec721a8123f118b7 Mon Sep 17 00:00:00 2001 From: Marissa Wall Date: Fri, 27 Jan 2017 12:55:36 -0800 Subject: test-hwc2: validate display Test: Add "#define HAVE_NO_SURFACE_FLINGER" to frameworks/native/libs/gui/BufferQueueCore.cpp. Recompile and flash. Run "mm" in frameworks/native/services/surfaceflinger/tests/hwc2. Push test-hwc2 to device. Run "adb root && adb shell stop". Run test case. Ex: "./test-hwc2" Change-Id: I9a9df2902213d99d4f043e3bdea1e5e2fc77b01d --- services/surfaceflinger/tests/hwc2/Hwc2Test.cpp | 196 +++++++++++++++++++++ .../surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp | 16 ++ services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h | 7 +- .../surfaceflinger/tests/hwc2/Hwc2TestLayers.cpp | 107 +++++++++++ .../surfaceflinger/tests/hwc2/Hwc2TestLayers.h | 23 ++- .../tests/hwc2/Hwc2TestProperties.cpp | 84 +++++++-- .../surfaceflinger/tests/hwc2/Hwc2TestProperties.h | 43 ++++- 7 files changed, 457 insertions(+), 19 deletions(-) diff --git a/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp index 024ba77795..44aa330b9f 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp +++ b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp @@ -559,6 +559,33 @@ public: } } + void validateDisplay(hwc2_display_t display, uint32_t* outNumTypes, + uint32_t* outNumRequests, hwc2_error_t* outErr) + { + auto pfn = reinterpret_cast( + getFunction(HWC2_FUNCTION_VALIDATE_DISPLAY)); + ASSERT_TRUE(pfn) << "failed to get function"; + + *outErr = static_cast(pfn(mHwc2Device, display, + outNumTypes, outNumRequests)); + } + + void validateDisplay(hwc2_display_t display, uint32_t* outNumTypes, + uint32_t* outNumRequests, bool* outHasChanges) + { + hwc2_error_t err = HWC2_ERROR_NONE; + + EXPECT_NO_FATAL_FAILURE(validateDisplay(display, outNumTypes, + outNumRequests, &err)); + + if (err != HWC2_ERROR_HAS_CHANGES) { + *outHasChanges = false; + EXPECT_EQ(err, HWC2_ERROR_NONE) << "failed to validate display"; + } else { + *outHasChanges = true; + } + } + protected: hwc2_function_pointer_t getFunction(hwc2_function_descriptor_t descriptor) { @@ -719,6 +746,12 @@ protected: using TestLayerPropertyBadParameterFunction = void (*)(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer, hwc2_error_t* outErr); + /* Is called after a display is powered on and all layer properties have + * been set. It should be used to test functions such as validate, accepting + * changes, present, etc. */ + using TestDisplayLayersFunction = void (*)(Hwc2Test* test, + hwc2_display_t display, const std::vector& layers); + /* Advances a property of Hwc2TestLayer */ using AdvanceProperty = bool (*)(Hwc2TestLayer* testLayer); @@ -895,6 +928,48 @@ protected: } } + /* For each active display it powers on the display, cycles through each + * config and creates a set of layers with a certain amount of coverage. + * For each active display, for each config and for each set of layers, + * it calls the TestDisplayLayersFunction */ + void displayLayers(Hwc2TestCoverage coverage, size_t layerCnt, + TestDisplayLayersFunction function) + { + for (auto display : mDisplays) { + std::vector configs; + + ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_ON)); + + ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs)); + + for (auto config : configs) { + Area displayArea; + std::vector layers; + + ASSERT_NO_FATAL_FAILURE(setActiveConfig(display, config)); + ASSERT_NO_FATAL_FAILURE(getActiveDisplayArea(display, &displayArea)); + + ASSERT_NO_FATAL_FAILURE(createLayers(display, &layers, layerCnt)); + Hwc2TestLayers testLayers(layers, coverage, displayArea); + + do { + bool skip; + + ASSERT_NO_FATAL_FAILURE(setLayerProperties(display, layers, + &testLayers, &skip)); + if (!skip) + EXPECT_NO_FATAL_FAILURE(function(this, display, layers)); + + } while (testLayers.advance()); + + ASSERT_NO_FATAL_FAILURE(destroyLayers(display, + std::move(layers))); + } + + ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_OFF)); + } + } + void getActiveConfigAttribute(hwc2_display_t display, hwc2_attribute_t attribute, int32_t* outValue) { @@ -914,6 +989,74 @@ protected: HWC2_ATTRIBUTE_HEIGHT, &displayArea->height)); } + void setLayerProperties(hwc2_display_t display, hwc2_layer_t layer, + Hwc2TestLayers* testLayers, bool* outSkip) + { + hwc2_composition_t composition; + buffer_handle_t handle = nullptr; + int32_t acquireFence; + hwc2_error_t err = HWC2_ERROR_NONE; + *outSkip = true; + + if (!testLayers->contains(layer)) + return; + + composition = testLayers->getComposition(layer); + + /* If the device cannot support a buffer format, then do not continue */ + if ((composition == HWC2_COMPOSITION_DEVICE + || composition == HWC2_COMPOSITION_CURSOR) + && testLayers->getBuffer(layer, &handle, &acquireFence) < 0) + return; + + EXPECT_NO_FATAL_FAILURE(setLayerCompositionType(display, layer, + composition, &err)); + if (err == HWC2_ERROR_UNSUPPORTED) + EXPECT_TRUE(composition != HWC2_COMPOSITION_CLIENT + && composition != HWC2_COMPOSITION_DEVICE); + + const hwc_rect_t cursor = testLayers->getCursorPosition(layer); + + EXPECT_NO_FATAL_FAILURE(setLayerBuffer(display, layer, handle, + acquireFence)); + EXPECT_NO_FATAL_FAILURE(setLayerBlendMode(display, layer, + testLayers->getBlendMode(layer))); + EXPECT_NO_FATAL_FAILURE(setLayerColor(display, layer, + testLayers->getColor(layer))); + EXPECT_NO_FATAL_FAILURE(setCursorPosition(display, layer, cursor.left, + cursor.top)); + EXPECT_NO_FATAL_FAILURE(setLayerDataspace(display, layer, + testLayers->getDataspace(layer))); + EXPECT_NO_FATAL_FAILURE(setLayerDisplayFrame(display, layer, + testLayers->getDisplayFrame(layer))); + EXPECT_NO_FATAL_FAILURE(setLayerPlaneAlpha(display, layer, + testLayers->getPlaneAlpha(layer))); + EXPECT_NO_FATAL_FAILURE(setLayerSourceCrop(display, layer, + testLayers->getSourceCrop(layer))); + EXPECT_NO_FATAL_FAILURE(setLayerSurfaceDamage(display, layer, + testLayers->getSurfaceDamage(layer))); + EXPECT_NO_FATAL_FAILURE(setLayerTransform(display, layer, + testLayers->getTransform(layer))); + EXPECT_NO_FATAL_FAILURE(setLayerVisibleRegion(display, layer, + testLayers->getVisibleRegion(layer))); + EXPECT_NO_FATAL_FAILURE(setLayerZOrder(display, layer, + testLayers->getZOrder(layer))); + + *outSkip = false; + } + + void setLayerProperties(hwc2_display_t display, + const std::vector& layers, + Hwc2TestLayers* testLayers, bool* outSkip) + { + for (auto layer : layers) { + EXPECT_NO_FATAL_FAILURE(setLayerProperties(display, layer, + testLayers, outSkip)); + if (*outSkip) + return; + } + } + hwc2_device_t* mHwc2Device = nullptr; enum class Hwc2TestHotplugStatus { @@ -2405,3 +2548,56 @@ TEST_F(Hwc2Test, SET_LAYER_Z_ORDER_bad_layer) ASSERT_NO_FATAL_FAILURE(setLayerPropertyBadLayer(Hwc2TestCoverage::Default, setZOrder)); } + +/* TESTCASE: Tests that the HWC2 can display a layer with basic property + * coverage */ +TEST_F(Hwc2Test, VALIDATE_DISPLAY_basic) +{ + ASSERT_NO_FATAL_FAILURE(displayLayers(Hwc2TestCoverage::Basic, 1, + [] (Hwc2Test* test, hwc2_display_t display, + const std::vector& layers) { + + uint32_t numTypes, numRequests; + bool hasChanges = false; + + EXPECT_NO_FATAL_FAILURE(test->validateDisplay(display, &numTypes, + &numRequests, &hasChanges)); + if (hasChanges) + EXPECT_LE(numTypes, static_cast(layers.size())) + << "wrong number of requests"; + } + )); +} + +/* TESTCASE: Tests that the HWC2 can display 5 layers with default coverage. */ +TEST_F(Hwc2Test, VALIDATE_DISPLAY_default_5) +{ + ASSERT_NO_FATAL_FAILURE(displayLayers(Hwc2TestCoverage::Default, 5, + [] (Hwc2Test* test, hwc2_display_t display, + const std::vector& layers) { + + uint32_t numTypes, numRequests; + bool hasChanges = false; + + EXPECT_NO_FATAL_FAILURE(test->validateDisplay(display, &numTypes, + &numRequests, &hasChanges)); + if (hasChanges) + EXPECT_LE(numTypes, static_cast(layers.size())) + << "wrong number of requests"; + } + )); +} + +/* TESTCASE: Tests that the HWC2 cannot validate a bad display */ +TEST_F(Hwc2Test, VALIDATE_DISPLAY_bad_display) +{ + hwc2_display_t display; + uint32_t numTypes, numRequests; + hwc2_error_t err = HWC2_ERROR_NONE; + + ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display)); + + ASSERT_NO_FATAL_FAILURE(validateDisplay(display, &numTypes, &numRequests, + &err)); + EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code"; +} diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp b/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp index f9c5aa0dc0..b459cd65c4 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp @@ -61,6 +61,12 @@ int Hwc2TestLayer::getBuffer(buffer_handle_t* outHandle, return ret; } +int Hwc2TestLayer::getBuffer(buffer_handle_t* outHandle, + int32_t* outAcquireFence) +{ + return mBuffer.get(outHandle, outAcquireFence); +} + void Hwc2TestLayer::setZOrder(uint32_t zOrder) { mZOrder = zOrder; @@ -80,6 +86,16 @@ void Hwc2TestLayer::reset() } } +bool Hwc2TestLayer::advance() +{ + for (auto property : mProperties) { + if (property->isSupported(mComposition.get())) + if (property->advance()) + return true; + } + return false; +} + hwc2_blend_mode_t Hwc2TestLayer::getBlendMode() const { return mBlendMode.get(); diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h b/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h index 86c36496c7..17f50790db 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h @@ -36,11 +36,13 @@ public: int getBuffer(buffer_handle_t* outHandle, android::base::unique_fd* outAcquireFence); + int getBuffer(buffer_handle_t* outHandle, int32_t* outAcquireFence); void setZOrder(uint32_t zOrder); void setVisibleRegion(const android::Region& region); void reset(); + bool advance(); hwc2_blend_mode_t getBlendMode() const; Area getBufferArea() const; @@ -71,8 +73,9 @@ public: private: std::array mProperties = {{ - &mBlendMode, &mBufferArea, &mColor, &mComposition, &mDataspace, - &mDisplayFrame, &mPlaneAlpha, &mSourceCrop, &mSurfaceDamage, &mTransform + &mTransform, &mColor, &mDataspace, &mPlaneAlpha, &mSourceCrop, + &mSurfaceDamage, &mBlendMode, &mBufferArea, &mDisplayFrame, + &mComposition }}; Hwc2TestBuffer mBuffer; diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.cpp b/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.cpp index 15a5f77a04..9d91f88da1 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.cpp +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.cpp @@ -20,6 +20,7 @@ Hwc2TestLayers::Hwc2TestLayers(const std::vector& layers, Hwc2TestCoverage coverage, const Area& displayArea) + : mDisplayArea(displayArea) { for (auto layer : layers) { mTestLayers.emplace(std::piecewise_construct, @@ -57,6 +58,18 @@ void Hwc2TestLayers::reset() setVisibleRegions(); } +bool Hwc2TestLayers::advance() +{ + for (auto& testLayer : mTestLayers) { + if (testLayer.second.advance()) { + setVisibleRegions(); + return true; + } + testLayer.second.reset(); + } + return false; +} + bool Hwc2TestLayers::advanceVisibleRegions() { for (auto& testLayer : mTestLayers) { @@ -69,6 +82,100 @@ bool Hwc2TestLayers::advanceVisibleRegions() return false; } +bool Hwc2TestLayers::contains(hwc2_layer_t layer) const +{ + return mTestLayers.count(layer) != 0; +} + +int Hwc2TestLayers::getBuffer(hwc2_layer_t layer, buffer_handle_t* outHandle, + int32_t* outAcquireFence) +{ + if (mTestLayers.count(layer) == 0) { + []() { GTEST_FAIL(); }(); + } + return mTestLayers.at(layer).getBuffer(outHandle, outAcquireFence); +} + +hwc2_blend_mode_t Hwc2TestLayers::getBlendMode(hwc2_layer_t layer) const +{ + if (mTestLayers.count(layer) == 0) { + []() { GTEST_FAIL(); }(); + } + return mTestLayers.at(layer).getBlendMode(); +} + +hwc_color_t Hwc2TestLayers::getColor(hwc2_layer_t layer) const +{ + if (mTestLayers.count(layer) == 0) { + []() { GTEST_FAIL(); }(); + } + return mTestLayers.at(layer).getColor(); +} + +hwc2_composition_t Hwc2TestLayers::getComposition(hwc2_layer_t layer) const +{ + if (mTestLayers.count(layer) == 0) { + []() { GTEST_FAIL(); }(); + } + return mTestLayers.at(layer).getComposition(); +} + +hwc_rect_t Hwc2TestLayers::getCursorPosition(hwc2_layer_t layer) const +{ + if (mTestLayers.count(layer) == 0) { + []() { GTEST_FAIL(); }(); + } + return mTestLayers.at(layer).getCursorPosition(); +} + +android_dataspace_t Hwc2TestLayers::getDataspace(hwc2_layer_t layer) const +{ + if (mTestLayers.count(layer) == 0) { + []() { GTEST_FAIL(); }(); + } + return mTestLayers.at(layer).getDataspace(); +} + +hwc_rect_t Hwc2TestLayers::getDisplayFrame(hwc2_layer_t layer) const +{ + if (mTestLayers.count(layer) == 0) { + []() { GTEST_FAIL(); }(); + } + return mTestLayers.at(layer).getDisplayFrame(); +} + +float Hwc2TestLayers::getPlaneAlpha(hwc2_layer_t layer) const +{ + if (mTestLayers.count(layer) == 0) { + []() { GTEST_FAIL(); }(); + } + return mTestLayers.at(layer).getPlaneAlpha(); +} + +hwc_frect_t Hwc2TestLayers::getSourceCrop(hwc2_layer_t layer) const +{ + if (mTestLayers.count(layer) == 0) { + []() { GTEST_FAIL(); }(); + } + return mTestLayers.at(layer).getSourceCrop(); +} + +hwc_region_t Hwc2TestLayers::getSurfaceDamage(hwc2_layer_t layer) const +{ + if (mTestLayers.count(layer) == 0) { + []() { GTEST_FAIL(); }(); + } + return mTestLayers.at(layer).getSurfaceDamage(); +} + +hwc_transform_t Hwc2TestLayers::getTransform(hwc2_layer_t layer) const +{ + if (mTestLayers.count(layer) == 0) { + []() { GTEST_FAIL(); }(); + } + return mTestLayers.at(layer).getTransform(); +} + hwc_region_t Hwc2TestLayers::getVisibleRegion(hwc2_layer_t layer) const { if (mTestLayers.count(layer) == 0) { diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.h b/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.h index b2468231a6..b4c3558a36 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.h +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.h @@ -37,15 +37,34 @@ public: void reset(); + bool advance(); bool advanceVisibleRegions(); - hwc_region_t getVisibleRegion(hwc2_layer_t layer) const; - uint32_t getZOrder(hwc2_layer_t layer) const; + bool contains(hwc2_layer_t layer) const; + + int getBuffer(hwc2_layer_t layer, buffer_handle_t* outHandle, + int32_t* outAcquireFence); + + hwc2_blend_mode_t getBlendMode(hwc2_layer_t layer) const; + hwc_color_t getColor(hwc2_layer_t layer) const; + hwc2_composition_t getComposition(hwc2_layer_t layer) const; + hwc_rect_t getCursorPosition(hwc2_layer_t layer) const; + android_dataspace_t getDataspace(hwc2_layer_t layer) const; + hwc_rect_t getDisplayFrame(hwc2_layer_t layer) const; + android_pixel_format_t getFormat(hwc2_layer_t layer) const; + float getPlaneAlpha(hwc2_layer_t layer) const; + hwc_frect_t getSourceCrop(hwc2_layer_t layer) const; + hwc_region_t getSurfaceDamage(hwc2_layer_t layer) const; + hwc_transform_t getTransform(hwc2_layer_t layer) const; + hwc_region_t getVisibleRegion(hwc2_layer_t layer) const; + uint32_t getZOrder(hwc2_layer_t layer) const; private: void setVisibleRegions(); std::map mTestLayers; + + Area mDisplayArea; }; #endif /* ifndef _HWC2_TEST_LAYERS_H */ diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp index a79909a041..e00c56067e 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp @@ -29,7 +29,7 @@ Hwc2TestBufferArea::Hwc2TestBufferArea(Hwc2TestCoverage coverage, const Area& displayArea) - : Hwc2TestProperty(mBufferAreas), + : Hwc2TestProperty(mBufferAreas, mCompositionSupport), mScalars((coverage == Hwc2TestCoverage::Complete)? mCompleteScalars: (coverage == Hwc2TestCoverage::Basic)? mBasicScalars: mDefaultScalars), @@ -115,7 +115,7 @@ const std::vector Hwc2TestBufferArea::mCompleteScalars = { Hwc2TestBlendMode::Hwc2TestBlendMode(Hwc2TestCoverage coverage) : Hwc2TestProperty(coverage, mCompleteBlendModes, mBasicBlendModes, - mDefaultBlendModes) { } + mDefaultBlendModes, mCompositionSupport) { } std::string Hwc2TestBlendMode::dump() const { @@ -154,7 +154,7 @@ const std::vector Hwc2TestBlendMode::mCompleteBlendModes = { Hwc2TestColor::Hwc2TestColor(Hwc2TestCoverage coverage, hwc2_blend_mode_t blendMode) - : Hwc2TestProperty(mColors), + : Hwc2TestProperty(mColors, mCompositionSupport), mBaseColors((coverage == Hwc2TestCoverage::Complete)? mCompleteBaseColors: (coverage == Hwc2TestCoverage::Basic)? mBasicBaseColors: mDefaultBaseColors), @@ -228,7 +228,7 @@ const std::vector Hwc2TestColor::mCompleteBaseColors = { Hwc2TestComposition::Hwc2TestComposition(Hwc2TestCoverage coverage) : Hwc2TestProperty(coverage, mCompleteCompositions, mBasicCompositions, - mDefaultCompositions) { } + mDefaultCompositions, mCompositionSupport) { } std::string Hwc2TestComposition::dump() const { @@ -257,7 +257,7 @@ const std::vector Hwc2TestComposition::mCompleteCompositions Hwc2TestDataspace::Hwc2TestDataspace(Hwc2TestCoverage coverage) : Hwc2TestProperty(coverage, completeDataspaces, basicDataspaces, - defaultDataspaces) { } + defaultDataspaces, mCompositionSupport) { } std::string Hwc2TestDataspace::dump() const { @@ -323,7 +323,7 @@ const std::vector Hwc2TestDataspace::completeDataspaces = { Hwc2TestDisplayFrame::Hwc2TestDisplayFrame(Hwc2TestCoverage coverage, const Area& displayArea) - : Hwc2TestProperty(mDisplayFrames), + : Hwc2TestProperty(mDisplayFrames, mCompositionSupport), mFrectScalars((coverage == Hwc2TestCoverage::Complete)? mCompleteFrectScalars: (coverage == Hwc2TestCoverage::Basic)? mBasicFrectScalars: mDefaultFrectScalars), @@ -383,7 +383,7 @@ const std::vector Hwc2TestDisplayFrame::mCompleteFrectScalars = { Hwc2TestPlaneAlpha::Hwc2TestPlaneAlpha(Hwc2TestCoverage coverage) : Hwc2TestProperty(coverage, mCompletePlaneAlphas, mBasicPlaneAlphas, - mDefaultPlaneAlphas) { } + mDefaultPlaneAlphas, mCompositionSupport) { } std::string Hwc2TestPlaneAlpha::dump() const { @@ -407,7 +407,7 @@ const std::vector Hwc2TestPlaneAlpha::mCompletePlaneAlphas = { Hwc2TestSourceCrop::Hwc2TestSourceCrop(Hwc2TestCoverage coverage, const Area& bufferArea) - : Hwc2TestProperty(mSourceCrops), + : Hwc2TestProperty(mSourceCrops, mCompositionSupport), mFrectScalars((coverage == Hwc2TestCoverage::Complete)? mCompleteFrectScalars: (coverage == Hwc2TestCoverage::Basic)? mBasicFrectScalars: mDefaultFrectScalars), @@ -470,7 +470,7 @@ const std::vector Hwc2TestSourceCrop::mCompleteFrectScalars = { Hwc2TestSurfaceDamage::Hwc2TestSurfaceDamage(Hwc2TestCoverage coverage) - : Hwc2TestProperty(mSurfaceDamages), + : Hwc2TestProperty(mSurfaceDamages, mCompositionSupport), mRegionScalars((coverage == Hwc2TestCoverage::Complete)? mCompleteRegionScalars: (coverage == Hwc2TestCoverage::Basic)? mBasicRegionScalars: mDefaultRegionScalars) @@ -568,7 +568,7 @@ const std::vector> Hwc2TestSurfaceDamage::mCompleteRegi Hwc2TestTransform::Hwc2TestTransform(Hwc2TestCoverage coverage) : Hwc2TestProperty(coverage, mCompleteTransforms, mBasicTransforms, - mDefaultTransforms) { } + mDefaultTransforms, mCompositionSupport) { } std::string Hwc2TestTransform::dump() const { @@ -654,3 +654,67 @@ void Hwc2TestVisibleRegion::release() mVisibleRegion.rects = nullptr; mVisibleRegion.numRects = 0; } + +/* Identifies which layer properties are supported by each composition type. + * hwc2_composition_t values range from: + * HWC2_COMPOSITION_INVALID = 0, + * HWC2_COMPOSITION_CLIENT = 1, + * HWC2_COMPOSITION_DEVICE = 2, + * HWC2_COMPOSITION_SOLID_COLOR = 3, + * HWC2_COMPOSITION_CURSOR = 4, + * HWC2_COMPOSITION_SIDEBAND = 5, + * + * Each property array can be indexed by a hwc2_composition_t value. + * By using an array instead of a more complex data structure, runtimes for + * some test cases showed a noticeable improvement. + */ + +/* INVALID CLIENT DEVICE COLOR CURSOR SIDEBAND */ +const std::array Hwc2TestBufferArea::mCompositionSupport = {{ + false, true, true, false, true, true, +}}; + +/* INVALID CLIENT DEVICE COLOR CURSOR SIDEBAND */ +const std::array Hwc2TestBlendMode::mCompositionSupport = {{ + false, true, true, false, true, true, +}}; + +/* INVALID CLIENT DEVICE COLOR CURSOR SIDEBAND */ +const std::array Hwc2TestColor::mCompositionSupport = {{ + false, false, false, true, false, false, +}}; + +/* INVALID CLIENT DEVICE COLOR CURSOR SIDEBAND */ +const std::array Hwc2TestComposition::mCompositionSupport = {{ + false, true, true, true, true, true, +}}; + +/* INVALID CLIENT DEVICE COLOR CURSOR SIDEBAND */ +const std::array Hwc2TestDataspace::mCompositionSupport = {{ + false, true, true, true, true, false, +}}; + +/* INVALID CLIENT DEVICE COLOR CURSOR SIDEBAND */ +const std::array Hwc2TestDisplayFrame::mCompositionSupport = {{ + false, true, true, true, false, true, +}}; + +/* INVALID CLIENT DEVICE COLOR CURSOR SIDEBAND */ +const std::array Hwc2TestPlaneAlpha::mCompositionSupport = {{ + false, true, true, true, true, true, +}}; + +/* INVALID CLIENT DEVICE COLOR CURSOR SIDEBAND */ +const std::array Hwc2TestSourceCrop::mCompositionSupport = {{ + false, true, true, false, true, false, +}}; + +/* INVALID CLIENT DEVICE COLOR CURSOR SIDEBAND */ +const std::array Hwc2TestSurfaceDamage::mCompositionSupport = {{ + false, false, true, false, true, false, +}}; + +/* INVALID CLIENT DEVICE COLOR CURSOR SIDEBAND */ +const std::array Hwc2TestTransform::mCompositionSupport = {{ + false, true, true, false, true, true, +}}; diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h index 9cdf69c394..f3c614cd55 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h @@ -52,6 +52,9 @@ public: virtual bool advance() = 0; virtual std::string dump() const = 0; + + /* Returns true if the container supports the given composition type */ + virtual bool isSupported(hwc2_composition_t composition) = 0; }; @@ -60,12 +63,16 @@ class Hwc2TestProperty : public Hwc2TestContainer { public: Hwc2TestProperty(Hwc2TestCoverage coverage, const std::vector& completeList, const std::vector& basicList, - const std::vector& defaultList) + const std::vector& defaultList, + const std::array& compositionSupport) : Hwc2TestProperty((coverage == Hwc2TestCoverage::Complete)? completeList: - (coverage == Hwc2TestCoverage::Basic)? basicList : defaultList) { } + (coverage == Hwc2TestCoverage::Basic)? basicList : defaultList, + compositionSupport) { } - Hwc2TestProperty(const std::vector& list) - : mList(list) { } + Hwc2TestProperty(const std::vector& list, + const std::array& compositionSupport) + : mList(list), + mCompositionSupport(compositionSupport) { } void reset() override { @@ -89,14 +96,20 @@ public: return mList.at(mListIdx); } + virtual bool isSupported(hwc2_composition_t composition) + { + return mCompositionSupport.at(composition); + } + protected: /* If a derived class has dependents, override this function */ virtual void updateDependents() { } const std::vector& mList; size_t mListIdx = 0; -}; + const std::array& mCompositionSupport; +}; class Hwc2TestBuffer; class Hwc2TestSourceCrop; @@ -128,6 +141,8 @@ protected: Hwc2TestSurfaceDamage* mSurfaceDamage = nullptr; std::vector mBufferAreas; + + static const std::array mCompositionSupport; }; @@ -149,6 +164,8 @@ protected: static const std::vector mDefaultBlendModes; static const std::vector mBasicBlendModes; static const std::vector mCompleteBlendModes; + + static const std::array mCompositionSupport; }; @@ -172,6 +189,8 @@ protected: hwc2_blend_mode_t mBlendMode; std::vector mColors; + + static const std::array mCompositionSupport; }; @@ -185,6 +204,8 @@ protected: static const std::vector mDefaultCompositions; static const std::vector mBasicCompositions; static const std::vector mCompleteCompositions; + + static const std::array mCompositionSupport; }; @@ -198,6 +219,8 @@ protected: static const std::vector defaultDataspaces; static const std::vector basicDataspaces; static const std::vector completeDataspaces; + + static const std::array mCompositionSupport; }; @@ -218,6 +241,8 @@ protected: Area mDisplayArea; std::vector mDisplayFrames; + + static const std::array mCompositionSupport; }; @@ -231,6 +256,8 @@ protected: static const std::vector mDefaultPlaneAlphas; static const std::vector mBasicPlaneAlphas; static const std::vector mCompletePlaneAlphas; + + static const std::array mCompositionSupport; }; @@ -253,6 +280,8 @@ protected: Area mBufferArea; std::vector mSourceCrops; + + static const std::array mCompositionSupport; }; @@ -277,6 +306,8 @@ protected: Area mBufferArea = {0, 0}; std::vector mSurfaceDamages; + + static const std::array mCompositionSupport; }; @@ -290,6 +321,8 @@ protected: static const std::vector mDefaultTransforms; static const std::vector mBasicTransforms; static const std::vector mCompleteTransforms; + + static const std::array mCompositionSupport; }; -- cgit v1.2.3-59-g8ed1b From 706178db2a89e2bf44e95bfad74dc4451a277b3d Mon Sep 17 00:00:00 2001 From: Marissa Wall Date: Thu, 15 Dec 2016 12:39:14 -0800 Subject: test-hwc2: get and accept display changes Test: Add "#define HAVE_NO_SURFACE_FLINGER" to frameworks/native/libs/gui/BufferQueueCore.cpp. Recompile and flash. Run "mm" in frameworks/native/services/surfaceflinger/tests/hwc2. Push test-hwc2 to device. Run "adb root && adb shell stop". Run test case. Ex: "./test-hwc2" Change-Id: Ia1d1a0ee5fce43e7904ee49f13a86df0e7adc428 --- services/surfaceflinger/tests/hwc2/Hwc2Test.cpp | 421 +++++++++++++++++++++++- 1 file changed, 417 insertions(+), 4 deletions(-) diff --git a/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp index 44aa330b9f..27f9abaa29 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp +++ b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp @@ -586,6 +586,192 @@ public: } } + void getDisplayRequests(hwc2_display_t display, + hwc2_display_request_t* outDisplayRequests, + std::vector* outLayers, + std::vector* outLayerRequests, + hwc2_error_t* outErr = nullptr) + { + auto pfn = reinterpret_cast( + getFunction(HWC2_FUNCTION_GET_DISPLAY_REQUESTS)); + ASSERT_TRUE(pfn) << "failed to get function"; + + uint32_t numElements = 0; + + auto err = static_cast(pfn(mHwc2Device, display, + reinterpret_cast(outDisplayRequests), &numElements, + nullptr, nullptr)); + + if (err == HWC2_ERROR_NONE && numElements > 0) { + outLayers->resize(numElements); + outLayerRequests->resize(numElements); + + err = static_cast(pfn(mHwc2Device, display, + reinterpret_cast(outDisplayRequests), &numElements, + reinterpret_cast(outLayers->data()), + reinterpret_cast(outLayerRequests->data()))); + } + + if (outErr) { + *outErr = err; + } else { + ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to get display requests"; + } + } + + void handleRequests(hwc2_display_t display, + const std::vector& layers, uint32_t numRequests, + std::set* outClearLayers = nullptr, + bool* outFlipClientTarget = nullptr) + { + hwc2_display_request_t displayRequest = + static_cast(0); + std::vector requestedLayers; + std::vector requests; + + ASSERT_NO_FATAL_FAILURE(getDisplayRequests(display, &displayRequest, + &requestedLayers, &requests)); + + EXPECT_EQ(numRequests, requests.size()) << "validate returned " + << numRequests << " requests and get display requests returned " + << requests.size() << " requests"; + + for (size_t i = 0; i < requests.size(); i++) { + hwc2_layer_t requestedLayer = requestedLayers.at(i); + hwc2_layer_request_t request = requests.at(i); + + EXPECT_EQ(std::count(layers.begin(), layers.end(), requestedLayer), + 0) << "get display requests returned an unknown layer"; + EXPECT_NE(request, 0) << "returned empty request for layer " + << requestedLayer; + + if (outClearLayers && request + == HWC2_LAYER_REQUEST_CLEAR_CLIENT_TARGET) + outClearLayers->insert(requestedLayer); + } + + if (outFlipClientTarget) + *outFlipClientTarget = displayRequest + & HWC2_DISPLAY_REQUEST_FLIP_CLIENT_TARGET; + } + + void getChangedCompositionTypes(hwc2_display_t display, + std::vector* outLayers, + std::vector* outTypes, + hwc2_error_t* outErr = nullptr) + { + auto pfn = reinterpret_cast( + getFunction(HWC2_FUNCTION_GET_CHANGED_COMPOSITION_TYPES)); + ASSERT_TRUE(pfn) << "failed to get function"; + + uint32_t numElements = 0; + + auto err = static_cast(pfn(mHwc2Device, display, + &numElements, nullptr, nullptr)); + + if (err == HWC2_ERROR_NONE && numElements > 0) { + outLayers->resize(numElements); + outTypes->resize(numElements); + + err = static_cast(pfn(mHwc2Device, display, + &numElements, reinterpret_cast(outLayers->data()), + reinterpret_cast(outTypes->data()))); + } + + if (outErr) { + *outErr = err; + } else { + ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to get changed" + " composition types"; + } + } + + void handleCompositionChanges(hwc2_display_t display, + const Hwc2TestLayers& testLayers, + const std::vector& layers, uint32_t numTypes, + std::set* outClientLayers = nullptr) + { + std::vector changedLayers; + std::vector types; + + ASSERT_NO_FATAL_FAILURE(getChangedCompositionTypes(display, + &changedLayers, &types)); + + EXPECT_EQ(numTypes, types.size()) << "validate returned " + << numTypes << " types and get changed composition types" + " returned " << types.size() << " types"; + + for (size_t i = 0; i < types.size(); i++) { + + auto layer = std::find(layers.begin(), layers.end(), + changedLayers.at(i)); + + EXPECT_TRUE(layer != layers.end() || !testLayers.contains(*layer)) + << "get changed composition types returned an unknown layer"; + + hwc2_composition_t requestedType = testLayers.getComposition(*layer); + hwc2_composition_t returnedType = types.at(i); + + EXPECT_NE(returnedType, HWC2_COMPOSITION_INVALID) << "get changed" + " composition types returned invalid composition"; + + switch (requestedType) { + case HWC2_COMPOSITION_CLIENT: + EXPECT_TRUE(false) << getCompositionName(returnedType) + << " cannot be changed"; + break; + case HWC2_COMPOSITION_DEVICE: + case HWC2_COMPOSITION_SOLID_COLOR: + EXPECT_EQ(returnedType, HWC2_COMPOSITION_CLIENT) + << "composition of type " + << getCompositionName(requestedType) + << " can only be changed to " + << getCompositionName(HWC2_COMPOSITION_CLIENT); + break; + case HWC2_COMPOSITION_CURSOR: + case HWC2_COMPOSITION_SIDEBAND: + EXPECT_TRUE(returnedType == HWC2_COMPOSITION_CLIENT + || returnedType == HWC2_COMPOSITION_DEVICE) + << "composition of type " + << getCompositionName(requestedType) + << " can only be changed to " + << getCompositionName(HWC2_COMPOSITION_CLIENT) << " or " + << getCompositionName(HWC2_COMPOSITION_DEVICE); + break; + default: + EXPECT_TRUE(false) << "unknown type " + << getCompositionName(requestedType); + break; + } + + if (outClientLayers) + if (returnedType == HWC2_COMPOSITION_CLIENT) + outClientLayers->insert(*layer); + } + + if (outClientLayers) { + for (auto layer : layers) { + if (testLayers.getComposition(layer) == HWC2_COMPOSITION_CLIENT) + outClientLayers->insert(layer); + } + } + } + + void acceptDisplayChanges(hwc2_display_t display, + hwc2_error_t* outErr = nullptr) + { + auto pfn = reinterpret_cast( + getFunction(HWC2_FUNCTION_ACCEPT_DISPLAY_CHANGES)); + ASSERT_TRUE(pfn) << "failed to get function"; + + auto err = static_cast(pfn(mHwc2Device, display)); + if (outErr) { + *outErr = err; + } else { + ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to accept display changes"; + } + } + protected: hwc2_function_pointer_t getFunction(hwc2_function_descriptor_t descriptor) { @@ -750,7 +936,12 @@ protected: * been set. It should be used to test functions such as validate, accepting * changes, present, etc. */ using TestDisplayLayersFunction = void (*)(Hwc2Test* test, - hwc2_display_t display, const std::vector& layers); + hwc2_display_t display, const std::vector& layers, + const Hwc2TestLayers& testLayers); + + /* It is called on an non validated display */ + using TestDisplayNonValidatedLayersFunction = void (*)(Hwc2Test* test, + hwc2_display_t display, std::vector* layers); /* Advances a property of Hwc2TestLayer */ using AdvanceProperty = bool (*)(Hwc2TestLayer* testLayer); @@ -958,7 +1149,8 @@ protected: ASSERT_NO_FATAL_FAILURE(setLayerProperties(display, layers, &testLayers, &skip)); if (!skip) - EXPECT_NO_FATAL_FAILURE(function(this, display, layers)); + EXPECT_NO_FATAL_FAILURE(function(this, display, layers, + testLayers)); } while (testLayers.advance()); @@ -970,6 +1162,50 @@ protected: } } + /* For each active display, it calls the + * TestDisplayNonValidatedLayersFunction on a variety on non-validated + * layer combinations */ + void displayNonValidatedLayers(size_t layerCnt, + TestDisplayNonValidatedLayersFunction function) + { + for (auto display : mDisplays) { + uint32_t numTypes, numRequests; + std::vector layers; + bool hasChanges; + + ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_ON)); + + EXPECT_NO_FATAL_FAILURE(function(this, display, &layers)); + + ASSERT_NO_FATAL_FAILURE(createLayers(display, &layers, layerCnt)); + + EXPECT_NO_FATAL_FAILURE(function(this, display, &layers)); + + for (auto layer : layers) { + ASSERT_NO_FATAL_FAILURE(setLayerCompositionType(display, layer, + HWC2_COMPOSITION_CLIENT)); + } + + EXPECT_NO_FATAL_FAILURE(function(this, display, &layers)); + + ASSERT_NO_FATAL_FAILURE(validateDisplay(display, &numTypes, + &numRequests, &hasChanges)); + + for (auto layer : layers) { + ASSERT_NO_FATAL_FAILURE(setLayerCompositionType(display, layer, + HWC2_COMPOSITION_DEVICE)); + } + + EXPECT_NO_FATAL_FAILURE(function(this, display, &layers)); + + ASSERT_NO_FATAL_FAILURE(destroyLayers(display, std::move(layers))); + + EXPECT_NO_FATAL_FAILURE(function(this, display, &layers)); + + ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_OFF)); + } + } + void getActiveConfigAttribute(hwc2_display_t display, hwc2_attribute_t attribute, int32_t* outValue) { @@ -2555,7 +2791,8 @@ TEST_F(Hwc2Test, VALIDATE_DISPLAY_basic) { ASSERT_NO_FATAL_FAILURE(displayLayers(Hwc2TestCoverage::Basic, 1, [] (Hwc2Test* test, hwc2_display_t display, - const std::vector& layers) { + const std::vector& layers, + const Hwc2TestLayers& /*testLayers*/) { uint32_t numTypes, numRequests; bool hasChanges = false; @@ -2574,7 +2811,8 @@ TEST_F(Hwc2Test, VALIDATE_DISPLAY_default_5) { ASSERT_NO_FATAL_FAILURE(displayLayers(Hwc2TestCoverage::Default, 5, [] (Hwc2Test* test, hwc2_display_t display, - const std::vector& layers) { + const std::vector& layers, + const Hwc2TestLayers& /*testLayers*/) { uint32_t numTypes, numRequests; bool hasChanges = false; @@ -2601,3 +2839,178 @@ TEST_F(Hwc2Test, VALIDATE_DISPLAY_bad_display) &err)); EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code"; } + +/* TESTCASE: Tests that the HWC2 can get display requests after validating a + * basic layer. */ +TEST_F(Hwc2Test, GET_DISPLAY_REQUESTS_basic) +{ + ASSERT_NO_FATAL_FAILURE(displayLayers(Hwc2TestCoverage::Basic, 1, + [] (Hwc2Test* test, hwc2_display_t display, + const std::vector& layers, + const Hwc2TestLayers& /*testLayers*/) { + + uint32_t numTypes, numRequests; + bool hasChanges = false; + + ASSERT_NO_FATAL_FAILURE(test->validateDisplay(display, &numTypes, + &numRequests, &hasChanges)); + if (hasChanges) + EXPECT_LE(numTypes, layers.size()) + << "wrong number of requests"; + + EXPECT_NO_FATAL_FAILURE(test->handleRequests(display, layers, + numRequests)); + } + )); +} + +/* TESTCASE: Tests that the HWC2 cannot get display requests from a bad display */ +TEST_F(Hwc2Test, GET_DISPLAY_REQUESTS_bad_display) +{ + hwc2_display_t display; + hwc2_display_request_t displayRequests; + std::vector layers; + std::vector layerRequests; + hwc2_error_t err = HWC2_ERROR_NONE; + + ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display)); + + EXPECT_NO_FATAL_FAILURE(getDisplayRequests(display, &displayRequests, + &layers, &layerRequests, &err)); + EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code"; +} + +/* TESTCASE: Tests that the HWC2 cannot get display requests from an non + * validated display. */ +TEST_F(Hwc2Test, GET_DISPLAY_REQUESTS_not_validated) +{ + ASSERT_NO_FATAL_FAILURE(displayNonValidatedLayers(5, + [] (Hwc2Test* test, hwc2_display_t display, + std::vector* layers) { + + hwc2_display_request_t displayRequests; + std::vector layerRequests; + hwc2_error_t err = HWC2_ERROR_NONE; + + ASSERT_NO_FATAL_FAILURE(test->getDisplayRequests(display, + &displayRequests, layers, &layerRequests, &err)); + EXPECT_EQ(err, HWC2_ERROR_NOT_VALIDATED) + << "returned wrong error code"; + } + )); +} + +/* TESTCASE: Tests that the HWC2 can get changed composition types after + * validating a basic layer. */ +TEST_F(Hwc2Test, GET_CHANGED_COMPOSITION_TYPES_basic) +{ + ASSERT_NO_FATAL_FAILURE(displayLayers(Hwc2TestCoverage::Basic, 1, + [] (Hwc2Test* test, hwc2_display_t display, + const std::vector& layers, + const Hwc2TestLayers& testLayers) { + + uint32_t numTypes, numRequests; + bool hasChanges = false; + + ASSERT_NO_FATAL_FAILURE(test->validateDisplay(display, &numTypes, + &numRequests, &hasChanges)); + if (hasChanges) + EXPECT_LE(numTypes, layers.size()) + << "wrong number of requests"; + + EXPECT_NO_FATAL_FAILURE(test->handleCompositionChanges(display, + testLayers, layers, numTypes)); + } + )); +} + +/* TESTCASE: Tests that the HWC2 cannot get changed composition types from a bad + * display */ +TEST_F(Hwc2Test, GET_CHANGED_COMPOSITION_TYPES_bad_display) +{ + hwc2_display_t display; + std::vector layers; + std::vector types; + hwc2_error_t err = HWC2_ERROR_NONE; + + ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display)); + + EXPECT_NO_FATAL_FAILURE(getChangedCompositionTypes(display, &layers, + &types, &err)); + EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code"; +} + +/* TESTCASE: Tests that the HWC2 cannot get changed composition types from an non + * validated display. */ +TEST_F(Hwc2Test, GET_CHANGED_COMPOSITION_TYPES_not_validated) +{ + ASSERT_NO_FATAL_FAILURE(displayNonValidatedLayers(5, + [] (Hwc2Test* test, hwc2_display_t display, + std::vector* layers) { + + std::vector types; + hwc2_error_t err = HWC2_ERROR_NONE; + + ASSERT_NO_FATAL_FAILURE(test->getChangedCompositionTypes( + display, layers, &types, &err)); + EXPECT_EQ(err, HWC2_ERROR_NOT_VALIDATED) + << "returned wrong error code"; + } + )); +} + +/* TESTCASE: Tests that the HWC2 can accept display changes after validating a + * basic layer. */ +TEST_F(Hwc2Test, ACCEPT_DISPLAY_CHANGES_basic) +{ + ASSERT_NO_FATAL_FAILURE(displayLayers(Hwc2TestCoverage::Basic, 1, + [] (Hwc2Test* test, hwc2_display_t display, + const std::vector& layers, + const Hwc2TestLayers& testLayers) { + + uint32_t numTypes, numRequests; + bool hasChanges = false; + + ASSERT_NO_FATAL_FAILURE(test->validateDisplay(display, &numTypes, + &numRequests, &hasChanges)); + if (hasChanges) + EXPECT_LE(numTypes, layers.size()) + << "wrong number of requests"; + + ASSERT_NO_FATAL_FAILURE(test->handleCompositionChanges(display, + testLayers, layers, numTypes)); + + EXPECT_NO_FATAL_FAILURE(test->acceptDisplayChanges(display)); + } + )); +} + +/* TESTCASE: Tests that the HWC2 cannot accept display changes from a bad + * display */ +TEST_F(Hwc2Test, ACCEPT_DISPLAY_CHANGES_bad_display) +{ + hwc2_display_t display; + hwc2_error_t err = HWC2_ERROR_NONE; + + ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display)); + + EXPECT_NO_FATAL_FAILURE(acceptDisplayChanges(display, &err)); + EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code"; +} + +/* TESTCASE: Tests that the HWC2 cannot accept display changes from an non + * validated display. */ +TEST_F(Hwc2Test, ACCEPT_DISPLAY_CHANGES_not_validated) +{ + ASSERT_NO_FATAL_FAILURE(displayNonValidatedLayers(5, + [] (Hwc2Test* test, hwc2_display_t display, + std::vector* /*layers*/) { + + hwc2_error_t err = HWC2_ERROR_NONE; + + ASSERT_NO_FATAL_FAILURE(test->acceptDisplayChanges(display, &err)); + EXPECT_EQ(err, HWC2_ERROR_NOT_VALIDATED) + << "returned wrong error code"; + } + )); +} -- cgit v1.2.3-59-g8ed1b From f18cfb0a780c69f12439457ccc3f5272db767fdd Mon Sep 17 00:00:00 2001 From: Marissa Wall Date: Tue, 21 Feb 2017 14:01:05 -0800 Subject: test-hwc2: add client target support Test: Add "#define HAVE_NO_SURFACE_FLINGER" to frameworks/native/libs/gui/BufferQueueCore.cpp. Recompile and flash. Run "mm" in frameworks/native/services/surfaceflinger/tests/hwc2. Push test-hwc2 to device. Run "adb root && adb shell stop". Run test case. Ex: "./test-hwc2" Change-Id: I94c86795b2e334df0570c6c5a3cbbcb5a8ca2826 --- services/surfaceflinger/tests/hwc2/Android.mk | 3 +- services/surfaceflinger/tests/hwc2/Hwc2Test.cpp | 273 ++++++++++++++++++++- .../surfaceflinger/tests/hwc2/Hwc2TestBuffer.cpp | 270 ++++++++++++++++++-- .../surfaceflinger/tests/hwc2/Hwc2TestBuffer.h | 27 +- .../tests/hwc2/Hwc2TestClientTarget.cpp | 102 ++++++++ .../tests/hwc2/Hwc2TestClientTarget.h | 69 ++++++ .../surfaceflinger/tests/hwc2/Hwc2TestLayers.cpp | 75 +++++- .../surfaceflinger/tests/hwc2/Hwc2TestLayers.h | 13 +- 8 files changed, 788 insertions(+), 44 deletions(-) create mode 100644 services/surfaceflinger/tests/hwc2/Hwc2TestClientTarget.cpp create mode 100644 services/surfaceflinger/tests/hwc2/Hwc2TestClientTarget.h diff --git a/services/surfaceflinger/tests/hwc2/Android.mk b/services/surfaceflinger/tests/hwc2/Android.mk index 79c3e9271e..329e124514 100644 --- a/services/surfaceflinger/tests/hwc2/Android.mk +++ b/services/surfaceflinger/tests/hwc2/Android.mk @@ -45,6 +45,7 @@ LOCAL_SRC_FILES := \ Hwc2TestProperties.cpp \ Hwc2TestLayer.cpp \ Hwc2TestLayers.cpp \ - Hwc2TestBuffer.cpp + Hwc2TestBuffer.cpp \ + Hwc2TestClientTarget.cpp include $(BUILD_NATIVE_TEST) diff --git a/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp index 27f9abaa29..9171de2b5d 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp +++ b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp @@ -29,6 +29,7 @@ #include "Hwc2TestLayer.h" #include "Hwc2TestLayers.h" +#include "Hwc2TestClientTarget.h" void hwc2TestHotplugCallback(hwc2_callback_data_t callbackData, hwc2_display_t display, int32_t connected); @@ -772,6 +773,53 @@ public: } } + void getClientTargetSupport(hwc2_display_t display, int32_t width, + int32_t height, android_pixel_format_t format, + android_dataspace_t dataspace, hwc2_error_t* outErr = nullptr) + { + auto pfn = reinterpret_cast( + getFunction(HWC2_FUNCTION_GET_CLIENT_TARGET_SUPPORT)); + ASSERT_TRUE(pfn) << "failed to get function"; + + auto err = static_cast(pfn(mHwc2Device, display, width, + height, format, dataspace)); + if (outErr) { + *outErr = err; + } else { + ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to get client target" + " support"; + } + } + + void setClientTarget(hwc2_display_t display, buffer_handle_t handle, + int32_t acquireFence, android_dataspace_t dataspace, + hwc_region_t damage, hwc2_error_t* outErr = nullptr) + { + auto pfn = reinterpret_cast( + getFunction(HWC2_FUNCTION_SET_CLIENT_TARGET)); + ASSERT_TRUE(pfn) << "failed to get function"; + + auto err = static_cast(pfn(mHwc2Device, display, handle, + acquireFence, dataspace, damage)); + if (outErr) { + *outErr = err; + } else { + ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set client target"; + } + } + + void getBadDisplay(hwc2_display_t* outDisplay) + { + for (hwc2_display_t display = 0; display < UINT64_MAX; display++) { + if (mDisplays.count(display) == 0) { + *outDisplay = display; + return; + } + } + ASSERT_TRUE(false) << "Unable to find bad display. UINT64_MAX displays" + " are registered. This should never happen."; + } + protected: hwc2_function_pointer_t getFunction(hwc2_function_descriptor_t descriptor) { @@ -820,18 +868,6 @@ protected: mHotplugStatus = Hwc2TestHotplugStatus::Done; } - void getBadDisplay(hwc2_display_t* outDisplay) - { - for (hwc2_display_t display = 0; display < UINT64_MAX; display++) { - if (mDisplays.count(display) == 0) { - *outDisplay = display; - return; - } - } - ASSERT_TRUE(false) << "Unable to find bad display. UINT64_MAX displays" - " are registered. This should never happen."; - } - /* NOTE: will create min(newlayerCnt, max supported layers) layers */ void createLayers(hwc2_display_t display, std::vector* outLayers, size_t newLayerCnt) @@ -943,12 +979,21 @@ protected: using TestDisplayNonValidatedLayersFunction = void (*)(Hwc2Test* test, hwc2_display_t display, std::vector* layers); + /* Tests client target support on a particular display and config */ + using TestClientTargetSupportFunction = void (*)(Hwc2Test* test, + hwc2_display_t display, + const Hwc2TestClientTargetSupport& testClientTargetSupport); + /* Advances a property of Hwc2TestLayer */ using AdvanceProperty = bool (*)(Hwc2TestLayer* testLayer); /* Advances properties of Hwc2TestLayers */ using AdvanceProperties = bool (*)(Hwc2TestLayers* testLayer); + /* Advances properties of Hwc2TestClientTargetSupport */ + using AdvanceClientTargetSupport = bool (*)( + Hwc2TestClientTargetSupport* testClientTargetSupport); + /* For each active display it cycles through each display config and tests * each property value. It creates a layer, sets the property and then * destroys the layer */ @@ -1206,6 +1251,34 @@ protected: } } + /* Test client target support on each config on each active display */ + void setClientTargetSupport(Hwc2TestCoverage coverage, + TestClientTargetSupportFunction function, + AdvanceClientTargetSupport advance) + { + for (auto display : mDisplays) { + std::vector configs; + + ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs)); + + for (auto config : configs) { + Area displayArea; + + ASSERT_NO_FATAL_FAILURE(setActiveConfig(display, config)); + ASSERT_NO_FATAL_FAILURE(getActiveDisplayArea(display, + &displayArea)); + Hwc2TestClientTargetSupport testClientTargetSupport(coverage, + displayArea); + + do { + EXPECT_NO_FATAL_FAILURE(function(this, display, + testClientTargetSupport)); + + } while (advance(&testClientTargetSupport)); + } + } + } + void getActiveConfigAttribute(hwc2_display_t display, hwc2_attribute_t attribute, int32_t* outValue) { @@ -1539,6 +1612,11 @@ bool advanceVisibleRegions(Hwc2TestLayers* testLayers) return testLayers->advanceVisibleRegions(); } +bool advanceClientTargetSupport( + Hwc2TestClientTargetSupport* testClientTargetSupport) +{ + return testClientTargetSupport->advance(); +} static const std::array requiredFunctions = {{ HWC2_FUNCTION_ACCEPT_DISPLAY_CHANGES, @@ -3014,3 +3092,174 @@ TEST_F(Hwc2Test, ACCEPT_DISPLAY_CHANGES_not_validated) } )); } + +/* TESTCASE: Tests that the HWC2 supports client target with required values */ +TEST_F(Hwc2Test, GET_CLIENT_TARGET_SUPPORT) +{ + ASSERT_NO_FATAL_FAILURE(setClientTargetSupport(Hwc2TestCoverage::Default, + [] (Hwc2Test* test, hwc2_display_t display, + const Hwc2TestClientTargetSupport& testClientTargetSupport) { + + const Area bufferArea = testClientTargetSupport.getBufferArea(); + const android_pixel_format_t format = HAL_PIXEL_FORMAT_RGBA_8888; + + ASSERT_NO_FATAL_FAILURE(test->getClientTargetSupport(display, + bufferArea.width, bufferArea.height, format, + testClientTargetSupport.getDataspace())); + }, + + advanceClientTargetSupport)); +} + +/* TESTCASE: Tests that the HWC2 cannot get client target support for a bad + * display. */ +TEST_F(Hwc2Test, GET_CLIENT_TARGET_SUPPORT_bad_display) +{ + ASSERT_NO_FATAL_FAILURE(setClientTargetSupport(Hwc2TestCoverage::Default, + [] (Hwc2Test* test, hwc2_display_t /*display*/, + const Hwc2TestClientTargetSupport& testClientTargetSupport) { + + const Area bufferArea = testClientTargetSupport.getBufferArea(); + const android_pixel_format_t format = HAL_PIXEL_FORMAT_RGBA_8888; + hwc2_display_t badDisplay; + hwc2_error_t err = HWC2_ERROR_NONE; + + ASSERT_NO_FATAL_FAILURE(test->getBadDisplay(&badDisplay)); + + ASSERT_NO_FATAL_FAILURE(test->getClientTargetSupport(badDisplay, + bufferArea.width, bufferArea.height, format, + testClientTargetSupport.getDataspace(), &err)); + EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code"; + }, + + advanceClientTargetSupport)); +} + +/* TESTCASE: Tests that the HWC2 either supports or returns error unsupported + * for a variety of client target values. */ +TEST_F(Hwc2Test, GET_CLIENT_TARGET_SUPPORT_unsupported) +{ + ASSERT_NO_FATAL_FAILURE(setClientTargetSupport(Hwc2TestCoverage::Complete, + [] (Hwc2Test* test, hwc2_display_t display, + const Hwc2TestClientTargetSupport& testClientTargetSupport) { + + const Area bufferArea = testClientTargetSupport.getBufferArea(); + const android_pixel_format_t format = HAL_PIXEL_FORMAT_RGBA_8888; + hwc2_error_t err = HWC2_ERROR_NONE; + + ASSERT_NO_FATAL_FAILURE(test->getClientTargetSupport(display, + bufferArea.width, bufferArea.height, format, + testClientTargetSupport.getDataspace(), &err)); + EXPECT_TRUE(err == HWC2_ERROR_NONE + || err == HWC2_ERROR_UNSUPPORTED) + << "returned wrong error code"; + }, + + advanceClientTargetSupport)); +} + +/* TESTCASE: Tests that the HWC2 can set a client target buffer for a basic + * layer. */ +TEST_F(Hwc2Test, SET_CLIENT_TARGET_basic) +{ + const android_dataspace_t dataspace = HAL_DATASPACE_UNKNOWN; + const hwc_region_t damage = { }; + const size_t layerCnt = 1; + + for (auto display : mDisplays) { + std::vector configs; + + ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_ON)); + + ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs)); + + for (auto config : configs) { + Area displayArea; + std::vector layers; + + ASSERT_NO_FATAL_FAILURE(setActiveConfig(display, config)); + ASSERT_NO_FATAL_FAILURE(getActiveDisplayArea(display, &displayArea)); + + ASSERT_NO_FATAL_FAILURE(createLayers(display, &layers, layerCnt)); + Hwc2TestLayers testLayers(layers, Hwc2TestCoverage::Basic, + displayArea); + + if (!testLayers.optimizeLayouts()) + continue; + + Hwc2TestClientTarget testClientTarget; + + do { + std::set clientLayers; + std::set clearLayers; + uint32_t numTypes, numRequests; + bool hasChanges, skip; + bool flipClientTarget; + buffer_handle_t handle; + int32_t acquireFence; + + ASSERT_NO_FATAL_FAILURE(setLayerProperties(display, layers, + &testLayers, &skip)); + if (skip) + continue; + + ASSERT_NO_FATAL_FAILURE(validateDisplay(display, &numTypes, + &numRequests, &hasChanges)); + if (hasChanges) + EXPECT_LE(numTypes, layers.size()) + << "wrong number of requests"; + + ASSERT_NO_FATAL_FAILURE(handleCompositionChanges(display, + testLayers, layers, numTypes, &clientLayers)); + ASSERT_NO_FATAL_FAILURE(handleRequests(display, layers, + numRequests, &clearLayers, &flipClientTarget)); + ASSERT_EQ(testClientTarget.getBuffer(testLayers, clientLayers, + clearLayers, flipClientTarget, displayArea, &handle, + &acquireFence), 0); + EXPECT_NO_FATAL_FAILURE(setClientTarget(display, handle, + acquireFence, dataspace, damage)); + + if (acquireFence >= 0) + close(acquireFence); + + } while (testLayers.advance()); + + ASSERT_NO_FATAL_FAILURE(destroyLayers(display, std::move(layers))); + } + + ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_OFF)); + } +} + +/* TESTCASE: Tests that the HWC2 cannot set a client target for a bad display. */ +TEST_F(Hwc2Test, SET_CLIENT_TARGET_bad_display) +{ + hwc2_display_t display; + std::vector layers; + const Area displayArea = {0, 0}; + Hwc2TestLayers testLayers(layers, Hwc2TestCoverage::Default, displayArea); + std::set clientLayers; + std::set flipClientTargetLayers; + bool flipClientTarget = true; + const android_dataspace_t dataspace = HAL_DATASPACE_UNKNOWN; + const hwc_region_t damage = { }; + buffer_handle_t handle; + int32_t acquireFence; + hwc2_error_t err = HWC2_ERROR_NONE; + + ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display)); + + Hwc2TestClientTarget testClientTarget; + + ASSERT_EQ(testClientTarget.getBuffer(testLayers, clientLayers, + flipClientTargetLayers, flipClientTarget, displayArea, &handle, + &acquireFence), 0); + + EXPECT_NO_FATAL_FAILURE(setClientTarget(display, handle, acquireFence, + dataspace, damage, &err)); + + if (acquireFence >= 0) + close(acquireFence); + + EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code"; +} diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestBuffer.cpp b/services/surfaceflinger/tests/hwc2/Hwc2TestBuffer.cpp index c9d8f4fdb7..a59f388a66 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2TestBuffer.cpp +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestBuffer.cpp @@ -330,6 +330,24 @@ static void setFence(int32_t fence, void* fenceGenerator) } +/* Sets the pixel of a buffer given the location, format, stride and color. + * Currently only supports RGBA_8888 */ +static void setColor(int32_t x, int32_t y, + android_pixel_format_t format, uint32_t stride, uint8_t* img, uint8_t r, + uint8_t g, uint8_t b, uint8_t a) +{ + switch (format) { + case HAL_PIXEL_FORMAT_RGBA_8888: + img[(y * stride + x) * 4 + 0] = r; + img[(y * stride + x) * 4 + 1] = g; + img[(y * stride + x) * 4 + 2] = b; + img[(y * stride + x) * 4 + 3] = a; + break; + default: + break; + } +} + Hwc2TestBuffer::Hwc2TestBuffer() : mFenceGenerator(new Hwc2TestFenceGenerator()) { } @@ -433,20 +451,242 @@ int Hwc2TestBuffer::generateBuffer() return 0; } -/* Sets the pixel of a buffer given the location, format, stride and color. - * Currently only supports RGBA_8888 */ -void Hwc2TestBuffer::setColor(int32_t x, int32_t y, - android_pixel_format_t format, uint32_t stride, uint8_t* img, uint8_t r, - uint8_t g, uint8_t b, uint8_t a) + +Hwc2TestClientTargetBuffer::Hwc2TestClientTargetBuffer() + : mFenceGenerator(new Hwc2TestFenceGenerator()) { } + +Hwc2TestClientTargetBuffer::~Hwc2TestClientTargetBuffer() { } + +/* Generates a client target buffer using the layers assigned for client + * composition. Takes into account the individual layer properties such as + * transform, blend mode, source crop, etc. */ +int Hwc2TestClientTargetBuffer::get(buffer_handle_t* outHandle, + int32_t* outFence, const Area& bufferArea, + const Hwc2TestLayers* testLayers, + const std::set* clientLayers, + const std::set* clearLayers) { - switch (format) { - case HAL_PIXEL_FORMAT_RGBA_8888: - img[(y * stride + x) * 4 + 0] = r; - img[(y * stride + x) * 4 + 1] = g; - img[(y * stride + x) * 4 + 2] = b; - img[(y * stride + x) * 4 + 3] = a; - break; - default: - break; - } + int err; + + /* Create new graphic buffer with updated size */ + mGraphicBuffer = mGraphicBufferAlloc.createGraphicBuffer(bufferArea.width, + bufferArea.height, mFormat, + GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_HW_RENDER, + "hwc2_test_buffer", &err); + if (err) + return err; + + uint8_t* img; + mGraphicBuffer->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img)); + + uint32_t stride = mGraphicBuffer->getStride(); + + float bWDiv3 = bufferArea.width / 3; + float bW2Div3 = bufferArea.width * 2 / 3; + float bHDiv3 = bufferArea.height / 3; + float bH2Div3 = bufferArea.height * 2 / 3; + + /* Cycle through every pixel in the buffer and determine what color it + * should be. */ + for (int32_t y = 0; y < bufferArea.height; y++) { + for (int32_t x = 0; x < bufferArea.width; x++) { + + uint8_t r = 0, g = 0, b = 0; + float a = 0.0f; + + /* Cycle through each client layer from back to front and + * update the pixel color. */ + for (auto layer = clientLayers->rbegin(); + layer != clientLayers->rend(); ++layer) { + + const hwc_rect_t df = testLayers->getDisplayFrame(*layer); + + float dfL = df.left; + float dfT = df.top; + float dfR = df.right; + float dfB = df.bottom; + + /* If the pixel location falls outside of the layer display + * frame, skip the layer. */ + if (x < dfL || x >= dfR || y < dfT || y >= dfB) + continue; + + /* If the device has requested the layer be clear, clear + * the pixel and continue. */ + if (clearLayers->count(*layer) != 0) { + r = 0; + g = 0; + b = 0; + a = 0.0f; + continue; + } + + float planeAlpha = testLayers->getPlaneAlpha(*layer); + + /* If the layer is a solid color, fill the color and + * continue. */ + if (testLayers->getComposition(*layer) + == HWC2_COMPOSITION_SOLID_COLOR) { + const auto color = testLayers->getColor(*layer); + r = color.r; + g = color.g; + b = color.b; + a = color.a * planeAlpha; + continue; + } + + float xPos = x; + float yPos = y; + + hwc_transform_t transform = testLayers->getTransform(*layer); + + float dfW = dfR - dfL; + float dfH = dfB - dfT; + + /* If a layer has a transform, find which location on the + * layer will end up in the current pixel location. We + * can calculate the color of the current pixel using that + * location. */ + if (transform > 0) { + /* Change origin to be the center of the layer. */ + xPos = xPos - dfL - dfW / 2.0; + yPos = yPos - dfT - dfH / 2.0; + + /* Flip Horizontal by reflecting across the y axis. */ + if (transform & HWC_TRANSFORM_FLIP_H) + xPos = -xPos; + + /* Flip vertical by reflecting across the x axis. */ + if (transform & HWC_TRANSFORM_FLIP_V) + yPos = -yPos; + + /* Rotate 90 by using a basic linear algebra rotation + * and scaling the result so the display frame remains + * the same. For example, a buffer of size 100x50 should + * rotate 90 degress but remain the same dimension + * (100x50) at the end of the transformation. */ + if (transform & HWC_TRANSFORM_ROT_90) { + float tmp = xPos; + xPos = -yPos * dfW / dfH; + yPos = tmp * dfH / dfW; + } + + /* Change origin back to the top left corner of the + * layer. */ + xPos = xPos + dfL + dfW / 2.0; + yPos = yPos + dfT + dfH / 2.0; + } + + hwc_frect_t sc = testLayers->getSourceCrop(*layer); + float scL = sc.left, scT = sc.top; + + float dfWDivScW = dfW / (sc.right - scL); + float dfHDivScH = dfH / (sc.bottom - scT); + + float max = 255, min = 0; + + /* Choose the pixel color. Similar to generateBuffer, + * each layer will be divided into 3x3 colors. Because + * both the source crop and display frame must be taken into + * account, the formulas are more complicated. + * + * If the source crop and display frame were not taken into + * account, we would simply divide the buffer into three + * sections by height. Each section would get one color. + * For example the formula for the first section would be: + * + * if (yPos < bufferArea.height / 3) + * //Select first section color + * + * However the pixel color is chosen based on the source + * crop and displayed based on the display frame. + * + * If the display frame top was 0 and the source crop height + * and display frame height were the same. The only factor + * would be the source crop top. To calculate the new + * section boundary, the section boundary would be moved up + * by the height of the source crop top. The formula would + * be: + * if (yPos < (bufferArea.height / 3 - sourceCrop.top) + * //Select first section color + * + * If the display frame top could also vary but source crop + * and display frame heights were the same, the formula + * would be: + * if (yPos < (bufferArea.height / 3 - sourceCrop.top + * + displayFrameTop) + * //Select first section color + * + * If the heights were not the same, the conversion between + * the source crop and display frame dimensions must be + * taken into account. The formula would be: + * if (yPos < ((bufferArea.height / 3) - sourceCrop.top) + * * displayFrameHeight / sourceCropHeight + * + displayFrameTop) + * //Select first section color + */ + if (yPos < ((bHDiv3) - scT) * dfHDivScH + dfT) { + min = 255 / 2; + } else if (yPos >= ((bH2Div3) - scT) * dfHDivScH + dfT) { + max = 255 / 2; + } + + uint8_t rCur = min, gCur = min, bCur = min; + float aCur = 1.0f; + + /* This further divides the color sections from 3 to 3x3. + * The math behind it follows the same logic as the previous + * comment */ + if (xPos < ((bWDiv3) - scL) * (dfWDivScW) + dfL) { + rCur = max; + } else if (xPos < ((bW2Div3) - scL) * (dfWDivScW) + dfL) { + gCur = max; + } else { + bCur = max; + } + + + /* Blend the pixel color with the previous layers' pixel + * colors using the plane alpha and blend mode. The final + * pixel color is chosen using the plane alpha and blend + * mode formulas found in hwcomposer2.h */ + hwc2_blend_mode_t blendMode = testLayers->getBlendMode(*layer); + + if (blendMode == HWC2_BLEND_MODE_PREMULTIPLIED) { + rCur *= planeAlpha; + gCur *= planeAlpha; + bCur *= planeAlpha; + } + + aCur *= planeAlpha; + + if (blendMode == HWC2_BLEND_MODE_PREMULTIPLIED) { + r = rCur + r * (1.0 - aCur); + g = gCur + g * (1.0 - aCur); + b = bCur + b * (1.0 - aCur); + a = aCur + a * (1.0 - aCur); + } else if (blendMode == HWC2_BLEND_MODE_COVERAGE) { + r = rCur * aCur + r * (1.0 - aCur); + g = gCur * aCur + g * (1.0 - aCur); + b = bCur * aCur + b * (1.0 - aCur); + a = aCur * aCur + a * (1.0 - aCur); + } else { + r = rCur; + g = gCur; + b = bCur; + a = aCur; + } + } + + /* Set the pixel color */ + setColor(x, y, mFormat, stride, img, r, g, b, a * 255); + } + } + + mGraphicBuffer->unlock(); + + *outFence = mFenceGenerator->get(); + *outHandle = mGraphicBuffer->handle; + + return 0; } diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestBuffer.h b/services/surfaceflinger/tests/hwc2/Hwc2TestBuffer.h index 721540fa42..ca60940aa9 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2TestBuffer.h +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestBuffer.h @@ -18,6 +18,8 @@ #define _HWC2_TEST_BUFFER_H #include +#include + #include #include @@ -26,6 +28,7 @@ #include "Hwc2TestProperties.h" class Hwc2TestFenceGenerator; +class Hwc2TestLayers; class Hwc2TestBuffer { public: @@ -39,10 +42,6 @@ public: protected: int generateBuffer(); - void setColor(int32_t x, int32_t y, android_pixel_format_t format, - uint32_t stride, uint8_t* img, uint8_t r, uint8_t g, uint8_t b, - uint8_t a); - android::GraphicBufferAlloc mGraphicBufferAlloc; android::sp mGraphicBuffer; @@ -55,4 +54,24 @@ protected: buffer_handle_t mHandle = nullptr; }; + +class Hwc2TestClientTargetBuffer { +public: + Hwc2TestClientTargetBuffer(); + ~Hwc2TestClientTargetBuffer(); + + int get(buffer_handle_t* outHandle, int32_t* outFence, + const Area& bufferArea, const Hwc2TestLayers* testLayers, + const std::set* clientLayers, + const std::set* clearLayers); + +protected: + android::GraphicBufferAlloc mGraphicBufferAlloc; + android::sp mGraphicBuffer; + + std::unique_ptr mFenceGenerator; + + const android_pixel_format_t mFormat = HAL_PIXEL_FORMAT_RGBA_8888; +}; + #endif /* ifndef _HWC2_TEST_BUFFER_H */ diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestClientTarget.cpp b/services/surfaceflinger/tests/hwc2/Hwc2TestClientTarget.cpp new file mode 100644 index 0000000000..69254921d4 --- /dev/null +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestClientTarget.cpp @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include + +#include "Hwc2TestClientTarget.h" + +int Hwc2TestClientTarget::getBuffer(const Hwc2TestLayers& testLayers, + const std::set& clientLayers, + const std::set& clearLayers, bool flipClientTarget, + const Area& displayArea, buffer_handle_t* outHandle, + int32_t* outAcquireFence) +{ + if (!flipClientTarget) { + bool needsClientTarget = false; + + for (auto clientLayer : clientLayers) { + if (testLayers.getVisibleRegion(clientLayer).numRects > 0) { + needsClientTarget = true; + break; + } + } + + if (!needsClientTarget) { + *outHandle = nullptr; + *outAcquireFence = -1; + return 0; + } + } + + return mBuffer.get(outHandle, outAcquireFence, displayArea, + &testLayers, &clientLayers, &clearLayers); +} + + +Hwc2TestClientTargetSupport::Hwc2TestClientTargetSupport( + Hwc2TestCoverage coverage, const Area& displayArea) + : mBufferArea(coverage, displayArea), + mDataspace(coverage), + mSurfaceDamage(coverage) +{ + mBufferArea.setDependent(&mSurfaceDamage); +} + +std::string Hwc2TestClientTargetSupport::dump() const +{ + std::stringstream dmp; + + dmp << "client target: \n"; + + for (auto property : properties) { + dmp << property->dump(); + } + + return dmp.str(); +} + +void Hwc2TestClientTargetSupport::reset() +{ + for (auto property : properties) { + property->reset(); + } +} + +bool Hwc2TestClientTargetSupport::advance() +{ + for (auto property : properties) { + if (property->advance()) + return true; + } + return false; +} + +Area Hwc2TestClientTargetSupport::getBufferArea() const +{ + return mBufferArea.get(); +} + +android_dataspace_t Hwc2TestClientTargetSupport::getDataspace() const +{ + return mDataspace.get(); +} + +const hwc_region_t Hwc2TestClientTargetSupport::getSurfaceDamage() const +{ + return mSurfaceDamage.get(); +} diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestClientTarget.h b/services/surfaceflinger/tests/hwc2/Hwc2TestClientTarget.h new file mode 100644 index 0000000000..3b47978bef --- /dev/null +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestClientTarget.h @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _HWC2_TEST_CLIENT_TARGET_H +#define _HWC2_TEST_CLIENT_TARGET_H + +#include + +#define HWC2_INCLUDE_STRINGIFICATION +#define HWC2_USE_CPP11 +#include +#undef HWC2_INCLUDE_STRINGIFICATION +#undef HWC2_USE_CPP11 + +#include "Hwc2TestProperties.h" +#include "Hwc2TestLayers.h" + +/* Generates client target buffers from client composition layers */ +class Hwc2TestClientTarget { +public: + int getBuffer(const Hwc2TestLayers& layers, + const std::set& clientLayers, + const std::set& clearLayers, + bool clearClientTarget, const Area& displayArea, + buffer_handle_t* outHandle, int32_t* outAcquireFence); + +private: + Hwc2TestClientTargetBuffer mBuffer; +}; + +/* Generates valid client targets to test which ones the device will support */ +class Hwc2TestClientTargetSupport { +public: + Hwc2TestClientTargetSupport(Hwc2TestCoverage coverage, + const Area& displayArea); + + std::string dump() const; + + void reset(); + bool advance(); + + Area getBufferArea() const; + android_dataspace_t getDataspace() const; + const hwc_region_t getSurfaceDamage() const; + +private: + std::array properties = {{ + &mDataspace, &mSurfaceDamage, &mBufferArea + }}; + + Hwc2TestBufferArea mBufferArea; + Hwc2TestDataspace mDataspace; + Hwc2TestSurfaceDamage mSurfaceDamage; +}; + +#endif /* ifndef _HWC2_TEST_CLIENT_TARGET_H */ diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.cpp b/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.cpp index 9d91f88da1..96cd98d0a7 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.cpp +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.cpp @@ -60,28 +60,54 @@ void Hwc2TestLayers::reset() bool Hwc2TestLayers::advance() { - for (auto& testLayer : mTestLayers) { - if (testLayer.second.advance()) { - setVisibleRegions(); - return true; + auto itr = mTestLayers.begin(); + bool optimized; + + while (itr != mTestLayers.end()) { + if (itr->second.advance()) { + optimized = setVisibleRegions(); + if (!mOptimize || optimized) + return true; + itr = mTestLayers.begin(); + } else { + itr->second.reset(); + ++itr; } - testLayer.second.reset(); } return false; } bool Hwc2TestLayers::advanceVisibleRegions() { - for (auto& testLayer : mTestLayers) { - if (testLayer.second.advanceVisibleRegion()) { - setVisibleRegions(); - return true; + auto itr = mTestLayers.begin(); + bool optimized; + + while (itr != mTestLayers.end()) { + if (itr->second.advanceVisibleRegion()) { + optimized = setVisibleRegions(); + if (!mOptimize || optimized) + return true; + itr = mTestLayers.begin(); + } else { + itr->second.reset(); + ++itr; } - testLayer.second.reset(); } return false; } +/* Removes layouts that do not cover the entire display. + * Also removes layouts where a layer is completely blocked from view. + */ +bool Hwc2TestLayers::optimizeLayouts() +{ + mOptimize = true; + + if (setVisibleRegions()) + return true; + return advance(); +} + bool Hwc2TestLayers::contains(hwc2_layer_t layer) const { return mTestLayers.count(layer) != 0; @@ -104,6 +130,14 @@ hwc2_blend_mode_t Hwc2TestLayers::getBlendMode(hwc2_layer_t layer) const return mTestLayers.at(layer).getBlendMode(); } +Area Hwc2TestLayers::getBufferArea(hwc2_layer_t layer) const +{ + auto testLayer = mTestLayers.find(layer); + if (testLayer == mTestLayers.end()) + [] () { GTEST_FAIL(); }(); + return testLayer->second.getBufferArea(); +} + hwc_color_t Hwc2TestLayers::getColor(hwc2_layer_t layer) const { if (mTestLayers.count(layer) == 0) { @@ -192,12 +226,16 @@ uint32_t Hwc2TestLayers::getZOrder(hwc2_layer_t layer) const return mTestLayers.at(layer).getZOrder(); } -void Hwc2TestLayers::setVisibleRegions() +/* Sets the visible regions for a display. Returns false if the layers do not + * cover the entire display or if a layer is not visible */ +bool Hwc2TestLayers::setVisibleRegions() { /* The region of the display that is covered by layers above the current * layer */ android::Region aboveOpaqueLayers; + bool optimized = true; + /* Iterate over test layers from max z order to min z order. */ for (auto& testLayer : mTestLayers) { android::Region visibleRegion; @@ -214,8 +252,23 @@ void Hwc2TestLayers::setVisibleRegions() testLayer.second.setVisibleRegion(visibleRegion); + /* If a layer is not visible, return false */ + if (visibleRegion.isEmpty()) + optimized = false; + /* If this layer is opaque, store the region it covers */ if (testLayer.second.getPlaneAlpha() == 1.0f) aboveOpaqueLayers.orSelf(visibleRegion); } + + /* If the opaque region does not cover the entire display return false */ + if (!aboveOpaqueLayers.isRect()) + return false; + + const auto rect = aboveOpaqueLayers.begin(); + if (rect->left != 0 || rect->top != 0 || rect->right != mDisplayArea.width + || rect->bottom != mDisplayArea.height) + return false; + + return optimized; } diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.h b/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.h index b4c3558a36..a8579ee765 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.h +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.h @@ -40,12 +40,21 @@ public: bool advance(); bool advanceVisibleRegions(); + /* Test cases with multiple layers and property values can take quite some + * time to run. A significant amount of time can be spent on test cases + * where one layer is changing property values but is not visible. To + * decrease runtime, this function can be called. Removes layouts where a + * layer is completely blocked from view. It also removes layouts that do + * not cover the entire display.*/ + bool optimizeLayouts(); + bool contains(hwc2_layer_t layer) const; int getBuffer(hwc2_layer_t layer, buffer_handle_t* outHandle, int32_t* outAcquireFence); hwc2_blend_mode_t getBlendMode(hwc2_layer_t layer) const; + Area getBufferArea(hwc2_layer_t layer) const; hwc_color_t getColor(hwc2_layer_t layer) const; hwc2_composition_t getComposition(hwc2_layer_t layer) const; hwc_rect_t getCursorPosition(hwc2_layer_t layer) const; @@ -60,11 +69,13 @@ public: uint32_t getZOrder(hwc2_layer_t layer) const; private: - void setVisibleRegions(); + bool setVisibleRegions(); std::map mTestLayers; Area mDisplayArea; + + bool mOptimize = false; }; #endif /* ifndef _HWC2_TEST_LAYERS_H */ -- cgit v1.2.3-59-g8ed1b From 563030b4402f4b9aa08cece732f2a4a756a0f72c Mon Sep 17 00:00:00 2001 From: Marissa Wall Date: Tue, 21 Feb 2017 14:01:05 -0800 Subject: test-hwc2: present display Test: Add "#define HAVE_NO_SURFACE_FLINGER" to frameworks/native/libs/gui/BufferQueueCore.cpp. Recompile and flash. Run "mm" in frameworks/native/services/surfaceflinger/tests/hwc2. Push test-hwc2 to device. Run "adb root && adb shell stop". Run test case. Ex: "./test-hwc2" Change-Id: I845320afdf635d1716310d1183bcb10515615517 --- services/surfaceflinger/tests/hwc2/Android.mk | 3 +- services/surfaceflinger/tests/hwc2/Hwc2Test.cpp | 668 +++++++++++++++++++-- .../surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp | 46 +- services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h | 5 + .../surfaceflinger/tests/hwc2/Hwc2TestLayers.cpp | 9 +- .../surfaceflinger/tests/hwc2/Hwc2TestLayers.h | 5 + .../surfaceflinger/tests/hwc2/Hwc2TestProperties.h | 14 + 7 files changed, 702 insertions(+), 48 deletions(-) diff --git a/services/surfaceflinger/tests/hwc2/Android.mk b/services/surfaceflinger/tests/hwc2/Android.mk index 329e124514..f7403cfe67 100644 --- a/services/surfaceflinger/tests/hwc2/Android.mk +++ b/services/surfaceflinger/tests/hwc2/Android.mk @@ -35,7 +35,8 @@ LOCAL_SHARED_LIBRARIES := \ libGLESv2 \ libui \ libgui \ - liblog + liblog \ + libsync LOCAL_STATIC_LIBRARIES := \ libbase \ libadf \ diff --git a/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp index 9171de2b5d..600c4540af 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp +++ b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp @@ -16,10 +16,12 @@ #include #include +#include #include #include #include #include +#include #define HWC2_INCLUDE_STRINGIFICATION #define HWC2_USE_CPP11 @@ -808,6 +810,50 @@ public: } } + void presentDisplay(hwc2_display_t display, int32_t* outPresentFence, + hwc2_error_t* outErr = nullptr) + { + auto pfn = reinterpret_cast( + getFunction(HWC2_FUNCTION_PRESENT_DISPLAY)); + ASSERT_TRUE(pfn) << "failed to get function"; + + auto err = static_cast(pfn(mHwc2Device, display, + outPresentFence)); + if (outErr) { + *outErr = err; + } else { + ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to present display"; + } + } + + void getReleaseFences(hwc2_display_t display, + std::vector* outLayers, + std::vector* outFences, hwc2_error_t* outErr = nullptr) + { + auto pfn = reinterpret_cast( + getFunction(HWC2_FUNCTION_GET_RELEASE_FENCES)); + ASSERT_TRUE(pfn) << "failed to get function"; + + uint32_t numElements = 0; + + auto err = static_cast(pfn(mHwc2Device, display, + &numElements, nullptr, nullptr)); + + if (err == HWC2_ERROR_NONE) { + outLayers->resize(numElements); + outFences->resize(numElements); + + err = static_cast(pfn(mHwc2Device, display, + &numElements, outLayers->data(), outFences->data())); + } + + if (outErr) { + *outErr = err; + } else { + ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to get release fences"; + } + } + void getBadDisplay(hwc2_display_t* outDisplay) { for (hwc2_display_t display = 0; display < UINT64_MAX; display++) { @@ -820,6 +866,32 @@ public: " are registered. This should never happen."; } + void waitForVsync(hwc2_display_t* outDisplay = nullptr, + int64_t* outTimestamp = nullptr) + { + std::unique_lock lock(mVsyncMutex); + ASSERT_EQ(mVsyncCv.wait_for(lock, std::chrono::seconds(3)), + std::cv_status::no_timeout) << "timed out attempting to get" + " vsync callback"; + if (outDisplay) + *outDisplay = mVsyncDisplay; + if (outTimestamp) + *outTimestamp = mVsyncTimestamp; + } + + void enableVsync(hwc2_display_t display) + { + ASSERT_NO_FATAL_FAILURE(registerCallback(HWC2_CALLBACK_VSYNC, this, + reinterpret_cast( + hwc2TestVsyncCallback))); + ASSERT_NO_FATAL_FAILURE(setVsyncEnabled(display, HWC2_VSYNC_ENABLE)); + } + + void disableVsync(hwc2_display_t display) + { + ASSERT_NO_FATAL_FAILURE(setVsyncEnabled(display, HWC2_VSYNC_DISABLE)); + } + protected: hwc2_function_pointer_t getFunction(hwc2_function_descriptor_t descriptor) { @@ -919,32 +991,6 @@ protected: *outConfig = config; } - void enableVsync(hwc2_display_t display) - { - ASSERT_NO_FATAL_FAILURE(registerCallback(HWC2_CALLBACK_VSYNC, this, - reinterpret_cast( - hwc2TestVsyncCallback))); - ASSERT_NO_FATAL_FAILURE(setVsyncEnabled(display, HWC2_VSYNC_ENABLE)); - } - - void disableVsync(hwc2_display_t display) - { - ASSERT_NO_FATAL_FAILURE(setVsyncEnabled(display, HWC2_VSYNC_DISABLE)); - } - - void waitForVsync(hwc2_display_t* outDisplay = nullptr, - int64_t* outTimestamp = nullptr) - { - std::unique_lock lock(mVsyncMutex); - ASSERT_EQ(mVsyncCv.wait_for(lock, std::chrono::seconds(3)), - std::cv_status::no_timeout) << "timed out attempting to get" - " vsync callback"; - if (outDisplay) - *outDisplay = mVsyncDisplay; - if (outTimestamp) - *outTimestamp = mVsyncTimestamp; - } - /* Calls a set property function from Hwc2Test to set a property value from * Hwc2TestLayer to hwc2_layer_t on hwc2_display_t */ using TestLayerPropertyFunction = void (*)(Hwc2Test* test, @@ -973,7 +1019,7 @@ protected: * changes, present, etc. */ using TestDisplayLayersFunction = void (*)(Hwc2Test* test, hwc2_display_t display, const std::vector& layers, - const Hwc2TestLayers& testLayers); + Hwc2TestLayers* testLayers); /* It is called on an non validated display */ using TestDisplayNonValidatedLayersFunction = void (*)(Hwc2Test* test, @@ -1195,7 +1241,7 @@ protected: &testLayers, &skip)); if (!skip) EXPECT_NO_FATAL_FAILURE(function(this, display, layers, - testLayers)); + &testLayers)); } while (testLayers.advance()); @@ -1298,6 +1344,27 @@ protected: HWC2_ATTRIBUTE_HEIGHT, &displayArea->height)); } + void closeFences(hwc2_display_t display, int32_t presentFence) + { + std::vector layers; + std::vector fences; + const int msWait = 3000; + + if (presentFence >= 0) { + ASSERT_GE(sync_wait(presentFence, msWait), 0); + close(presentFence); + } + + ASSERT_NO_FATAL_FAILURE(getReleaseFences(display, &layers, &fences)); + EXPECT_EQ(layers.size(), fences.size()); + + for (int32_t fence : fences) { + EXPECT_GE(sync_wait(fence, msWait), 0); + if (fence >= 0) + close(fence); + } + } + void setLayerProperties(hwc2_display_t display, hwc2_layer_t layer, Hwc2TestLayers* testLayers, bool* outSkip) { @@ -1366,6 +1433,100 @@ protected: } } + void setClientTarget(hwc2_display_t display, + Hwc2TestClientTarget* testClientTarget, + const Hwc2TestLayers& testLayers, + const std::set& clientLayers, + const std::set& clearLayers, bool flipClientTarget, + const Area& displayArea) + { + android_dataspace_t dataspace = HAL_DATASPACE_UNKNOWN; + hwc_region_t damage = { }; + buffer_handle_t handle; + int32_t acquireFence; + + ASSERT_EQ(testClientTarget->getBuffer(testLayers, clientLayers, + clearLayers, flipClientTarget, displayArea, &handle, + &acquireFence), 0); + EXPECT_NO_FATAL_FAILURE(setClientTarget(display, handle, acquireFence, + dataspace, damage)); + } + + void presentDisplays(size_t layerCnt, Hwc2TestCoverage coverage, + const std::unordered_map& + coverageExceptions, bool optimize) + { + for (auto display : mDisplays) { + std::vector configs; + + ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_ON)); + ASSERT_NO_FATAL_FAILURE(enableVsync(display)); + + ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs)); + + for (auto config : configs) { + Area displayArea; + std::vector layers; + + ASSERT_NO_FATAL_FAILURE(setActiveConfig(display, config)); + ASSERT_NO_FATAL_FAILURE(getActiveDisplayArea(display, + &displayArea)); + + ASSERT_NO_FATAL_FAILURE(createLayers(display, &layers, layerCnt)); + Hwc2TestLayers testLayers(layers, coverage, displayArea, + coverageExceptions); + + if (optimize && !testLayers.optimizeLayouts()) + continue; + + std::set clientLayers; + std::set clearLayers; + Hwc2TestClientTarget testClientTarget; + + do { + uint32_t numTypes, numRequests; + bool hasChanges, skip; + bool flipClientTarget; + int32_t presentFence; + + ASSERT_NO_FATAL_FAILURE(setLayerProperties(display, layers, + &testLayers, &skip)); + if (skip) + continue; + + ASSERT_NO_FATAL_FAILURE(validateDisplay(display, &numTypes, + &numRequests, &hasChanges)); + if (hasChanges) + EXPECT_LE(numTypes, static_cast(layers.size())) + << "wrong number of requests"; + + ASSERT_NO_FATAL_FAILURE(handleCompositionChanges(display, + testLayers, layers, numTypes, &clientLayers)); + ASSERT_NO_FATAL_FAILURE(handleRequests(display, layers, + numRequests, &clearLayers, &flipClientTarget)); + ASSERT_NO_FATAL_FAILURE(setClientTarget(display, + &testClientTarget, testLayers, clientLayers, + clearLayers, flipClientTarget, displayArea)); + ASSERT_NO_FATAL_FAILURE(acceptDisplayChanges(display)); + + ASSERT_NO_FATAL_FAILURE(waitForVsync()); + + EXPECT_NO_FATAL_FAILURE(presentDisplay(display, + &presentFence)); + + ASSERT_NO_FATAL_FAILURE(closeFences(display, presentFence)); + + } while (testLayers.advance()); + + ASSERT_NO_FATAL_FAILURE(destroyLayers(display, + std::move(layers))); + } + + ASSERT_NO_FATAL_FAILURE(disableVsync(display)); + ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_OFF)); + } + } + hwc2_device_t* mHwc2Device = nullptr; enum class Hwc2TestHotplugStatus { @@ -2870,7 +3031,7 @@ TEST_F(Hwc2Test, VALIDATE_DISPLAY_basic) ASSERT_NO_FATAL_FAILURE(displayLayers(Hwc2TestCoverage::Basic, 1, [] (Hwc2Test* test, hwc2_display_t display, const std::vector& layers, - const Hwc2TestLayers& /*testLayers*/) { + Hwc2TestLayers* /*testLayers*/) { uint32_t numTypes, numRequests; bool hasChanges = false; @@ -2890,7 +3051,7 @@ TEST_F(Hwc2Test, VALIDATE_DISPLAY_default_5) ASSERT_NO_FATAL_FAILURE(displayLayers(Hwc2TestCoverage::Default, 5, [] (Hwc2Test* test, hwc2_display_t display, const std::vector& layers, - const Hwc2TestLayers& /*testLayers*/) { + Hwc2TestLayers* /*testLayers*/) { uint32_t numTypes, numRequests; bool hasChanges = false; @@ -2925,7 +3086,7 @@ TEST_F(Hwc2Test, GET_DISPLAY_REQUESTS_basic) ASSERT_NO_FATAL_FAILURE(displayLayers(Hwc2TestCoverage::Basic, 1, [] (Hwc2Test* test, hwc2_display_t display, const std::vector& layers, - const Hwc2TestLayers& /*testLayers*/) { + Hwc2TestLayers* /*testLayers*/) { uint32_t numTypes, numRequests; bool hasChanges = false; @@ -2985,7 +3146,7 @@ TEST_F(Hwc2Test, GET_CHANGED_COMPOSITION_TYPES_basic) ASSERT_NO_FATAL_FAILURE(displayLayers(Hwc2TestCoverage::Basic, 1, [] (Hwc2Test* test, hwc2_display_t display, const std::vector& layers, - const Hwc2TestLayers& testLayers) { + Hwc2TestLayers* testLayers) { uint32_t numTypes, numRequests; bool hasChanges = false; @@ -2997,7 +3158,7 @@ TEST_F(Hwc2Test, GET_CHANGED_COMPOSITION_TYPES_basic) << "wrong number of requests"; EXPECT_NO_FATAL_FAILURE(test->handleCompositionChanges(display, - testLayers, layers, numTypes)); + *testLayers, layers, numTypes)); } )); } @@ -3044,7 +3205,7 @@ TEST_F(Hwc2Test, ACCEPT_DISPLAY_CHANGES_basic) ASSERT_NO_FATAL_FAILURE(displayLayers(Hwc2TestCoverage::Basic, 1, [] (Hwc2Test* test, hwc2_display_t display, const std::vector& layers, - const Hwc2TestLayers& testLayers) { + Hwc2TestLayers* testLayers) { uint32_t numTypes, numRequests; bool hasChanges = false; @@ -3056,7 +3217,7 @@ TEST_F(Hwc2Test, ACCEPT_DISPLAY_CHANGES_basic) << "wrong number of requests"; ASSERT_NO_FATAL_FAILURE(test->handleCompositionChanges(display, - testLayers, layers, numTypes)); + *testLayers, layers, numTypes)); EXPECT_NO_FATAL_FAILURE(test->acceptDisplayChanges(display)); } @@ -3263,3 +3424,440 @@ TEST_F(Hwc2Test, SET_CLIENT_TARGET_bad_display) EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code"; } + +/* TESTCASE: Tests that the HWC2 can present 1 default layer. */ +TEST_F(Hwc2Test, PRESENT_DISPLAY_default_1) +{ + const size_t layerCnt = 1; + Hwc2TestCoverage coverage = Hwc2TestCoverage::Default; + std::unordered_map exceptions; + bool optimize = false; + + ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions, + optimize)); +} + +/* TESTCASE: Tests that the HWC2 can present 2 default layers. */ +TEST_F(Hwc2Test, PRESENT_DISPLAY_default_2) +{ + const size_t layerCnt = 2; + Hwc2TestCoverage coverage = Hwc2TestCoverage::Default; + std::unordered_map exceptions; + bool optimize = false; + + ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions, + optimize)); +} + +/* TESTCASE: Tests that the HWC2 can present 3 default layers. */ +TEST_F(Hwc2Test, PRESENT_DISPLAY_default_3) +{ + const size_t layerCnt = 3; + Hwc2TestCoverage coverage = Hwc2TestCoverage::Default; + std::unordered_map exceptions; + bool optimize = false; + + ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions, + optimize)); +} + +/* TESTCASE: Tests that the HWC2 can present 4 default layers. */ +TEST_F(Hwc2Test, PRESENT_DISPLAY_default_4) +{ + const size_t layerCnt = 4; + Hwc2TestCoverage coverage = Hwc2TestCoverage::Default; + std::unordered_map exceptions; + bool optimize = false; + + ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions, + optimize)); +} + +/* TESTCASE: Tests that the HWC2 can present 5 default layers. */ +TEST_F(Hwc2Test, PRESENT_DISPLAY_default_5) +{ + const size_t layerCnt = 5; + Hwc2TestCoverage coverage = Hwc2TestCoverage::Default; + std::unordered_map exceptions; + bool optimize = false; + + ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions, + optimize)); +} + +/* TESTCASE: Tests that the HWC2 can present 6 default layers. */ +TEST_F(Hwc2Test, PRESENT_DISPLAY_default_6) +{ + const size_t layerCnt = 6; + Hwc2TestCoverage coverage = Hwc2TestCoverage::Default; + std::unordered_map exceptions; + bool optimize = false; + + ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions, + optimize)); +} + +/* TESTCASE: Tests that the HWC2 can present 1 layer with complete coverage of + * blend mode. */ +TEST_F(Hwc2Test, PRESENT_DISPLAY_blend_mode_1) +{ + const size_t layerCnt = 1; + Hwc2TestCoverage coverage = Hwc2TestCoverage::Default; + std::unordered_map exceptions = + {{Hwc2TestPropertyName::BlendMode, Hwc2TestCoverage::Complete}, + {Hwc2TestPropertyName::Transform, Hwc2TestCoverage::Basic}, + {Hwc2TestPropertyName::PlaneAlpha, Hwc2TestCoverage::Basic}}; + bool optimize = false; + + ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions, + optimize)); +} + +/* TESTCASE: Tests that the HWC2 can present 2 layers with complete coverage of + * blend mode. */ +TEST_F(Hwc2Test, PRESENT_DISPLAY_blend_mode_2) +{ + const size_t layerCnt = 2; + Hwc2TestCoverage coverage = Hwc2TestCoverage::Default; + std::unordered_map exceptions = + {{Hwc2TestPropertyName::BlendMode, Hwc2TestCoverage::Complete}, + {Hwc2TestPropertyName::PlaneAlpha, Hwc2TestCoverage::Basic}}; + bool optimize = false; + + ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions, + optimize)); +} + +/* TESTCASE: Tests that the HWC2 can present 1 layer with complete coverage of + * buffer. */ +TEST_F(Hwc2Test, PRESENT_DISPLAY_buffer_1) +{ + const size_t layerCnt = 1; + Hwc2TestCoverage coverage = Hwc2TestCoverage::Default; + std::unordered_map exceptions = + {{Hwc2TestPropertyName::BufferArea, Hwc2TestCoverage::Complete}}; + bool optimize = true; + + ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions, + optimize)); +} + +/* TESTCASE: Tests that the HWC2 can present 1 layer with complete coverage of + * color. */ +TEST_F(Hwc2Test, PRESENT_DISPLAY_color_1) +{ + const size_t layerCnt = 1; + Hwc2TestCoverage coverage = Hwc2TestCoverage::Default; + std::unordered_map exceptions = + {{Hwc2TestPropertyName::Composition, Hwc2TestCoverage::Complete}, + {Hwc2TestPropertyName::Color, Hwc2TestCoverage::Complete}}; + bool optimize = true; + + ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions, + optimize)); +} + +/* TESTCASE: Tests that the HWC2 can present 2 layers with complete coverage of + * color. */ +TEST_F(Hwc2Test, PRESENT_DISPLAY_color_2) +{ + const size_t layerCnt = 2; + Hwc2TestCoverage coverage = Hwc2TestCoverage::Default; + std::unordered_map exceptions = + {{Hwc2TestPropertyName::Composition, Hwc2TestCoverage::Complete}, + {Hwc2TestPropertyName::BlendMode, Hwc2TestCoverage::Basic}, + {Hwc2TestPropertyName::PlaneAlpha, Hwc2TestCoverage::Basic}, + {Hwc2TestPropertyName::Color, Hwc2TestCoverage::Basic}}; + bool optimize = true; + + ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions, + optimize)); +} + +/* TESTCASE: Tests that the HWC2 can present 1 layer with complete coverage of + * composition. */ +TEST_F(Hwc2Test, PRESENT_DISPLAY_composition_1) +{ + const size_t layerCnt = 1; + Hwc2TestCoverage coverage = Hwc2TestCoverage::Default; + std::unordered_map exceptions = + {{Hwc2TestPropertyName::Composition, Hwc2TestCoverage::Complete}}; + bool optimize = true; + + ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions, + optimize)); +} + +/* TESTCASE: Tests that the HWC2 can present 1 layer with complete coverage of + * cursor. */ +TEST_F(Hwc2Test, PRESENT_DISPLAY_cursor_1) +{ + const size_t layerCnt = 1; + Hwc2TestCoverage coverage = Hwc2TestCoverage::Default; + std::unordered_map exceptions = + {{Hwc2TestPropertyName::Composition, Hwc2TestCoverage::Complete}, + {Hwc2TestPropertyName::CursorPosition, Hwc2TestCoverage::Complete}}; + bool optimize = true; + + ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions, + optimize)); +} + +/* TESTCASE: Tests that the HWC2 can present 2 layers with complete coverage of + * cursor. */ +TEST_F(Hwc2Test, PRESENT_DISPLAY_cursor_2) +{ + const size_t layerCnt = 2; + Hwc2TestCoverage coverage = Hwc2TestCoverage::Default; + std::unordered_map exceptions = + {{Hwc2TestPropertyName::Composition, Hwc2TestCoverage::Complete}, + {Hwc2TestPropertyName::CursorPosition, Hwc2TestCoverage::Complete}, + {Hwc2TestPropertyName::DisplayFrame, Hwc2TestCoverage::Basic}}; + bool optimize = true; + + ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions, + optimize)); +} + +/* TESTCASE: Tests that the HWC2 can present 1 layer with complete coverage of + * dataspace. */ +TEST_F(Hwc2Test, PRESENT_DISPLAY_dataspace_1) +{ + const size_t layerCnt = 1; + Hwc2TestCoverage coverage = Hwc2TestCoverage::Default; + std::unordered_map exceptions = + {{Hwc2TestPropertyName::Dataspace, Hwc2TestCoverage::Complete}}; + bool optimize = true; + + ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions, + optimize)); +} + +/* TESTCASE: Tests that the HWC2 can present 1 layer with complete coverage of + * display frame. */ +TEST_F(Hwc2Test, PRESENT_DISPLAY_display_frame_1) +{ + const size_t layerCnt = 1; + Hwc2TestCoverage coverage = Hwc2TestCoverage::Default; + std::unordered_map exceptions = + {{Hwc2TestPropertyName::DisplayFrame, Hwc2TestCoverage::Complete}}; + bool optimize = true; + + ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions, + optimize)); +} + +/* TESTCASE: Tests that the HWC2 can present 2 layers with complete coverage of + * display frame. */ +TEST_F(Hwc2Test, PRESENT_DISPLAY_display_frame_2) +{ + const size_t layerCnt = 2; + Hwc2TestCoverage coverage = Hwc2TestCoverage::Default; + std::unordered_map exceptions = + {{Hwc2TestPropertyName::DisplayFrame, Hwc2TestCoverage::Complete}}; + bool optimize = true; + + ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions, + optimize)); +} + +/* TESTCASE: Tests that the HWC2 can present 3 layers with complete coverage of + * display frame. */ +TEST_F(Hwc2Test, PRESENT_DISPLAY_display_frame_3) +{ + const size_t layerCnt = 3; + Hwc2TestCoverage coverage = Hwc2TestCoverage::Default; + std::unordered_map exceptions = + {{Hwc2TestPropertyName::DisplayFrame, Hwc2TestCoverage::Complete}}; + bool optimize = true; + + ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions, + optimize)); +} + +/* TESTCASE: Tests that the HWC2 can present 4 layers with complete coverage of + * display frame. */ +TEST_F(Hwc2Test, PRESENT_DISPLAY_display_frame_4) +{ + const size_t layerCnt = 4; + Hwc2TestCoverage coverage = Hwc2TestCoverage::Default; + std::unordered_map exceptions = + {{Hwc2TestPropertyName::DisplayFrame, Hwc2TestCoverage::Complete}}; + bool optimize = true; + + ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions, + optimize)); +} + +/* TESTCASE: Tests that the HWC2 can present 1 layer with complete coverage of + * plane alpha. */ +TEST_F(Hwc2Test, PRESENT_DISPLAY_plane_alpha_1) +{ + const size_t layerCnt = 1; + Hwc2TestCoverage coverage = Hwc2TestCoverage::Default; + std::unordered_map exceptions = + {{Hwc2TestPropertyName::BlendMode, Hwc2TestCoverage::Basic}, + {Hwc2TestPropertyName::PlaneAlpha, Hwc2TestCoverage::Complete}}; + bool optimize = false; + + ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions, + optimize)); +} + +/* TESTCASE: Tests that the HWC2 can present 2 layers with complete coverage of + * plane alpha. */ +TEST_F(Hwc2Test, PRESENT_DISPLAY_plane_alpha_2) +{ + const size_t layerCnt = 2; + Hwc2TestCoverage coverage = Hwc2TestCoverage::Default; + std::unordered_map exceptions = + {{Hwc2TestPropertyName::BlendMode, Hwc2TestCoverage::Basic}, + {Hwc2TestPropertyName::PlaneAlpha, Hwc2TestCoverage::Complete}}; + bool optimize = false; + + ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions, + optimize)); +} + +/* TESTCASE: Tests that the HWC2 can present 1 layer with complete coverage of + * source crop. */ +TEST_F(Hwc2Test, PRESENT_DISPLAY_source_crop_1) +{ + const size_t layerCnt = 1; + Hwc2TestCoverage coverage = Hwc2TestCoverage::Default; + std::unordered_map exceptions = + {{Hwc2TestPropertyName::DisplayFrame, Hwc2TestCoverage::Complete}, + {Hwc2TestPropertyName::SourceCrop, Hwc2TestCoverage::Complete}}; + bool optimize = true; + + ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions, + optimize)); +} + +/* TESTCASE: Tests that the HWC2 can present 2 layers with complete coverage of + * source crop. */ +TEST_F(Hwc2Test, PRESENT_DISPLAY_source_crop_2) +{ + const size_t layerCnt = 2; + Hwc2TestCoverage coverage = Hwc2TestCoverage::Default; + std::unordered_map exceptions = + {{Hwc2TestPropertyName::DisplayFrame, Hwc2TestCoverage::Complete}, + {Hwc2TestPropertyName::SourceCrop, Hwc2TestCoverage::Complete}}; + bool optimize = true; + + ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions, + optimize)); +} + + +/* TESTCASE: Tests that the HWC2 can present 1 layer with complete coverage of + * surface damage. */ +TEST_F(Hwc2Test, PRESENT_DISPLAY_surface_damage_1) +{ + const size_t layerCnt = 1; + Hwc2TestCoverage coverage = Hwc2TestCoverage::Default; + std::unordered_map exceptions = + {{Hwc2TestPropertyName::SurfaceDamage, Hwc2TestCoverage::Complete}}; + bool optimize = true; + + ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions, + optimize)); +} + +/* TESTCASE: Tests that the HWC2 can present 1 layer with complete coverage of + * transform. */ +TEST_F(Hwc2Test, PRESENT_DISPLAY_transform_1) +{ + const size_t layerCnt = 1; + Hwc2TestCoverage coverage = Hwc2TestCoverage::Default; + std::unordered_map exceptions = + {{Hwc2TestPropertyName::Transform, Hwc2TestCoverage::Complete}}; + bool optimize = true; + + ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions, + optimize)); +} + +/* TESTCASE: Tests that the HWC2 can present 2 layers with complete coverage of + * transform. */ +TEST_F(Hwc2Test, PRESENT_DISPLAY_transform_2) +{ + const size_t layerCnt = 2; + Hwc2TestCoverage coverage = Hwc2TestCoverage::Default; + std::unordered_map exceptions = + {{Hwc2TestPropertyName::Transform, Hwc2TestCoverage::Complete}, + {Hwc2TestPropertyName::DisplayFrame, Hwc2TestCoverage::Basic}}; + bool optimize = true; + + ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions, + optimize)); +} + +/* TESTCASE: Tests that the HWC2 can present 1 layer with complete coverage of + * basic. */ +TEST_F(Hwc2Test, PRESENT_DISPLAY_basic_1) +{ + const size_t layerCnt = 1; + Hwc2TestCoverage coverage = Hwc2TestCoverage::Basic; + std::unordered_map exceptions; + bool optimize = true; + + ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions, + optimize)); +} + +/* TESTCASE: Tests that the HWC2 cannot present a bad display. */ +TEST_F(Hwc2Test, PRESENT_DISPLAY_bad_display) +{ + hwc2_display_t display; + int32_t presentFence; + hwc2_error_t err = HWC2_ERROR_NONE; + + ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display)); + + ASSERT_NO_FATAL_FAILURE(presentDisplay(display, &presentFence, &err)); + EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code"; +} + +/* TESTCASE: Tests that the HWC2 cannot present an unvalidated display. */ +TEST_F(Hwc2Test, PRESENT_DISPLAY_not_validated) +{ + ASSERT_NO_FATAL_FAILURE(displayLayers(Hwc2TestCoverage::Default, 1, + [] (Hwc2Test* test, hwc2_display_t display, + const std::vector& /*layers*/, + Hwc2TestLayers* /*testLayers*/) { + + int32_t presentFence; + hwc2_error_t err = HWC2_ERROR_NONE; + + ASSERT_NO_FATAL_FAILURE(test->setPowerMode(display, + HWC2_POWER_MODE_ON)); + ASSERT_NO_FATAL_FAILURE(test->enableVsync(display)); + + ASSERT_NO_FATAL_FAILURE(test->waitForVsync()); + + ASSERT_NO_FATAL_FAILURE(test->presentDisplay(display, + &presentFence, &err)); + EXPECT_EQ(err, HWC2_ERROR_NOT_VALIDATED) + << "returned wrong error code"; + + ASSERT_NO_FATAL_FAILURE(test->disableVsync(display)); + ASSERT_NO_FATAL_FAILURE(test->setPowerMode(display, + HWC2_POWER_MODE_OFF)); + } + )); +} + +/* TESTCASE: Tests that the HWC2 cannot get release fences from a bad display. */ +TEST_F(Hwc2Test, GET_RELEASE_FENCES_bad_display) +{ + hwc2_display_t display; + std::vector layers; + std::vector fences; + hwc2_error_t err = HWC2_ERROR_NONE; + + ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display)); + + ASSERT_NO_FATAL_FAILURE(getReleaseFences(display, &layers, &fences, &err)); + EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code"; +} diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp b/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp index b459cd65c4..937fce28fb 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp @@ -18,17 +18,41 @@ #include "Hwc2TestLayer.h" -Hwc2TestLayer::Hwc2TestLayer(Hwc2TestCoverage coverage, const Area& displayArea) - : mBlendMode(coverage), - mBufferArea(coverage, displayArea), - mColor(coverage), - mComposition(coverage), - mDataspace(coverage), - mDisplayFrame(coverage, displayArea), - mPlaneAlpha(coverage), - mSourceCrop(coverage), - mSurfaceDamage(coverage), - mTransform(coverage) +Hwc2TestCoverage getCoverage(Hwc2TestPropertyName property, + Hwc2TestCoverage coverage, const std::unordered_map& coverageExceptions) { + auto exception = coverageExceptions.find(property); + return (exception != coverageExceptions.end())? exception->second : coverage; +} + +Hwc2TestLayer::Hwc2TestLayer(Hwc2TestCoverage coverage, + const Area& displayArea) + : Hwc2TestLayer(coverage, displayArea, + std::unordered_map()) { } + +Hwc2TestLayer::Hwc2TestLayer(Hwc2TestCoverage coverage, + const Area& displayArea, const std::unordered_map& coverageExceptions) + : mBlendMode(getCoverage(Hwc2TestPropertyName::BlendMode, coverage, + coverageExceptions)), + mBufferArea(getCoverage(Hwc2TestPropertyName::BufferArea, coverage, + coverageExceptions), displayArea), + mColor(getCoverage(Hwc2TestPropertyName::Color, coverage, + coverageExceptions)), + mComposition(getCoverage(Hwc2TestPropertyName::Composition, coverage, + coverageExceptions)), + mDataspace(getCoverage(Hwc2TestPropertyName::Dataspace, coverage, + coverageExceptions)), + mDisplayFrame(getCoverage(Hwc2TestPropertyName::DisplayFrame, coverage, + coverageExceptions), displayArea), + mPlaneAlpha(getCoverage(Hwc2TestPropertyName::PlaneAlpha, coverage, + coverageExceptions)), + mSourceCrop(getCoverage(Hwc2TestPropertyName::SourceCrop, coverage, + coverageExceptions)), + mSurfaceDamage(getCoverage(Hwc2TestPropertyName::SurfaceDamage, coverage, + coverageExceptions)), + mTransform(getCoverage(Hwc2TestPropertyName::Transform, coverage, + coverageExceptions)) { mBufferArea.setDependent(&mBuffer); mBufferArea.setDependent(&mSourceCrop); diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h b/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h index 17f50790db..0e7dd228fb 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h @@ -18,6 +18,7 @@ #define _HWC2_TEST_LAYER_H #include +#include #include "Hwc2TestBuffer.h" #include "Hwc2TestProperties.h" @@ -32,6 +33,10 @@ class Hwc2TestLayer { public: Hwc2TestLayer(Hwc2TestCoverage coverage, const Area& displayArea); + Hwc2TestLayer(Hwc2TestCoverage coverage, const Area& displayArea, + const std::unordered_map& coverage_exceptions); + std::string dump() const; int getBuffer(buffer_handle_t* outHandle, diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.cpp b/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.cpp index 96cd98d0a7..495ef79609 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.cpp +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.cpp @@ -20,12 +20,19 @@ Hwc2TestLayers::Hwc2TestLayers(const std::vector& layers, Hwc2TestCoverage coverage, const Area& displayArea) + : Hwc2TestLayers(layers, coverage, displayArea, + std::unordered_map()) { } + +Hwc2TestLayers::Hwc2TestLayers(const std::vector& layers, + Hwc2TestCoverage coverage, const Area& displayArea, + const std::unordered_map& coverageExceptions) : mDisplayArea(displayArea) { for (auto layer : layers) { mTestLayers.emplace(std::piecewise_construct, std::forward_as_tuple(layer), - std::forward_as_tuple(coverage, displayArea)); + std::forward_as_tuple(coverage, displayArea, coverageExceptions)); } /* Iterate over the layers in order and assign z orders in the same order. diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.h b/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.h index a8579ee765..d95a91f485 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.h +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.h @@ -33,6 +33,11 @@ public: Hwc2TestLayers(const std::vector& layers, Hwc2TestCoverage coverage, const Area& displayArea); + Hwc2TestLayers(const std::vector& layers, + Hwc2TestCoverage coverage, const Area& displayArea, + const std::unordered_map& coverageExceptions); + std::string dump() const; void reset(); diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h index f3c614cd55..d978237cdf 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h @@ -34,6 +34,20 @@ enum class Hwc2TestCoverage { Complete, }; +enum class Hwc2TestPropertyName { + BlendMode = 1, + BufferArea, + Color, + Composition, + CursorPosition, + Dataspace, + DisplayFrame, + PlaneAlpha, + SourceCrop, + SurfaceDamage, + Transform, +}; + typedef struct { int32_t width; int32_t height; -- cgit v1.2.3-59-g8ed1b From 35040c559d26d00d6123c894cfc9573b0a5aa860 Mon Sep 17 00:00:00 2001 From: Marissa Wall Date: Thu, 15 Dec 2016 12:41:06 -0800 Subject: test-hwc2: color and hdr requests Test: Add "#define HAVE_NO_SURFACE_FLINGER" to frameworks/native/libs/gui/BufferQueueCore.cpp. Recompile and flash. Run "mm" in frameworks/native/services/surfaceflinger/tests/hwc2. Push test-hwc2 to device. Run "adb root && adb shell stop". Run test case. Ex: "./test-hwc2" Change-Id: Id515de0fac7e842724ae8f27e865fad4933256e6 --- services/surfaceflinger/tests/hwc2/Hwc2Test.cpp | 358 ++++++++++++++++++++++++ 1 file changed, 358 insertions(+) diff --git a/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp index 600c4540af..840f67d112 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp +++ b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp @@ -854,6 +854,101 @@ public: } } + void getColorModes(hwc2_display_t display, + std::vector* outColorModes, + hwc2_error_t* outErr = nullptr) + { + auto pfn = reinterpret_cast( + getFunction(HWC2_FUNCTION_GET_COLOR_MODES)); + ASSERT_TRUE(pfn) << "failed to get function"; + + uint32_t numColorModes = 0; + + auto err = static_cast(pfn(mHwc2Device, display, + &numColorModes, nullptr)); + if (err == HWC2_ERROR_NONE) { + outColorModes->resize(numColorModes); + + err = static_cast(pfn(mHwc2Device, display, + &numColorModes, + reinterpret_cast(outColorModes->data()))); + } + + if (outErr) { + *outErr = err; + } else { + ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to get color modes for" + " display " << display; + } + } + + void setColorMode(hwc2_display_t display, android_color_mode_t colorMode, + hwc2_error_t* outErr = nullptr) + { + auto pfn = reinterpret_cast( + getFunction(HWC2_FUNCTION_SET_COLOR_MODE)); + ASSERT_TRUE(pfn) << "failed to get function"; + + auto err = static_cast(pfn(mHwc2Device, display, + static_cast(colorMode))); + if (outErr) { + *outErr = err; + } else { + ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set color mode " + << colorMode; + } + } + + void getHdrCapabilities(hwc2_display_t display, + std::vector* outTypes, float* outMaxLuminance, + float* outMaxAverageLuminance, float* outMinLuminance, + hwc2_error_t* outErr = nullptr) + { + auto pfn = reinterpret_cast( + getFunction(HWC2_FUNCTION_GET_HDR_CAPABILITIES)); + ASSERT_TRUE(pfn) << "failed to get function"; + + uint32_t numTypes = 0; + + auto err = static_cast(pfn(mHwc2Device, display, + &numTypes, nullptr, outMaxLuminance, outMaxAverageLuminance, + outMinLuminance)); + + if (err == HWC2_ERROR_NONE) { + outTypes->resize(numTypes); + + err = static_cast(pfn(mHwc2Device, display, &numTypes, + reinterpret_cast(outTypes->data()), outMaxLuminance, + outMaxAverageLuminance, outMinLuminance)); + } + + if (outErr) { + *outErr = err; + } else { + ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to get hdr capabilities" + " for display " << display; + } + } + + void setColorTransform(hwc2_display_t display, + const std::array& matrix, android_color_transform_t hint, + hwc2_error_t* outErr = nullptr) + { + auto pfn = reinterpret_cast( + getFunction(HWC2_FUNCTION_SET_COLOR_TRANSFORM)); + ASSERT_TRUE(pfn) << "failed to get function"; + + auto err = static_cast(pfn(mHwc2Device, display, + matrix.data(), hint)); + + if (outErr) { + *outErr = err; + } else { + ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set color transform " + << hint; + } + } + void getBadDisplay(hwc2_display_t* outDisplay) { for (hwc2_display_t display = 0; display < UINT64_MAX; display++) { @@ -1030,6 +1125,10 @@ protected: hwc2_display_t display, const Hwc2TestClientTargetSupport& testClientTargetSupport); + /* Tests a particular active display config */ + using TestActiveDisplayConfigFunction = void (*)(Hwc2Test* test, + hwc2_display_t display); + /* Advances a property of Hwc2TestLayer */ using AdvanceProperty = bool (*)(Hwc2TestLayer* testLayer); @@ -1325,6 +1424,23 @@ protected: } } + /* Cycles through each config on each active display and calls + * a TestActiveDisplayConfigFunction */ + void setActiveDisplayConfig(TestActiveDisplayConfigFunction function) + { + for (auto display : mDisplays) { + std::vector configs; + + ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs)); + + for (auto config : configs) { + ASSERT_NO_FATAL_FAILURE(setActiveConfig(display, config)); + + EXPECT_NO_FATAL_FAILURE(function(this, display)); + } + } + } + void getActiveConfigAttribute(hwc2_display_t display, hwc2_attribute_t attribute, int32_t* outValue) { @@ -3861,3 +3977,245 @@ TEST_F(Hwc2Test, GET_RELEASE_FENCES_bad_display) ASSERT_NO_FATAL_FAILURE(getReleaseFences(display, &layers, &fences, &err)); EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code"; } + +static const std::array androidColorModes = {{ + HAL_COLOR_MODE_NATIVE, + HAL_COLOR_MODE_STANDARD_BT601_625, + HAL_COLOR_MODE_STANDARD_BT601_625_UNADJUSTED, + HAL_COLOR_MODE_STANDARD_BT601_525, + HAL_COLOR_MODE_STANDARD_BT601_525_UNADJUSTED, + HAL_COLOR_MODE_STANDARD_BT709, + HAL_COLOR_MODE_DCI_P3, + HAL_COLOR_MODE_SRGB, + HAL_COLOR_MODE_ADOBE_RGB, +}}; + +/* TESTCASE: Tests that the HWC2 can get the color modes for a display. The + * display must support HAL_COLOR_MODE_NATIVE */ +TEST_F(Hwc2Test, GET_COLOR_MODES) +{ + ASSERT_NO_FATAL_FAILURE(setActiveDisplayConfig( + [] (Hwc2Test* test, hwc2_display_t display) { + + std::vector colorModes; + + ASSERT_NO_FATAL_FAILURE(test->getColorModes(display, + &colorModes)); + + EXPECT_NE(std::count(colorModes.begin(), colorModes.end(), + HAL_COLOR_MODE_NATIVE), 0) << "all displays" + " must support HAL_COLOR_MODE_NATIVE"; + } + )); +} + +/* TESTCASE: Tests that the HWC2 cannot get color modes from a bad display. */ +TEST_F(Hwc2Test, GET_COLOR_MODES_bad_display) +{ + hwc2_display_t display; + std::vector colorModes; + hwc2_error_t err = HWC2_ERROR_NONE; + + ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display)); + + ASSERT_NO_FATAL_FAILURE(getColorModes(display, &colorModes, &err)); + EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code"; +} + +/* TESTCASE: Tests that the HWC2 can set the required color mode on a display. */ +TEST_F(Hwc2Test, SET_COLOR_MODES) +{ + ASSERT_NO_FATAL_FAILURE(setActiveDisplayConfig( + [] (Hwc2Test* test, hwc2_display_t display) { + + const android_color_mode_t colorMode = HAL_COLOR_MODE_NATIVE; + + EXPECT_NO_FATAL_FAILURE(test->setColorMode(display, colorMode)); + } + )); +} + +/* TESTCASE: Tests that the HWC2 cannot set a color mode on a bad display. */ +TEST_F(Hwc2Test, SET_COLOR_MODES_bad_display) +{ + hwc2_display_t display; + const android_color_mode_t colorMode = HAL_COLOR_MODE_NATIVE; + hwc2_error_t err = HWC2_ERROR_NONE; + + ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display)); + + ASSERT_NO_FATAL_FAILURE(setColorMode(display, colorMode, &err)); + EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code"; +} + +/* TESTCASE: Tests that the HWC2 cannot set an invalid color mode. */ +TEST_F(Hwc2Test, SET_COLOR_MODES_bad_parameter) +{ + ASSERT_NO_FATAL_FAILURE(setActiveDisplayConfig( + [] (Hwc2Test* test, hwc2_display_t display) { + + const android_color_mode_t colorMode = + static_cast(-1); + hwc2_error_t err = HWC2_ERROR_NONE; + + ASSERT_NO_FATAL_FAILURE(test->setColorMode(display, colorMode, + &err)); + EXPECT_EQ(err, HWC2_ERROR_BAD_PARAMETER) + << "returned wrong error code"; + } + )); +} + +/* TESTCASE: Tests that the HWC2 either supports or returns error unsupported + * for all valid color modes. */ +TEST_F(Hwc2Test, SET_COLOR_MODES_unsupported) +{ + ASSERT_NO_FATAL_FAILURE(setActiveDisplayConfig( + [] (Hwc2Test* test, hwc2_display_t display) { + + for (auto colorMode : androidColorModes) { + hwc2_error_t err = HWC2_ERROR_NONE; + + ASSERT_NO_FATAL_FAILURE(test->setColorMode(display, + colorMode, &err)); + + EXPECT_TRUE(err == HWC2_ERROR_NONE + || err == HWC2_ERROR_UNSUPPORTED) + << "returned wrong error code"; + } + } + )); +} + +/* TESTCASE: Tests that the HWC2 gets the HDR capabilities for a display and + * test if they are valid. */ +TEST_F(Hwc2Test, GET_HDR_CAPABILITIES) +{ + ASSERT_NO_FATAL_FAILURE(setActiveDisplayConfig( + [] (Hwc2Test* test, hwc2_display_t display) { + + std::vector hdrCapabilities; + float maxLuminance, maxAverageLuminance, minLuminance; + + EXPECT_NO_FATAL_FAILURE(test->getHdrCapabilities(display, + &hdrCapabilities, &maxLuminance, &maxAverageLuminance, + &minLuminance)); + + if (hdrCapabilities.empty()) + return; + + EXPECT_GE(maxLuminance, maxAverageLuminance); + EXPECT_GE(maxAverageLuminance, minLuminance); + } + )); +} + +/* TESTCASE: Tests that the HWC2 cannot get hdr capabilities from a bad display */ +TEST_F(Hwc2Test, GET_HDR_CAPABILITIES_bad_display) +{ + hwc2_display_t display; + std::vector hdrCapabilities; + float maxLuminance, maxAverageLuminance, minLuminance; + hwc2_error_t err = HWC2_ERROR_NONE; + + ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display)); + + ASSERT_NO_FATAL_FAILURE(getHdrCapabilities(display, &hdrCapabilities, + &maxLuminance, &maxAverageLuminance, &minLuminance, &err)); + EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code"; +} + +static const std::array identityMatrix = {{ + 1.0, 0.0, 0.0, 0.0, + 0.0, 1.0, 0.0, 0.0, + 0.0, 0.0, 1.0, 0.0, + 0.0, 0.0, 0.0, 1.0, +}}; + +/* Values for the color transform matrices were precomputed using the source code + * in surfaceflinger/Effects/Daltonizer.cpp. */ + +static const std::array, 5> exampleMatrices = {{ + identityMatrix, + /* Converts RGB color to the XYZ space */ + {{ 0.4124, 0.2126, 0.0193, 0, + 0.3576, 0.7152, 0.1192, 0, + 0.1805, 0.0722, 0.9505, 0, + 0 , 0 , 0 , 1 }}, + /* Protanomaly */ + {{ 0.068493, 0.931506, 0, 0, + 0.068493, 0.931507, 0, 0, + 0.013626, -0.013626, 1, 0, + 0, 0, 0, 1 }}, + /* Deuteranomaly */ + {{ 0.288299, 0.711701, 0, 0, + 0.052709, 0.947291, 0, 0, + -0.257912, 0.257912, 1, 0, + 0, 0, 0, 1 }}, + /* Tritanomaly */ + {{ 1, -0.805712, 0.805712, 0, + 0, 0.378838, 0.621162, 0, + 0, 0.104823, 0.895177, 0, + 0, 0, 0, 1 }}, +}}; + +/* TESTCASE: Tests that the HWC2 can set the identity color transform */ +TEST_F(Hwc2Test, SET_COLOR_TRANSFORM) +{ + ASSERT_NO_FATAL_FAILURE(setActiveDisplayConfig( + [] (Hwc2Test* test, hwc2_display_t display) { + + EXPECT_NO_FATAL_FAILURE(test->setColorTransform(display, + identityMatrix, HAL_COLOR_TRANSFORM_IDENTITY)); + } + )); +} + +/* TESTCASE: Tests that the HWC2 cannot set the color transform for a bad + * display. */ +TEST_F(Hwc2Test, SET_COLOR_TRANSFORM_bad_display) +{ + hwc2_display_t display; + hwc2_error_t err = HWC2_ERROR_NONE; + + ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display)); + + ASSERT_NO_FATAL_FAILURE(setColorTransform(display, identityMatrix, + HAL_COLOR_TRANSFORM_IDENTITY, &err)); + EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code"; +} + +/* TESTCASE: Tests that the HWC2 cannot set an invalid color transform. */ +TEST_F(Hwc2Test, SET_COLOR_TRANSFORM_bad_parameter) +{ + ASSERT_NO_FATAL_FAILURE(setActiveDisplayConfig( + [] (Hwc2Test* test, hwc2_display_t display) { + + const android_color_transform_t hint = + static_cast(-1); + hwc2_error_t err = HWC2_ERROR_NONE; + + ASSERT_NO_FATAL_FAILURE(test->setColorTransform(display, + identityMatrix, hint, &err)); + EXPECT_EQ(err, HWC2_ERROR_BAD_PARAMETER) + << "returned wrong error code"; + } + )); +} + +/* TESTCASE: Tests that the HWC2 can set an arbitrary color matrix. */ +TEST_F(Hwc2Test, SET_COLOR_TRANSFORM_arbitrary_matrix) +{ + ASSERT_NO_FATAL_FAILURE(setActiveDisplayConfig( + [] (Hwc2Test* test, hwc2_display_t display) { + + const android_color_transform_t hint = + HAL_COLOR_TRANSFORM_ARBITRARY_MATRIX; + + for (const std::array& matrix : exampleMatrices) { + EXPECT_NO_FATAL_FAILURE(test->setColorTransform(display, + matrix, hint)); + } + } + )); +} -- cgit v1.2.3-59-g8ed1b From bad1bc78ef50648fadbe725a1fe1c28d62097351 Mon Sep 17 00:00:00 2001 From: Marissa Wall Date: Tue, 21 Feb 2017 14:33:46 -0800 Subject: test-hwc2: virtual displays Test: Add "#define HAVE_NO_SURFACE_FLINGER" to frameworks/native/libs/gui/BufferQueueCore.cpp. Recompile and flash. Run "mm" in frameworks/native/services/surfaceflinger/tests/hwc2. Push test-hwc2 to device. Run "adb root && adb shell stop". Run test case. Ex: "./test-hwc2" Change-Id: Ia10ec761712ee03f56782e3df2d6eabf7fb77760 --- services/surfaceflinger/tests/hwc2/Android.mk | 3 +- services/surfaceflinger/tests/hwc2/Hwc2Test.cpp | 310 +++++++++++++++++++++ .../tests/hwc2/Hwc2TestProperties.cpp | 62 +++++ .../surfaceflinger/tests/hwc2/Hwc2TestProperties.h | 27 ++ .../tests/hwc2/Hwc2TestVirtualDisplay.cpp | 61 ++++ .../tests/hwc2/Hwc2TestVirtualDisplay.h | 49 ++++ 6 files changed, 511 insertions(+), 1 deletion(-) create mode 100644 services/surfaceflinger/tests/hwc2/Hwc2TestVirtualDisplay.cpp create mode 100644 services/surfaceflinger/tests/hwc2/Hwc2TestVirtualDisplay.h diff --git a/services/surfaceflinger/tests/hwc2/Android.mk b/services/surfaceflinger/tests/hwc2/Android.mk index f7403cfe67..b8c2133027 100644 --- a/services/surfaceflinger/tests/hwc2/Android.mk +++ b/services/surfaceflinger/tests/hwc2/Android.mk @@ -47,6 +47,7 @@ LOCAL_SRC_FILES := \ Hwc2TestLayer.cpp \ Hwc2TestLayers.cpp \ Hwc2TestBuffer.cpp \ - Hwc2TestClientTarget.cpp + Hwc2TestClientTarget.cpp \ + Hwc2TestVirtualDisplay.cpp include $(BUILD_NATIVE_TEST) diff --git a/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp index 840f67d112..751a9cc9cc 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp +++ b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp @@ -32,6 +32,7 @@ #include "Hwc2TestLayer.h" #include "Hwc2TestLayers.h" #include "Hwc2TestClientTarget.h" +#include "Hwc2TestVirtualDisplay.h" void hwc2TestHotplugCallback(hwc2_callback_data_t callbackData, hwc2_display_t display, int32_t connected); @@ -77,6 +78,13 @@ public: setPowerMode(display, HWC2_POWER_MODE_OFF); } + for (auto itr = mVirtualDisplays.begin(); itr != mVirtualDisplays.end();) { + hwc2_display_t display = *itr; + itr++; + /* Destroys virtual displays */ + destroyVirtualDisplay(display); + } + if (mHwc2Device) hwc2_close(mHwc2Device); } @@ -949,6 +957,71 @@ public: } } + void createVirtualDisplay(uint32_t width, uint32_t height, + android_pixel_format_t* outFormat, hwc2_display_t* outDisplay, + hwc2_error_t* outErr = nullptr) + { + auto pfn = reinterpret_cast( + getFunction(HWC2_FUNCTION_CREATE_VIRTUAL_DISPLAY)); + ASSERT_TRUE(pfn) << "failed to get function"; + + auto err = static_cast(pfn(mHwc2Device, width, height, + reinterpret_cast(outFormat), outDisplay)); + + if (err == HWC2_ERROR_NONE) + mVirtualDisplays.insert(*outDisplay); + + if (outErr) { + *outErr = err; + } else { + ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to create virtual display"; + } + } + + void destroyVirtualDisplay(hwc2_display_t display, + hwc2_error_t* outErr = nullptr) + { + auto pfn = reinterpret_cast( + getFunction(HWC2_FUNCTION_DESTROY_VIRTUAL_DISPLAY)); + ASSERT_TRUE(pfn) << "failed to get function"; + + auto err = static_cast(pfn(mHwc2Device, display)); + + if (err == HWC2_ERROR_NONE) + mVirtualDisplays.erase(display); + + if (outErr) { + *outErr = err; + } else { + ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to destroy virtual display"; + } + } + + void getMaxVirtualDisplayCount(uint32_t* outMaxCnt) + { + auto pfn = reinterpret_cast( + getFunction(HWC2_FUNCTION_GET_MAX_VIRTUAL_DISPLAY_COUNT)); + ASSERT_TRUE(pfn) << "failed to get function"; + + *outMaxCnt = pfn(mHwc2Device); + } + + void setOutputBuffer(hwc2_display_t display, buffer_handle_t buffer, + int32_t releaseFence, hwc2_error_t* outErr = nullptr) + { + auto pfn = reinterpret_cast( + getFunction(HWC2_FUNCTION_SET_OUTPUT_BUFFER)); + ASSERT_TRUE(pfn) << "failed to get function"; + + auto err = static_cast(pfn(mHwc2Device, display, buffer, + releaseFence)); + if (outErr) { + *outErr = err; + } else { + ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set output buffer"; + } + } + void getBadDisplay(hwc2_display_t* outDisplay) { for (hwc2_display_t display = 0; display < UINT64_MAX; display++) { @@ -1129,6 +1202,10 @@ protected: using TestActiveDisplayConfigFunction = void (*)(Hwc2Test* test, hwc2_display_t display); + /* Tests a newly created virtual display */ + using TestCreateVirtualDisplayFunction = void (*)(Hwc2Test* test, + hwc2_display_t display, Hwc2TestVirtualDisplay* testVirtualDisplay); + /* Advances a property of Hwc2TestLayer */ using AdvanceProperty = bool (*)(Hwc2TestLayer* testLayer); @@ -1441,6 +1518,40 @@ protected: } } + /* Creates a virtual display for testing */ + void createVirtualDisplay(Hwc2TestCoverage coverage, + TestCreateVirtualDisplayFunction function) + { + Hwc2TestVirtualDisplay testVirtualDisplay(coverage); + + do { + hwc2_display_t display; + hwc2_error_t err = HWC2_ERROR_NONE; + + const UnsignedArea& dimension = + testVirtualDisplay.getDisplayDimension(); + android_pixel_format_t desiredFormat = HAL_PIXEL_FORMAT_RGBA_8888; + + ASSERT_NO_FATAL_FAILURE(createVirtualDisplay(dimension.width, + dimension.height, &desiredFormat, &display, &err)); + + EXPECT_TRUE(err == HWC2_ERROR_NONE || err == HWC2_ERROR_NO_RESOURCES + || err == HWC2_ERROR_UNSUPPORTED) + << "returned wrong error code"; + EXPECT_GE(desiredFormat, 0) << "invalid format"; + + if (err != HWC2_ERROR_NONE) + continue; + + EXPECT_NO_FATAL_FAILURE(function(this, display, + &testVirtualDisplay)); + + ASSERT_NO_FATAL_FAILURE(destroyVirtualDisplay(display)); + + } while (testVirtualDisplay.advance()); + } + + void getActiveConfigAttribute(hwc2_display_t display, hwc2_attribute_t attribute, int32_t* outValue) { @@ -1664,6 +1775,10 @@ protected: * tearing down the test cases, change it to HWC2_POWER_MODE_OFF */ std::set mActiveDisplays; + /* Store all created virtual displays that have not been destroyed. If an + * ASSERT_* fails, then destroy the virtual displays on exit */ + std::set mVirtualDisplays; + std::mutex mVsyncMutex; std::condition_variable mVsyncCv; hwc2_display_t mVsyncDisplay; @@ -4219,3 +4334,198 @@ TEST_F(Hwc2Test, SET_COLOR_TRANSFORM_arbitrary_matrix) } )); } + +/* TESTCASE: Tests that the HWC2 create an destory virtual displays. */ +TEST_F(Hwc2Test, CREATE_DESTROY_VIRTUAL_DISPLAY) +{ + ASSERT_NO_FATAL_FAILURE(createVirtualDisplay(Hwc2TestCoverage::Complete, + [] (Hwc2Test* /*test*/, hwc2_display_t /*display*/, + Hwc2TestVirtualDisplay* /*testVirtualDisplay*/) { })); +} + +/* TESTCASE: Tests that the HWC2 can create and destroy multiple virtual + * displays. */ +TEST_F(Hwc2Test, CREATE_DESTROY_VIRTUAL_DISPLAY_multiple) +{ + Hwc2TestVirtualDisplay testVirtualDisplay(Hwc2TestCoverage::Complete); + std::vector displays; + + do { + const UnsignedArea& dimension = + testVirtualDisplay.getDisplayDimension(); + android_pixel_format_t desiredFormat = HAL_PIXEL_FORMAT_RGBA_8888; + hwc2_display_t display; + hwc2_error_t err = HWC2_ERROR_NONE; + + ASSERT_NO_FATAL_FAILURE(createVirtualDisplay(dimension.width, + dimension.height, &desiredFormat, &display, &err)); + + EXPECT_TRUE(err == HWC2_ERROR_NONE || err == HWC2_ERROR_NO_RESOURCES + || err == HWC2_ERROR_UNSUPPORTED) << "returned wrong error code"; + EXPECT_GE(desiredFormat, 0) << "invalid format"; + + if (err == HWC2_ERROR_NONE) + displays.push_back(display); + + } while (testVirtualDisplay.advance()); + + for (hwc2_display_t display : displays) { + EXPECT_NO_FATAL_FAILURE(destroyVirtualDisplay(display)); + } +} + +/* TESTCASE: Tests that the HWC2 cannot destroy a bad virtual displays. */ +TEST_F(Hwc2Test, DESTROY_VIRTUAL_DISPLAY_bad_display) +{ + hwc2_display_t display; + hwc2_error_t err = HWC2_ERROR_NONE; + + ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display)); + + ASSERT_NO_FATAL_FAILURE(destroyVirtualDisplay(display, &err)); + EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code"; +} + +/* TESTCASE: Tests that the HWC2 cannot destroy a physical display. */ +TEST_F(Hwc2Test, DESTROY_VIRTUAL_DISPLAY_bad_parameter) +{ + hwc2_display_t display = HWC_DISPLAY_PRIMARY; + hwc2_error_t err = HWC2_ERROR_NONE; + + ASSERT_NO_FATAL_FAILURE(destroyVirtualDisplay(display, &err)); + EXPECT_EQ(err, HWC2_ERROR_BAD_PARAMETER) << "returned wrong error code"; +} + +/* TESTCASE: Tests that the HWC2 can get the max virtual display count. */ +TEST_F(Hwc2Test, GET_MAX_VIRTUAL_DISPLAY_COUNT) +{ + uint32_t maxCnt; + + ASSERT_NO_FATAL_FAILURE(getMaxVirtualDisplayCount(&maxCnt)); +} + +/* TESTCASE: Tests that the HWC2 returns the same max virtual display count for + * each call. */ +TEST_F(Hwc2Test, GET_MAX_VIRTUAL_DISPLAY_COUNT_duplicate) +{ + uint32_t maxCnt1, maxCnt2; + + ASSERT_NO_FATAL_FAILURE(getMaxVirtualDisplayCount(&maxCnt1)); + ASSERT_NO_FATAL_FAILURE(getMaxVirtualDisplayCount(&maxCnt2)); + + EXPECT_EQ(maxCnt1, maxCnt2) << "returned two different max virtual display" + " counts"; +} + +/* TESTCASE: Tests that the HWC2 can create the max number of virtual displays + * that it reports. */ +TEST_F(Hwc2Test, GET_MAX_VIRTUAL_DISPLAY_COUNT_create_max) +{ + std::vector displays; + uint32_t maxCnt; + + ASSERT_NO_FATAL_FAILURE(getMaxVirtualDisplayCount(&maxCnt)); + + while (displays.size() < maxCnt) { + uint32_t width = 1920, height = 1080; + android_pixel_format_t desiredFormat = HAL_PIXEL_FORMAT_RGBA_8888; + hwc2_display_t display; + hwc2_error_t err = HWC2_ERROR_NONE; + + ASSERT_NO_FATAL_FAILURE(createVirtualDisplay(width, height, + &desiredFormat, &display, &err)); + + EXPECT_TRUE(err == HWC2_ERROR_NONE || err == HWC2_ERROR_UNSUPPORTED) + << "returned wrong error code"; + if (err != HWC2_ERROR_NONE) + break; + + displays.push_back(display); + } + + for (hwc2_display_t display : displays) { + EXPECT_NO_FATAL_FAILURE(destroyVirtualDisplay(display)); + } +} + +/* TESTCASE: Tests that the HWC2 can set an output buffer for a virtual + * display. */ +TEST_F(Hwc2Test, SET_OUTPUT_BUFFER) +{ + ASSERT_NO_FATAL_FAILURE(createVirtualDisplay(Hwc2TestCoverage::Complete, + [] (Hwc2Test* test, hwc2_display_t display, + Hwc2TestVirtualDisplay* testVirtualDisplay) { + + buffer_handle_t handle; + android::base::unique_fd acquireFence; + + if (testVirtualDisplay->getBuffer(&handle, &acquireFence) >= 0) + EXPECT_NO_FATAL_FAILURE(test->setOutputBuffer(display, + handle, acquireFence)); + })); +} + +/* TESTCASE: Tests that the HWC2 cannot set an output buffer for a bad display */ +TEST_F(Hwc2Test, SET_OUTPUT_BUFFER_bad_display) +{ + ASSERT_NO_FATAL_FAILURE(createVirtualDisplay(Hwc2TestCoverage::Default, + [] (Hwc2Test* test, hwc2_display_t /*display*/, + Hwc2TestVirtualDisplay* testVirtualDisplay) { + + hwc2_display_t badDisplay; + buffer_handle_t handle; + android::base::unique_fd acquireFence; + hwc2_error_t err = HWC2_ERROR_NONE; + + ASSERT_NO_FATAL_FAILURE(test->getBadDisplay(&badDisplay)); + + if (testVirtualDisplay->getBuffer(&handle, &acquireFence) < 0) + return; + + ASSERT_NO_FATAL_FAILURE(test->setOutputBuffer(badDisplay, + handle, acquireFence, &err)); + EXPECT_TRUE(err == HWC2_ERROR_BAD_DISPLAY) + << "returned wrong error code"; + })); +} + +/* TESTCASE: Tests that the HWC2 cannot set an invalid output buffer. */ +TEST_F(Hwc2Test, SET_OUTPUT_BUFFER_bad_parameter) +{ + ASSERT_NO_FATAL_FAILURE(createVirtualDisplay(Hwc2TestCoverage::Default, + [] (Hwc2Test* test, hwc2_display_t display, + Hwc2TestVirtualDisplay* /*testVirtualDisplay*/) { + + const buffer_handle_t handle = nullptr; + uint32_t releaseFence = -1; + hwc2_error_t err = HWC2_ERROR_NONE; + + ASSERT_NO_FATAL_FAILURE(test->setOutputBuffer(display, handle, + releaseFence, &err)); + EXPECT_EQ(err, HWC2_ERROR_BAD_PARAMETER) + << "returned wrong error code"; + })); +} + +/* TESTCASE: Tests that the HWC2 cannot set an output buffer for non virtual + * display */ +TEST_F(Hwc2Test, SET_OUTPUT_BUFFER_unsupported) +{ + for (auto display : mDisplays) { + Hwc2TestVirtualDisplay testVirtualDisplay(Hwc2TestCoverage::Complete); + + do { + buffer_handle_t handle; + android::base::unique_fd acquireFence; + hwc2_error_t err = HWC2_ERROR_NONE; + + if (testVirtualDisplay.getBuffer(&handle, &acquireFence) < 0) + continue; + + ASSERT_NO_FATAL_FAILURE(setOutputBuffer(display, handle, + acquireFence, &err)); + EXPECT_EQ(err, HWC2_ERROR_UNSUPPORTED) << "returned wrong error code"; + + } while (testVirtualDisplay.advance()); + } +} diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp index e00c56067e..b5522de3a5 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp @@ -321,6 +321,63 @@ const std::vector Hwc2TestDataspace::completeDataspaces = { }; +Hwc2TestDisplayDimension::Hwc2TestDisplayDimension(Hwc2TestCoverage coverage) + : Hwc2TestProperty( + (coverage == Hwc2TestCoverage::Complete)? mCompleteDisplayDimensions: + (coverage == Hwc2TestCoverage::Basic)? mBasicDisplayDimensions: + mDefaultDisplayDimensions, mCompositionSupport) { } + +std::string Hwc2TestDisplayDimension::dump() const +{ + std::stringstream dmp; + const UnsignedArea& curr = get(); + dmp << "\tdisplay dimension: " << curr.width<< " x " << curr.height<< "\n"; + return dmp.str(); +} + +void Hwc2TestDisplayDimension::setDependent(Hwc2TestBuffer* buffer) +{ + mBuffer = buffer; + updateDependents(); +} + +void Hwc2TestDisplayDimension::updateDependents() +{ + const UnsignedArea& curr = get(); + + if (mBuffer) + mBuffer->updateBufferArea({static_cast(curr.width), + static_cast(curr.height)}); +} + +const std::vector + Hwc2TestDisplayDimension::mDefaultDisplayDimensions = { + {1920, 1080}, +}; + +const std::vector + Hwc2TestDisplayDimension::mBasicDisplayDimensions = { + {640, 480}, + {1280, 720}, + {1920, 1080}, + {1920, 1200}, +}; + +const std::vector + Hwc2TestDisplayDimension::mCompleteDisplayDimensions = { + {320, 240}, + {480, 320}, + {640, 480}, + {1280, 720}, + {1920, 1080}, + {1920, 1200}, + {2560, 1440}, + {2560, 1600}, + {3840, 2160}, + {4096, 2160}, +}; + + Hwc2TestDisplayFrame::Hwc2TestDisplayFrame(Hwc2TestCoverage coverage, const Area& displayArea) : Hwc2TestProperty(mDisplayFrames, mCompositionSupport), @@ -694,6 +751,11 @@ const std::array Hwc2TestDataspace::mCompositionSupport = {{ false, true, true, true, true, false, }}; +/* INVALID CLIENT DEVICE COLOR CURSOR SIDEBAND */ +const std::array Hwc2TestDisplayDimension::mCompositionSupport = {{ + false, true, true, true, true, true, +}}; + /* INVALID CLIENT DEVICE COLOR CURSOR SIDEBAND */ const std::array Hwc2TestDisplayFrame::mCompositionSupport = {{ false, true, true, true, false, true, diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h index d978237cdf..c2029aba04 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h @@ -54,6 +54,12 @@ typedef struct { } Area; +typedef struct { + uint32_t width; + uint32_t height; +} UnsignedArea; + + class Hwc2TestContainer { public: virtual ~Hwc2TestContainer() = default; @@ -238,6 +244,27 @@ protected: }; +class Hwc2TestDisplayDimension : public Hwc2TestProperty { +public: + Hwc2TestDisplayDimension(Hwc2TestCoverage coverage); + + std::string dump() const; + + void setDependent(Hwc2TestBuffer* buffer); + +private: + void updateDependents(); + + Hwc2TestBuffer* mBuffer; + + static const std::vector mDefaultDisplayDimensions; + static const std::vector mBasicDisplayDimensions; + static const std::vector mCompleteDisplayDimensions; + + static const std::array mCompositionSupport; +}; + + class Hwc2TestDisplayFrame : public Hwc2TestProperty { public: Hwc2TestDisplayFrame(Hwc2TestCoverage coverage, const Area& displayArea); diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestVirtualDisplay.cpp b/services/surfaceflinger/tests/hwc2/Hwc2TestVirtualDisplay.cpp new file mode 100644 index 0000000000..d0fbc0b5ad --- /dev/null +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestVirtualDisplay.cpp @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "Hwc2TestVirtualDisplay.h" + +Hwc2TestVirtualDisplay::Hwc2TestVirtualDisplay( + Hwc2TestCoverage coverage) + : mDisplayDimension(coverage) +{ + mDisplayDimension.setDependent(&mBuffer); +} + +std::string Hwc2TestVirtualDisplay::dump() const +{ + std::stringstream dmp; + + dmp << "virtual display: \n"; + + mDisplayDimension.dump(); + + return dmp.str(); +} + +int Hwc2TestVirtualDisplay::getBuffer(buffer_handle_t* outHandle, + android::base::unique_fd* outAcquireFence) +{ + int32_t acquireFence; + int ret = mBuffer.get(outHandle, &acquireFence); + outAcquireFence->reset(acquireFence); + return ret; +} + +void Hwc2TestVirtualDisplay::reset() +{ + return mDisplayDimension.reset(); +} + +bool Hwc2TestVirtualDisplay::advance() +{ + return mDisplayDimension.advance(); +} + +UnsignedArea Hwc2TestVirtualDisplay::getDisplayDimension() const +{ + return mDisplayDimension.get(); +} diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestVirtualDisplay.h b/services/surfaceflinger/tests/hwc2/Hwc2TestVirtualDisplay.h new file mode 100644 index 0000000000..09420ef629 --- /dev/null +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestVirtualDisplay.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _HWC2_TEST_VIRTUAL_DISPLAY_H +#define _HWC2_TEST_VIRTUAL_DISPLAY_H + +#include "Hwc2TestBuffer.h" +#include "Hwc2TestProperties.h" + +#define HWC2_INCLUDE_STRINGIFICATION +#define HWC2_USE_CPP11 +#include +#undef HWC2_INCLUDE_STRINGIFICATION +#undef HWC2_USE_CPP11 + +class Hwc2TestVirtualDisplay { +public: + Hwc2TestVirtualDisplay(Hwc2TestCoverage coverage); + + std::string dump() const; + + int getBuffer(buffer_handle_t* outHandle, + android::base::unique_fd* outAcquireFence); + + void reset(); + bool advance(); + + UnsignedArea getDisplayDimension() const; + +private: + Hwc2TestBuffer mBuffer; + + Hwc2TestDisplayDimension mDisplayDimension; +}; + +#endif /* ifndef _HWC2_TEST_VIRTUAL_DISPLAY_H */ -- cgit v1.2.3-59-g8ed1b From ae7d324fcad6d561bc0ee460f296ff2ad8306b00 Mon Sep 17 00:00:00 2001 From: Marissa Wall Date: Thu, 15 Dec 2016 12:42:07 -0800 Subject: test-hwc2: dump Test: Add "#define HAVE_NO_SURFACE_FLINGER" to frameworks/native/libs/gui/BufferQueueCore.cpp. Recompile and flash. Run "mm" in frameworks/native/services/surfaceflinger/tests/hwc2. Push test-hwc2 to device. Run "adb root && adb shell stop". Run test case. Ex: "./test-hwc2" Change-Id: I0215fea464fd126b5f9041435bef7e00b46c6ac8 --- services/surfaceflinger/tests/hwc2/Hwc2Test.cpp | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp index 751a9cc9cc..062485ea52 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp +++ b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp @@ -1022,6 +1022,23 @@ public: } } + void dump(std::string* outBuffer) + { + auto pfn = reinterpret_cast( + getFunction(HWC2_FUNCTION_DUMP)); + ASSERT_TRUE(pfn) << "failed to get function"; + + uint32_t size = 0; + + pfn(mHwc2Device, &size, nullptr); + + std::vector buffer(size); + + pfn(mHwc2Device, &size, buffer.data()); + + outBuffer->assign(buffer.data()); + } + void getBadDisplay(hwc2_display_t* outDisplay) { for (hwc2_display_t display = 0; display < UINT64_MAX; display++) { @@ -4529,3 +4546,11 @@ TEST_F(Hwc2Test, SET_OUTPUT_BUFFER_unsupported) } while (testVirtualDisplay.advance()); } } + +/* TESTCASE: Tests that the HWC2 can dump debug information. */ +TEST_F(Hwc2Test, DUMP) +{ + std::string buffer; + + ASSERT_NO_FATAL_FAILURE(dump(&buffer)); +} -- cgit v1.2.3-59-g8ed1b