}
}
+ void setLayerVisibleRegion(hwc2_display_t display, hwc2_layer_t layer,
+ const hwc_region_t& visibleRegion, hwc2_error_t* outErr = nullptr)
+ {
+ auto pfn = reinterpret_cast<HWC2_PFN_SET_LAYER_VISIBLE_REGION>(
+ getFunction(HWC2_FUNCTION_SET_LAYER_VISIBLE_REGION));
+ ASSERT_TRUE(pfn) << "failed to get function";
+
+ auto err = static_cast<hwc2_error_t>(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)
{
/* 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 */
* 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<hwc2_config_t> configs;
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)));
}
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)
{
return testLayer->advanceTransform();
}
+bool advanceVisibleRegions(Hwc2TestLayers* testLayers)
+{
+ return testLayers->advanceVisibleRegions();
+}
+
static const std::array<hwc2_function_descriptor_t, 42> requiredFunctions = {{
HWC2_FUNCTION_ACCEPT_DISPLAY_CHANGES,
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)
{
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;
}
));
}
#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),
mPlaneAlpha(coverage),
mSourceCrop(coverage),
mSurfaceDamage(coverage),
- mTransform(coverage),
- mZOrder(zOrder)
+ mTransform(coverage)
{
mBufferArea.setDependent(&mBuffer);
mBufferArea.setDependent(&mSourceCrop);
dmp << property->dump();
}
+ dmp << mVisibleRegion.dump();
dmp << "\tz order: " << mZOrder << "\n";
return dmp.str();
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();
}
return mBlendMode.get();
}
+Area Hwc2TestLayer::getBufferArea() const
+{
+ return mBufferArea.get();
+}
+
hwc_color_t Hwc2TestLayer::getColor() const
{
return mColor.get();
return mTransform.get();
}
+hwc_region_t Hwc2TestLayer::getVisibleRegion() const
+{
+ return mVisibleRegion.get();
+}
+
uint32_t Hwc2TestLayer::getZOrder() const
{
return mZOrder;
{
return mTransform.advance();
}
+
+bool Hwc2TestLayer::advanceVisibleRegion()
+{
+ if (mPlaneAlpha.advance())
+ return true;
+ return mDisplayFrame.advance();
+}
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;
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();
bool advanceSourceCrop();
bool advanceSurfaceDamage();
bool advanceTransform();
+ bool advanceVisibleRegion();
private:
- std::array<Hwc2TestContainer*, 9> mProperties = {{
- &mBlendMode, &mColor, &mComposition, &mDataspace, &mDisplayFrame,
- &mPlaneAlpha, &mSourceCrop, &mSurfaceDamage, &mTransform
+ std::array<Hwc2TestContainer*, 10> mProperties = {{
+ &mBlendMode, &mBufferArea, &mColor, &mComposition, &mDataspace,
+ &mDisplayFrame, &mPlaneAlpha, &mSourceCrop, &mSurfaceDamage, &mTransform
}};
Hwc2TestBuffer mBuffer;
Hwc2TestSourceCrop mSourceCrop;
Hwc2TestSurfaceDamage mSurfaceDamage;
Hwc2TestTransform mTransform;
+ Hwc2TestVisibleRegion mVisibleRegion;
- uint32_t mZOrder;
+ uint32_t mZOrder = UINT32_MAX;
};
#endif /* ifndef _HWC2_TEST_LAYER_H */
Hwc2TestLayers::Hwc2TestLayers(const std::vector<hwc2_layer_t>& 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
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
}
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);
+ }
+}
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<hwc2_layer_t, Hwc2TestLayer> mTestLayers;
};
#include <sstream>
#include <cutils/log.h>
+#include <ui/Rect.h>
#define HWC2_INCLUDE_STRINGIFICATION
#define HWC2_USE_CPP11
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;
+}
#include <array>
#include <vector>
+#include <ui/Region.h>
+
#define HWC2_INCLUDE_STRINGIFICATION
#define HWC2_USE_CPP11
#include <hardware/hwcomposer2.h>
static const std::vector<hwc_transform_t> 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 */