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

Commit 337513b7 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Unify hwc2_device_t and HWComposer."

parents 6212df9b bdd08ccc
Loading
Loading
Loading
Loading
+0 −182
Original line number Diff line number Diff line
@@ -42,8 +42,6 @@ using android::HdrMetadata;
using android::Rect;
using android::Region;
using android::sp;
using android::hardware::Return;
using android::hardware::Void;

namespace HWC2 {

@@ -60,188 +58,8 @@ inline bool hasMetadataKey(const std::set<Hwc2::PerFrameMetadataKey>& keys,
    return keys.find(key) != keys.end();
}

class ComposerCallbackBridge : public Hwc2::IComposerCallback {
public:
    ComposerCallbackBridge(ComposerCallback* callback, int32_t sequenceId,
                           bool vsyncSwitchingSupported)
          : mCallback(callback),
            mSequenceId(sequenceId),
            mVsyncSwitchingSupported(vsyncSwitchingSupported) {}

    Return<void> onHotplug(Hwc2::Display display,
                           IComposerCallback::Connection conn) override
    {
        HWC2::Connection connection = static_cast<HWC2::Connection>(conn);
        mCallback->onHotplugReceived(mSequenceId, display, connection);
        return Void();
    }

    Return<void> onRefresh(Hwc2::Display display) override
    {
        mCallback->onRefreshReceived(mSequenceId, display);
        return Void();
    }

    Return<void> onVsync(Hwc2::Display display, int64_t timestamp) override
    {
        if (!mVsyncSwitchingSupported) {
            mCallback->onVsyncReceived(mSequenceId, display, timestamp, std::nullopt);
        } else {
            ALOGW("Unexpected onVsync callback on composer >= 2.4, ignoring.");
        }
        return Void();
    }

    Return<void> onVsync_2_4(Hwc2::Display display, int64_t timestamp,
                             Hwc2::VsyncPeriodNanos vsyncPeriodNanos) override {
        if (mVsyncSwitchingSupported) {
            // TODO(b/140201379): use vsyncPeriodNanos in the new DispSync
            mCallback->onVsyncReceived(mSequenceId, display, timestamp,
                                       std::make_optional(vsyncPeriodNanos));
        } else {
            ALOGW("Unexpected onVsync_2_4 callback on composer <= 2.3, ignoring.");
        }
        return Void();
    }

    Return<void> onVsyncPeriodTimingChanged(
            Hwc2::Display display,
            const Hwc2::VsyncPeriodChangeTimeline& updatedTimeline) override {
        hwc_vsync_period_change_timeline_t timeline;
        timeline.newVsyncAppliedTimeNanos = updatedTimeline.newVsyncAppliedTimeNanos;
        timeline.refreshRequired = updatedTimeline.refreshRequired;
        timeline.refreshTimeNanos = updatedTimeline.refreshTimeNanos;
        mCallback->onVsyncPeriodTimingChangedReceived(mSequenceId, display, timeline);
        return Void();
    }

private:
    ComposerCallback* mCallback;
    int32_t mSequenceId;
    const bool mVsyncSwitchingSupported;
};

} // namespace anonymous


// Device methods

Device::Device(std::unique_ptr<android::Hwc2::Composer> composer) : mComposer(std::move(composer)) {
    loadCapabilities();
}

void Device::registerCallback(ComposerCallback* callback, int32_t sequenceId) {
    if (mRegisteredCallback) {
        ALOGW("Callback already registered. Ignored extra registration "
                "attempt.");
        return;
    }
    mRegisteredCallback = true;
    sp<ComposerCallbackBridge> callbackBridge(
            new ComposerCallbackBridge(callback, sequenceId,
                                       mComposer->isVsyncPeriodSwitchSupported()));
    mComposer->registerCallback(callbackBridge);
}

// Required by HWC2 device

std::string Device::dump() const
{
    return mComposer->dumpDebugInfo();
}

uint32_t Device::getMaxVirtualDisplayCount() const
{
    return mComposer->getMaxVirtualDisplayCount();
}

Error Device::getDisplayIdentificationData(hwc2_display_t hwcDisplayId, uint8_t* outPort,
                                           std::vector<uint8_t>* outData) const {
    auto intError = mComposer->getDisplayIdentificationData(hwcDisplayId, outPort, outData);
    return static_cast<Error>(intError);
}

