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

Commit 8dc87156 authored by Dominik Laskowski's avatar Dominik Laskowski Committed by Android (Google) Code Review
Browse files

Merge changes I34af02d4,Ifc222d84,I74c8cffa into main

* changes:
  SF: Apply color matrix to newly connected displays
  SF: Extract CommitAndCompositeTest helper
  SF: Replace futureOf with ftl::yield in tests
parents 85b2524c 01f191c9
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -3764,6 +3764,9 @@ void SurfaceFlinger::processDisplayChangesLocked() {
        mVisibleRegionsDirty = true;
        mUpdateInputInfo = true;

        // Apply the current color matrix to any added or changed display.
        mCurrentState.colorMatrixChanged = true;

        // find the displays that were removed
        // (ie: in drawing state but not in current state)
        // also handle displays that changed
@@ -4308,7 +4311,6 @@ void SurfaceFlinger::doCommitTransactions() {
    }

    mDrawingState = mCurrentState;
    // clear the "changed" flags in current state
    mCurrentState.colorMatrixChanged = false;

    if (mVisibleRegionsDirty) {
+1 −0
Original line number Diff line number Diff line
@@ -95,6 +95,7 @@ cc_test {
        "MessageQueueTest.cpp",
        "PowerAdvisorTest.cpp",
        "SmallAreaDetectionAllowMappingsTest.cpp",
        "SurfaceFlinger_ColorMatrixTest.cpp",
        "SurfaceFlinger_CreateDisplayTest.cpp",
        "SurfaceFlinger_DestroyDisplayTest.cpp",
        "SurfaceFlinger_DisplayModeSwitching.cpp",
+86 −0
Original line number Diff line number Diff line
/*
 * Copyright 2024 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 <gtest/gtest.h>

#include <compositionengine/Display.h>
#include <compositionengine/mock/DisplaySurface.h>
#include <renderengine/mock/RenderEngine.h>

#include "TestableSurfaceFlinger.h"
#include "mock/DisplayHardware/MockComposer.h"
#include "mock/DisplayHardware/MockPowerAdvisor.h"
#include "mock/MockTimeStats.h"
#include "mock/system/window/MockNativeWindow.h"

namespace android {

// Minimal setup to use TestableSurfaceFlinger::commitAndComposite.
struct CommitAndCompositeTest : testing::Test {
    void SetUp() override {
        mFlinger.setupMockScheduler({.displayId = DEFAULT_DISPLAY_ID});
        mComposer = new Hwc2::mock::Composer();
        mPowerAdvisor = new Hwc2::mock::PowerAdvisor();
        mFlinger.setupRenderEngine(std::unique_ptr<renderengine::RenderEngine>(mRenderEngine));
        mFlinger.setupTimeStats(std::shared_ptr<TimeStats>(mTimeStats));
        mFlinger.setupComposer(std::unique_ptr<Hwc2::Composer>(mComposer));
        mFlinger.setupPowerAdvisor(std::unique_ptr<Hwc2::PowerAdvisor>(mPowerAdvisor));

        constexpr bool kIsPrimary = true;
        FakeHwcDisplayInjector(DEFAULT_DISPLAY_ID, hal::DisplayType::PHYSICAL, kIsPrimary)
                .setPowerMode(hal::PowerMode::ON)
                .inject(&mFlinger, mComposer);
        auto compostionEngineDisplayArgs =
                compositionengine::DisplayCreationArgsBuilder()
                        .setId(DEFAULT_DISPLAY_ID)
                        .setPixels({DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT})
                        .setPowerAdvisor(mPowerAdvisor)
                        .setName("Internal display")
                        .build();
        auto compositionDisplay =
                compositionengine::impl::createDisplay(mFlinger.getCompositionEngine(),
                                                       std::move(compostionEngineDisplayArgs));
        mDisplay = FakeDisplayDeviceInjector(mFlinger, compositionDisplay,
                                             ui::DisplayConnectionType::Internal, HWC_DISPLAY,
                                             kIsPrimary)
                           .setDisplaySurface(mDisplaySurface)
                           .setNativeWindow(mNativeWindow)
                           .setPowerMode(hal::PowerMode::ON)
                           .setRefreshRateSelector(mFlinger.scheduler()->refreshRateSelector())
                           .skipRegisterDisplay()
                           .inject();
    }

    using FakeHwcDisplayInjector = TestableSurfaceFlinger::FakeHwcDisplayInjector;
    using FakeDisplayDeviceInjector = TestableSurfaceFlinger::FakeDisplayDeviceInjector;

    static constexpr hal::HWDisplayId HWC_DISPLAY = FakeHwcDisplayInjector::DEFAULT_HWC_DISPLAY_ID;
    static constexpr PhysicalDisplayId DEFAULT_DISPLAY_ID = PhysicalDisplayId::fromPort(42u);
    static constexpr int DEFAULT_DISPLAY_WIDTH = 1920;
    static constexpr int DEFAULT_DISPLAY_HEIGHT = 1024;

    TestableSurfaceFlinger mFlinger;
    renderengine::mock::RenderEngine* mRenderEngine = new renderengine::mock::RenderEngine();
    sp<DisplayDevice> mDisplay;
    sp<compositionengine::mock::DisplaySurface> mDisplaySurface =
            sp<compositionengine::mock::DisplaySurface>::make();
    sp<mock::NativeWindow> mNativeWindow = sp<mock::NativeWindow>::make();
    mock::TimeStats* mTimeStats = new mock::TimeStats();
    Hwc2::mock::PowerAdvisor* mPowerAdvisor = nullptr;
    Hwc2::mock::Composer* mComposer = nullptr;
};

} // namespace android
+14 −18
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@

#include <compositionengine/Display.h>
#include <compositionengine/mock/DisplaySurface.h>
#include <ftl/future.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <gui/IProducerListener.h>
@@ -227,14 +228,6 @@ void CompositionTest::captureScreenComposition() {
    LayerCase::cleanup(this);
}

template <class T>
std::future<T> futureOf(T obj) {
    std::promise<T> resultPromise;
    std::future<T> resultFuture = resultPromise.get_future();
    resultPromise.set_value(std::move(obj));
    return resultFuture;
}

/* ------------------------------------------------------------------------
 * Variants for each display configuration which can be tested
 */
@@ -327,13 +320,13 @@ struct BaseDisplayVariant {
                .WillRepeatedly([&](const renderengine::DisplaySettings& displaySettings,
                                    const std::vector<renderengine::LayerSettings>&,
                                    const std::shared_ptr<renderengine::ExternalTexture>&,
                                    base::unique_fd&&) -> std::future<FenceResult> {
                                    base::unique_fd&&) -> ftl::Future<FenceResult> {
                    EXPECT_EQ(DEFAULT_DISPLAY_MAX_LUMINANCE, displaySettings.maxLuminance);
                    EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT),
                              displaySettings.physicalDisplay);
                    EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT),
                              displaySettings.clip);
                    return futureOf<FenceResult>(Fence::NO_FENCE);
                    return ftl::yield<FenceResult>(Fence::NO_FENCE);
                });
    }

