Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bad1bc78 authored by Marissa Wall's avatar Marissa Wall
Browse files

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
parent 35040c55
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -47,6 +47,7 @@ LOCAL_SRC_FILES := \
    Hwc2TestLayer.cpp \
    Hwc2TestLayers.cpp \
    Hwc2TestBuffer.cpp \
    Hwc2TestClientTarget.cpp
    Hwc2TestClientTarget.cpp \
    Hwc2TestVirtualDisplay.cpp

include $(BUILD_NATIVE_TEST)
+310 −0
Original line number Diff line number Diff line
@@ -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<HWC2_PFN_CREATE_VIRTUAL_DISPLAY>(
                getFunction(HWC2_FUNCTION_CREATE_VIRTUAL_DISPLAY));
        ASSERT_TRUE(pfn) << "failed to get function";

        auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, width, height,
                reinterpret_cast<int32_t*>(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<HWC2_PFN_DESTROY_VIRTUAL_DISPLAY>(
                getFunction(HWC2_FUNCTION_DESTROY_VIRTUAL_DISPLAY));
        ASSERT_TRUE(pfn) << "failed to get function";

        auto err = static_cast<hwc2_error_t>(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<HWC2_PFN_GET_MAX_VIRTUAL_DISPLAY_COUNT>(
                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<HWC2_PFN_SET_OUTPUT_BUFFER>(
                getFunction(HWC2_FUNCTION_SET_OUTPUT_BUFFER));
        ASSERT_TRUE(pfn) << "failed to get function";

        auto err = static_cast<hwc2_error_t>(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<hwc2_display_t> mActiveDisplays;

    /* Store all created virtual displays that have not been destroyed. If an
     * ASSERT_* fails, then destroy the virtual displays on exit */
    std::set<hwc2_display_t> 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<hwc2_display_t> 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<hwc2_display_t> 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());
    }
}
+62 −0
Original line number Diff line number Diff line
@@ -321,6 +321,63 @@ const std::vector<android_dataspace_t> 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<int32_t>(curr.width),
                static_cast<int32_t>(curr.height)});
}

const std::vector<UnsignedArea>
        Hwc2TestDisplayDimension::mDefaultDisplayDimensions = {
    {1920, 1080},
};

const std::vector<UnsignedArea>
        Hwc2TestDisplayDimension::mBasicDisplayDimensions = {
    {640, 480},
    {1280, 720},
    {1920, 1080},
    {1920, 1200},
};

const std::vector<UnsignedArea>
        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<bool, 6> Hwc2TestDataspace::mCompositionSupport = {{
    false,   true,    true,    true,    true,    false,
}};

/*  INVALID  CLIENT   DEVICE   COLOR    CURSOR   SIDEBAND */
const std::array<bool, 6> Hwc2TestDisplayDimension::mCompositionSupport = {{
    false,   true,    true,    true,    true,    true,
}};

/*  INVALID  CLIENT   DEVICE   COLOR    CURSOR   SIDEBAND */
const std::array<bool, 6> Hwc2TestDisplayFrame::mCompositionSupport = {{
    false,   true,    true,    true,    false,   true,
+27 −0
Original line number Diff line number Diff line
@@ -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<UnsignedArea> {
public:
    Hwc2TestDisplayDimension(Hwc2TestCoverage coverage);

    std::string dump() const;

    void setDependent(Hwc2TestBuffer* buffer);

private:
    void updateDependents();

    Hwc2TestBuffer* mBuffer;

    static const std::vector<UnsignedArea> mDefaultDisplayDimensions;
    static const std::vector<UnsignedArea> mBasicDisplayDimensions;
    static const std::vector<UnsignedArea> mCompleteDisplayDimensions;

    static const std::array<bool, 6> mCompositionSupport;
};


class Hwc2TestDisplayFrame : public Hwc2TestProperty<hwc_rect_t> {
public:
    Hwc2TestDisplayFrame(Hwc2TestCoverage coverage, const Area& displayArea);
+61 −0
Original line number Diff line number Diff line
/*
 * 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 "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();
}
Loading