Error Device::createVirtualDisplay(uint32_t width, uint32_t height,
        PixelFormat* format, Display** outDisplay)
{
    ALOGI("Creating virtual display");

    hwc2_display_t displayId = 0;
    auto intError = mComposer->createVirtualDisplay(width, height,
            format, &displayId);
    auto error = static_cast<Error>(intError);
    if (error != Error::None) {
        return error;
    }

    auto display = std::make_unique<impl::Display>(*mComposer.get(), mCapabilities, displayId,
                                                   DisplayType::Virtual);
    display->setConnected(true);
    *outDisplay = display.get();
    mDisplays.emplace(displayId, std::move(display));
    ALOGI("Created virtual display");
    return Error::None;
}

void Device::destroyDisplay(hwc2_display_t displayId)
{
    ALOGI("Destroying display %" PRIu64, displayId);
    mDisplays.erase(displayId);
}

void Device::onHotplug(hwc2_display_t displayId, Connection connection) {
    if (connection == Connection::Connected) {
        // If we get a hotplug connected event for a display we already have,
        // destroy the display and recreate it. This will force us to requery
        // the display params and recreate all layers on that display.
        auto oldDisplay = getDisplayById(displayId);
        if (oldDisplay != nullptr && oldDisplay->isConnected()) {
            ALOGI("Hotplug connecting an already connected display."
                    " Clearing old display state.");
        }
        mDisplays.erase(displayId);

        auto newDisplay = std::make_unique<impl::Display>(*mComposer.get(), mCapabilities,
                                                          displayId, DisplayType::Physical);
        newDisplay->setConnected(true);
        mDisplays.emplace(displayId, std::move(newDisplay));
    } else if (connection == Connection::Disconnected) {
        // The display will later be destroyed by a call to
        // destroyDisplay(). For now we just mark it disconnected.
        auto display = getDisplayById(displayId);
        if (display) {
            display->setConnected(false);
        } else {
            ALOGW("Attempted to disconnect unknown display %" PRIu64,
                  displayId);
        }
    }
}

// Other Device methods

Display* Device::getDisplayById(hwc2_display_t id) {
    auto iter = mDisplays.find(id);
    return iter == mDisplays.end() ? nullptr : iter->second.get();
}

// Device initialization methods

void Device::loadCapabilities()
{
    static_assert(sizeof(Capability) == sizeof(int32_t),
            "Capability size has changed");
    auto capabilities = mComposer->getCapabilities();
    for (auto capability : capabilities) {
        mCapabilities.emplace(static_cast<Capability>(capability));
    }
}

Error Device::flushCommands()
{
    return static_cast<Error>(mComposer->executeCommands());
}

// Display methods
Display::~Display() = default;