@@ -378,14 +371,14 @@ struct BaseDisplayVariant {
                .WillRepeatedly([&](const renderengine::DisplaySettings& displaySettings,
                                    const std::vector<renderengine::LayerSettings>&,
                                    const std::shared_ptr<renderengine::ExternalTexture>&,
                                    base::unique_fd&&) -> std::future<FenceResult> {
                                    base::unique_fd&&) -> ftl::Future<FenceResult> {
                    EXPECT_EQ(DEFAULT_DISPLAY_MAX_LUMINANCE, displaySettings.maxLuminance);
                    EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT),
                              displaySettings.physicalDisplay);
                    EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT),
                              displaySettings.clip);
                    EXPECT_EQ(ui::Dataspace::UNKNOWN, displaySettings.outputDataspace);
                    return futureOf<FenceResult>(Fence::NO_FENCE);
                    return ftl::yield<FenceResult>(Fence::NO_FENCE);
                });
    }

@@ -578,7 +571,7 @@ struct BaseLayerProperties {
                .WillOnce([&](const renderengine::DisplaySettings& displaySettings,
                              const std::vector<renderengine::LayerSettings>& layerSettings,
                              const std::shared_ptr<renderengine::ExternalTexture>&,
                              base::unique_fd&&) -> std::future<FenceResult> {
                              base::unique_fd&&) -> ftl::Future<FenceResult> {
                    EXPECT_EQ(DEFAULT_DISPLAY_MAX_LUMINANCE, displaySettings.maxLuminance);
                    EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT),
                              displaySettings.physicalDisplay);
@@ -586,7 +579,8 @@ struct BaseLayerProperties {
                              displaySettings.clip);
                    // screen capture adds an additional color layer as an alpha
                    // prefill, so gtet the back layer.
                    std::future<FenceResult> resultFuture = futureOf<FenceResult>(Fence::NO_FENCE);
                    ftl::Future<FenceResult> resultFuture =
                            ftl::yield<FenceResult>(Fence::NO_FENCE);
                    if (layerSettings.empty()) {
                        ADD_FAILURE() << "layerSettings was not expected to be empty in "
                                         "setupREBufferCompositionCommonCallExpectations "
@@ -627,7 +621,7 @@ struct BaseLayerProperties {
                .WillOnce([&](const renderengine::DisplaySettings& displaySettings,
                              const std::vector<renderengine::LayerSettings>& layerSettings,
                              const std::shared_ptr<renderengine::ExternalTexture>&,
                              base::unique_fd&&) -> std::future<FenceResult> {
                              base::unique_fd&&) -> ftl::Future<FenceResult> {
                    EXPECT_EQ(DEFAULT_DISPLAY_MAX_LUMINANCE, displaySettings.maxLuminance);
                    EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT),
                              displaySettings.physicalDisplay);
@@ -635,7 +629,8 @@ struct BaseLayerProperties {
                              displaySettings.clip);
                    // screen capture adds an additional color layer as an alpha
                    // prefill, so get the back layer.
                    std::future<FenceResult> resultFuture = futureOf<FenceResult>(Fence::NO_FENCE);
                    ftl::Future<FenceResult> resultFuture =
                            ftl::yield<FenceResult>(Fence::NO_FENCE);
                    if (layerSettings.empty()) {
                        ADD_FAILURE()
                                << "layerSettings was not expected to be empty in "
@@ -709,7 +704,7 @@ struct CommonSecureLayerProperties : public BaseLayerProperties<LayerProperties>
                .WillOnce([&](const renderengine::DisplaySettings& displaySettings,
                              const std::vector<renderengine::LayerSettings>& layerSettings,
                              const std::shared_ptr<renderengine::ExternalTexture>&,
                              base::unique_fd&&) -> std::future<FenceResult> {
                              base::unique_fd&&) -> ftl::Future<FenceResult> {
                    EXPECT_EQ(DEFAULT_DISPLAY_MAX_LUMINANCE, displaySettings.maxLuminance);
                    EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT),
                              displaySettings.physicalDisplay);
@@ -717,7 +712,8 @@ struct CommonSecureLayerProperties : public BaseLayerProperties<LayerProperties>
                              displaySettings.clip);
                    // screen capture adds an additional color layer as an alpha
                    // prefill, so get the back layer.
                    std::future<FenceResult> resultFuture = futureOf<FenceResult>(Fence::NO_FENCE);
                    ftl::Future<FenceResult> resultFuture =
                            ftl::yield<FenceResult>(Fence::NO_FENCE);
                    if (layerSettings.empty()) {
                        ADD_FAILURE() << "layerSettings was not expected to be empty in "
                                         "setupInsecureREBufferCompositionCommonCallExpectations "
+63 −0
Original line number Diff line number Diff line
/*
 * Copyright 2024 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.
 */

#undef LOG_TAG
#define LOG_TAG "LibSurfaceFlingerUnittests"

#include "CommitAndCompositeTest.h"

#define EXPECT_COLOR_MATRIX_CHANGED(current, drawing)               \
    EXPECT_EQ(current, mFlinger.currentState().colorMatrixChanged); \
    EXPECT_EQ(drawing, mFlinger.drawingState().colorMatrixChanged);

namespace android {

class ColorMatrixTest : public CommitAndCompositeTest {};

TEST_F(ColorMatrixTest, colorMatrixChanged) {
    EXPECT_COLOR_MATRIX_CHANGED(true, true);
    mFlinger.mutableTransactionFlags() |= eTransactionNeeded;

    mFlinger.commitAndComposite();
    EXPECT_COLOR_MATRIX_CHANGED(false, false);

    mFlinger.setDaltonizerType(ColorBlindnessType::Deuteranomaly);
    EXPECT_COLOR_MATRIX_CHANGED(true, false);

    mFlinger.commit();
    EXPECT_COLOR_MATRIX_CHANGED(false, true);

    mFlinger.commitAndComposite();
    EXPECT_COLOR_MATRIX_CHANGED(false, false);
}

TEST_F(ColorMatrixTest, colorMatrixChangedAfterDisplayTransaction) {
    EXPECT_COLOR_MATRIX_CHANGED(true, true);
    mFlinger.mutableTransactionFlags() |= eTransactionNeeded;

    mFlinger.commitAndComposite();
    EXPECT_COLOR_MATRIX_CHANGED(false, false);

    mFlinger.createDisplay(String8("Test Display"), false);

    mFlinger.commit();
    EXPECT_COLOR_MATRIX_CHANGED(false, true);

    mFlinger.commitAndComposite();
    EXPECT_COLOR_MATRIX_CHANGED(false, false);
}

} // namespace android
Loading