|  | /* * 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 <sstream> | 
|  | #include <gtest/gtest.h> | 
|  |  | 
|  | #include "Hwc2TestLayers.h" | 
|  |  | 
|  | Hwc2TestLayers::Hwc2TestLayers(const std::vector<hwc2_layer_t>& layers, | 
|  | Hwc2TestCoverage coverage, const Area& displayArea) | 
|  | : Hwc2TestLayers(layers, coverage, displayArea, | 
|  | std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage>()) { } | 
|  |  | 
|  | Hwc2TestLayers::Hwc2TestLayers(const std::vector<hwc2_layer_t>& layers, | 
|  | Hwc2TestCoverage coverage, const Area& displayArea, | 
|  | const std::unordered_map<Hwc2TestPropertyName, | 
|  | Hwc2TestCoverage>& coverageExceptions) | 
|  | : mDisplayArea(displayArea) | 
|  | { | 
|  | for (auto layer : layers) { | 
|  | mTestLayers.emplace(std::piecewise_construct, | 
|  | std::forward_as_tuple(layer), | 
|  | std::forward_as_tuple(coverage, displayArea, coverageExceptions)); | 
|  | } | 
|  |  | 
|  | /* 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 | 
|  | { | 
|  | std::stringstream dmp; | 
|  | for (auto& testLayer : mTestLayers) { | 
|  | dmp << testLayer.second.dump(); | 
|  | } | 
|  | return dmp.str(); | 
|  | } | 
|  |  | 
|  | void Hwc2TestLayers::reset() | 
|  | { | 
|  | for (auto& testLayer : mTestLayers) { | 
|  | testLayer.second.reset(); | 
|  | } | 
|  |  | 
|  | setVisibleRegions(); | 
|  | } | 
|  |  | 
|  | bool Hwc2TestLayers::advance() | 
|  | { | 
|  | 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; | 
|  | } | 
|  | } | 
|  | return false; | 
|  | } | 
|  |  | 
|  | bool Hwc2TestLayers::advanceVisibleRegions() | 
|  | { | 
|  | 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; | 
|  | } | 
|  | } | 
|  | 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; | 
|  | } | 
|  |  | 
|  | 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(); | 
|  | } | 
|  |  | 
|  | 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) { | 
|  | []() { 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) { | 
|  | []() { GTEST_FAIL(); }(); | 
|  | } | 
|  | return mTestLayers.at(layer).getVisibleRegion(); | 
|  | } | 
|  |  | 
|  | uint32_t Hwc2TestLayers::getZOrder(hwc2_layer_t layer) const | 
|  | { | 
|  | if (mTestLayers.count(layer) == 0) { | 
|  | []() { GTEST_FAIL(); }(); | 
|  | } | 
|  | return mTestLayers.at(layer).getZOrder(); | 
|  | } | 
|  |  | 
|  | /* 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; | 
|  |  | 
|  | /* 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 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; | 
|  | } |