+0 −51
Original line number Diff line number Diff line
@@ -52,7 +52,6 @@ namespace android {

namespace HWC2 {

class Display;
class Layer;
using VsyncPeriodChangeConstraints = hwc_vsync_period_change_constraints_t;
using VsyncPeriodChangeTimeline = hwc_vsync_period_change_timeline_t;
@@ -81,56 +80,6 @@ class ComposerCallback {
    virtual ~ComposerCallback() = default;
};

// C++ Wrapper around hwc2_device_t. Load all functions pointers
// and handle callback registration.
class Device
{
public:
    explicit Device(std::unique_ptr<android::Hwc2::Composer> composer);

    void registerCallback(ComposerCallback* callback, int32_t sequenceId);

    // Required by HWC2

    std::string dump() const;

    const std::unordered_set<Capability>& getCapabilities() const {
        return mCapabilities;
    };

    uint32_t getMaxVirtualDisplayCount() const;
    Error getDisplayIdentificationData(hwc2_display_t hwcDisplayId, uint8_t* outPort,
                                       std::vector<uint8_t>* outData) const;

    Error createVirtualDisplay(uint32_t width, uint32_t height,
            android::ui::PixelFormat* format, Display** outDisplay);
    void destroyDisplay(hwc2_display_t displayId);

    void onHotplug(hwc2_display_t displayId, Connection connection);

    // Other Device methods

    Display* getDisplayById(hwc2_display_t id);

    android::Hwc2::Composer* getComposer() { return mComposer.get(); }

    // We buffer most state changes and flush them implicitly with
    // Display::validate, Display::present, and Display::presentOrValidate.
    // This method provides an explicit way to flush state changes to HWC.
    Error flushCommands();

private:
    // Initialization methods

    void loadCapabilities();

    // Member variables
    std::unique_ptr<android::Hwc2::Composer> mComposer;
    std::unordered_set<Capability> mCapabilities;
    std::unordered_map<hwc2_display_t, std::unique_ptr<Display>> mDisplays;
    bool mRegisteredCallback = false;
};

// Convenience C++ class to access hwc2_device_t Display functions directly.
class Display {
public:
+141 −30
Original line number Diff line number Diff line
@@ -65,14 +65,88 @@
#define RETURN_IF_HWC_ERROR(error, displayId, ...) \
    RETURN_IF_HWC_ERROR_FOR(__FUNCTION__, error, displayId, __VA_ARGS__)

namespace {

using android::hardware::Return;
using android::hardware::Void;

class ComposerCallbackBridge : public android::Hwc2::IComposerCallback {
public:
    ComposerCallbackBridge(HWC2::ComposerCallback* callback, int32_t sequenceId,
                           bool vsyncSwitchingSupported)
          : mCallback(callback),
            mSequenceId(sequenceId),
            mVsyncSwitchingSupported(vsyncSwitchingSupported) {}

    android::hardware::Return<void> onHotplug(
            android::Hwc2::Display display,
            android::Hwc2::IComposerCallback::Connection conn) override {
        HWC2::Connection connection = static_cast<HWC2::Connection>(conn);
        mCallback->onHotplugReceived(mSequenceId, display, connection);
        return android::hardware::Void();
    }

    android::hardware::Return<void> onRefresh(android::Hwc2::Display display) override {
        mCallback->onRefreshReceived(mSequenceId, display);
        return android::hardware::Void();
    }

    android::hardware::Return<void> onVsync(android::Hwc2::Display display,
                                            int64_t timestamp) override {
        if (!mVsyncSwitchingSupported) {
            mCallback->onVsyncReceived(mSequenceId, display, timestamp, std::nullopt);
        } else {
            ALOGW("Unexpected onVsync callback on composer >= 2.4, ignoring.");
        }
        return android::hardware::Void();
    }

    android::hardware::Return<void> onVsync_2_4(
            android::Hwc2::Display display, int64_t timestamp,
            android::Hwc2::VsyncPeriodNanos vsyncPeriodNanos) override {
        if (mVsyncSwitchingSupported) {
            // TODO(b/140201379): use vsyncPeriodNanos in the new DispSync
            mCallback->onVsyncReceived(mSequenceId, display, timestamp,
                                       std::make_optional(vsyncPeriodNanos));
        } else {
            ALOGW("Unexpected onVsync_2_4 callback on composer <= 2.3, ignoring.");
        }
        return android::hardware::Void();
    }

    android::hardware::Return<void> onVsyncPeriodTimingChanged(
            android::Hwc2::Display display,
            const android::Hwc2::VsyncPeriodChangeTimeline& updatedTimeline) override {
        hwc_vsync_period_change_timeline_t timeline;
        timeline.newVsyncAppliedTimeNanos = updatedTimeline.newVsyncAppliedTimeNanos;
        timeline.refreshRequired = updatedTimeline.refreshRequired;
        timeline.refreshTimeNanos = updatedTimeline.refreshTimeNanos;
        mCallback->onVsyncPeriodTimingChangedReceived(mSequenceId, display, timeline);
        return android::hardware::Void();
    }

private:
    HWC2::ComposerCallback* mCallback;
    const int32_t mSequenceId;
    const bool mVsyncSwitchingSupported;
};

} // namespace

namespace android {

HWComposer::~HWComposer() = default;

namespace impl {

HWComposer::HWComposer(std::unique_ptr<Hwc2::Composer> composer)
      : mHwcDevice(std::make_unique<HWC2::Device>(std::move(composer))) {}
HWComposer::HWComposer(std::unique_ptr<Hwc2::Composer> composer) : mComposer(std::move(composer)) {
    loadCapabilities();
}

HWComposer::HWComposer(const std::string& composerServiceName)
      : mComposer(std::make_unique<Hwc2::impl::Composer>(composerServiceName)) {
    loadCapabilities();
}

HWComposer::~HWComposer() {
    mDisplayData.clear();
@@ -80,12 +154,21 @@ HWComposer::~HWComposer() {

void HWComposer::registerCallback(HWC2::ComposerCallback* callback,
                                  int32_t sequenceId) {
    mHwcDevice->registerCallback(callback, sequenceId);
    if (mRegisteredCallback) {
        ALOGW("Callback already registered. Ignored extra registration attempt.");
        return;
    }
    mRegisteredCallback = true;
    sp<ComposerCallbackBridge> callbackBridge(
            new ComposerCallbackBridge(callback, sequenceId,
                                       mComposer->isVsyncPeriodSwitchSupported()));
    mComposer->registerCallback(callbackBridge);
}

bool HWComposer::getDisplayIdentificationData(hwc2_display_t hwcDisplayId, uint8_t* outPort,
                                              DisplayIdentificationData* outData) const {
    const auto error = mHwcDevice->getDisplayIdentificationData(hwcDisplayId, outPort, outData);
    const auto error = static_cast<HWC2::Error>(
            mComposer->getDisplayIdentificationData(hwcDisplayId, outPort, outData));
    if (error != HWC2::Error::None) {
        if (error != HWC2::Error::Unsupported) {
            LOG_HWC_DISPLAY_ERROR(hwcDisplayId, to_string(error).c_str());
@@ -95,9 +178,8 @@ bool HWComposer::getDisplayIdentificationData(hwc2_display_t hwcDisplayId, uint8
    return true;
}

bool HWComposer::hasCapability(HWC2::Capability capability) const
{
    return mHwcDevice->getCapabilities().count(capability) > 0;
bool HWComposer::hasCapability(HWC2::Capability capability) const {
    return mCapabilities.count(capability) > 0;
}

bool HWComposer::hasDisplayCapability(const std::optional<DisplayId>& displayId,
@@ -133,13 +215,33 @@ std::optional<DisplayIdentificationInfo> HWComposer::onHotplug(hwc2_display_t hw
          hwcDisplayId == mInternalHwcDisplayId ? "internal" : "external",
          to_string(info->id).c_str(), hwcDisplayId);

    mHwcDevice->onHotplug(hwcDisplayId, connection);

    // Disconnect is handled through HWComposer::disconnectDisplay via
    // SurfaceFlinger's onHotplugReceived callback handling
    if (connection == HWC2::Connection::Connected) {
        mDisplayData[info->id].hwcDisplay = mHwcDevice->getDisplayById(hwcDisplayId);
        auto& displayData = mDisplayData[info->id];
        // If we get a hotplug connected event for a display we already have,
        // destroy the display and recreate it. This will force us to requery
        // the display params and recreate all layers on that display.
        if (displayData.hwcDisplay != nullptr && displayData.hwcDisplay->isConnected()) {
            ALOGI("Hotplug connecting an already connected display."
                  " Clearing old display state.");
        }
        displayData.hwcDisplay.reset();
        auto newDisplay =
                std::make_unique<HWC2::impl::Display>(*mComposer.get(), mCapabilities, hwcDisplayId,
                                                      HWC2::DisplayType::Physical);
        newDisplay->setConnected(true);
        displayData.hwcDisplay = std::move(newDisplay);
        mPhysicalDisplayIdMap[hwcDisplayId] = info->id;
    } else if (connection == HWC2::Connection::Disconnected) {
        // The display will later be destroyed by a call to
        // destroyDisplay(). For now we just mark it disconnected.
        auto& displayData = mDisplayData[info->id];
        if (displayData.hwcDisplay) {
            displayData.hwcDisplay->setConnected(false);
        } else {
            ALOGW("Attempted to disconnect unknown display %" PRIu64, hwcDisplayId);
        }
        // The cleanup of Disconnect is handled through HWComposer::disconnectDisplay
        // via SurfaceFlinger's onHotplugReceived callback handling
    }

    return info;
@@ -197,14 +299,18 @@ std::optional<DisplayId> HWComposer::allocateVirtualDisplay(uint32_t width, uint
              height, SurfaceFlinger::maxVirtualDisplaySize);
        return {};
    }
    HWC2::Display* display;
    auto error = mHwcDevice->createVirtualDisplay(width, height, format,
            &display);
    hwc2_display_t hwcDisplayId = 0;
    const auto error = static_cast<HWC2::Error>(
            mComposer->createVirtualDisplay(width, height, format, &hwcDisplayId));
    if (error != HWC2::Error::None) {
        ALOGE("%s: Failed to create HWC virtual display", __FUNCTION__);
        return {};
    }

    auto display = std::make_unique<HWC2::impl::Display>(*mComposer.get(), mCapabilities,
                                                         hwcDisplayId, HWC2::DisplayType::Virtual);
    display->setConnected(true);

    DisplayId displayId;
    if (mFreeVirtualDisplayIds.empty()) {
        displayId = getVirtualDisplayId(mNextVirtualDisplayId++);
@@ -214,7 +320,7 @@ std::optional<DisplayId> HWComposer::allocateVirtualDisplay(uint32_t width, uint
    }

    auto& displayData = mDisplayData[displayId];
    displayData.hwcDisplay = display;
    displayData.hwcDisplay = std::move(display);
    displayData.isVirtual = true;

    --mRemainingHwcVirtualDisplays;
@@ -224,9 +330,8 @@ std::optional<DisplayId> HWComposer::allocateVirtualDisplay(uint32_t width, uint
HWC2::Layer* HWComposer::createLayer(DisplayId displayId) {
    RETURN_IF_INVALID_DISPLAY(displayId, nullptr);

    auto display = mDisplayData[displayId].hwcDisplay;
    HWC2::Layer* layer;
    auto error = display->createLayer(&layer);
    auto error = mDisplayData[displayId].hwcDisplay->createLayer(&layer);
    RETURN_IF_HWC_ERROR(error, displayId, nullptr);
    return layer;
}
@@ -234,8 +339,7 @@ HWC2::Layer* HWComposer::createLayer(DisplayId displayId) {
void HWComposer::destroyLayer(DisplayId displayId, HWC2::Layer* layer) {
    RETURN_IF_INVALID_DISPLAY(displayId);

    auto display = mDisplayData[displayId].hwcDisplay;
    auto error = display->destroyLayer(layer);
    auto error = mDisplayData[displayId].hwcDisplay->destroyLayer(layer);
    RETURN_IF_HWC_ERROR(error, displayId);
}

@@ -484,8 +588,8 @@ status_t HWComposer::presentAndGetReleaseFences(DisplayId displayId) {

    if (displayData.validateWasSkipped) {
        // explicitly flush all pending commands
        auto error = mHwcDevice->flushCommands();
        RETURN_IF_HWC_ERROR_FOR("flushCommands", error, displayId, UNKNOWN_ERROR);
        auto error = static_cast<HWC2::Error>(mComposer->executeCommands());
        RETURN_IF_HWC_ERROR_FOR("executeCommands", error, displayId, UNKNOWN_ERROR);
        RETURN_IF_HWC_ERROR_FOR("present", displayData.presentError, displayId, UNKNOWN_ERROR);
        return NO_ERROR;
    }
@@ -600,8 +704,6 @@ void HWComposer::disconnectDisplay(DisplayId displayId) {
    }

    const auto hwcDisplayId = displayData.hwcDisplay->getId();
    mPhysicalDisplayIdMap.erase(hwcDisplayId);
    mDisplayData.erase(displayId);

    // TODO(b/74619554): Select internal/external display from remaining displays.
    if (hwcDisplayId == mInternalHwcDisplayId) {
@@ -609,8 +711,8 @@ void HWComposer::disconnectDisplay(DisplayId displayId) {
    } else if (hwcDisplayId == mExternalHwcDisplayId) {
        mExternalHwcDisplayId.reset();
    }

    mHwcDevice->destroyDisplay(hwcDisplayId);
    mPhysicalDisplayIdMap.erase(hwcDisplayId);
    mDisplayData.erase(displayId);
}

status_t HWComposer::setOutputBuffer(DisplayId displayId, const sp<Fence>& acquireFence,
@@ -761,10 +863,7 @@ status_t HWComposer::setContentType(DisplayId displayId, HWC2::ContentType conte
}

void HWComposer::dump(std::string& result) const {
    // TODO: In order to provide a dump equivalent to HWC1, we need to shadow
    // all the state going into the layers. This is probably better done in
    // Layer itself, but it's going to take a bit of work to get there.
    result.append(mHwcDevice->dump());
    result.append(mComposer->dumpDebugInfo());
}

std::optional<DisplayId> HWComposer::toPhysicalDisplayId(hwc2_display_t hwcDisplayId) const {
@@ -830,5 +929,17 @@ std::optional<DisplayIdentificationInfo> HWComposer::onHotplugConnect(hwc2_displ
                                                                           : "External display"};
}

void HWComposer::loadCapabilities() {
    static_assert(sizeof(HWC2::Capability) == sizeof(int32_t), "Capability size has changed");
    auto capabilities = mComposer->getCapabilities();
    for (auto capability : capabilities) {
        mCapabilities.emplace(static_cast<HWC2::Capability>(capability));
    }
}

uint32_t HWComposer::getMaxVirtualDisplayCount() const {
    return mComposer->getMaxVirtualDisplayCount();
}

} // namespace impl
} // namespace android
+9 −7
Original line number Diff line number Diff line
@@ -207,6 +207,7 @@ namespace impl {
class HWComposer final : public android::HWComposer {
public:
    explicit HWComposer(std::unique_ptr<Hwc2::Composer> composer);
    explicit HWComposer(const std::string& composerServiceName);

    ~HWComposer() override;

@@ -325,7 +326,7 @@ public:
    // for debugging ----------------------------------------------------------
    void dump(std::string& out) const override;

    Hwc2::Composer* getComposer() const override { return mHwcDevice->getComposer(); }
    Hwc2::Composer* getComposer() const override { return mComposer.get(); }

    // TODO(b/74619554): Remove special cases for internal/external display.
    std::optional<hwc2_display_t> getInternalHwcDisplayId() const override {
@@ -343,11 +344,12 @@ private:
    friend TestableSurfaceFlinger;

    std::optional<DisplayIdentificationInfo> onHotplugConnect(hwc2_display_t hwcDisplayId);
    void loadCapabilities();
    uint32_t getMaxVirtualDisplayCount() const;

    struct DisplayData {
        bool isVirtual = false;

        HWC2::Display* hwcDisplay = nullptr;
        std::unique_ptr<HWC2::Display> hwcDisplay;
        sp<Fence> lastPresentFence = Fence::NO_FENCE; // signals when the last set op retires
        std::unordered_map<HWC2::Layer*, sp<Fence>> releaseFences;
        buffer_handle_t outbufHandle = nullptr;
@@ -369,9 +371,9 @@ private:

    std::unordered_map<DisplayId, DisplayData> mDisplayData;

    // This must be destroyed before mDisplayData, because destructor may call back into HWComposer
    // and look up DisplayData.
    std::unique_ptr<HWC2::Device> mHwcDevice;
    std::unique_ptr<android::Hwc2::Composer> mComposer;
    std::unordered_set<HWC2::Capability> mCapabilities;
    bool mRegisteredCallback = false;

    std::unordered_map<hwc2_display_t, DisplayId> mPhysicalDisplayIdMap;
    std::optional<hwc2_display_t> mInternalHwcDisplayId;
@@ -380,7 +382,7 @@ private:

    std::unordered_set<DisplayId> mFreeVirtualDisplayIds;
    uint32_t mNextVirtualDisplayId = 0;
    uint32_t mRemainingHwcVirtualDisplays{mHwcDevice->getMaxVirtualDisplayCount()};
    uint32_t mRemainingHwcVirtualDisplays{getMaxVirtualDisplayCount()};
};

} // namespace impl
+1 −2
Original line number Diff line number Diff line
@@ -52,8 +52,7 @@ std::unique_ptr<EventControlThread> DefaultFactory::createEventControlThread(
}

std::unique_ptr<HWComposer> DefaultFactory::createHWComposer(const std::string& serviceName) {
    return std::make_unique<android::impl::HWComposer>(
            std::make_unique<Hwc2::impl::Composer>(serviceName));
    return std::make_unique<android::impl::HWComposer>(serviceName);
}

std::unique_ptr<MessageQueue> DefaultFactory::createMessageQueue() {
Loading