/* * 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::ui::Dataspace 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; }