diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2022-09-12 23:06:07 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2022-09-12 23:06:07 +0000 |
commit | 4b7b3264fec3e413eedc210c0199366f01298baf (patch) | |
tree | 1946a087eae8f2453fe403704b4e390499c22d4b | |
parent | 92ee642e5fc0f9cac1512dd247da950775501a8d (diff) | |
parent | 35506601ebf83a6bcd83a57510872e90f09c73f9 (diff) | |
download | goldfish-opengl-4b7b3264fec3e413eedc210c0199366f01298baf.tar.gz |
Snap for 9053530 from 35506601ebf83a6bcd83a57510872e90f09c73f9 to tm-qpr1-releaseandroid-13.0.0_r30android-13.0.0_r29android-13.0.0_r28android-13.0.0_r27android-13.0.0_r24android-13.0.0_r23android-13.0.0_r22android-13.0.0_r21android-13.0.0_r20android-13.0.0_r19android-13.0.0_r18android-13.0.0_r17android-13.0.0_r16android13-qpr1-s8-releaseandroid13-qpr1-s7-releaseandroid13-qpr1-s6-releaseandroid13-qpr1-s5-releaseandroid13-qpr1-s4-releaseandroid13-qpr1-s3-releaseandroid13-qpr1-s2-releaseandroid13-qpr1-s1-releaseandroid13-qpr1-release
Change-Id: If3ec775d1117c7bda789f7700b62a045fb52ece5
-rw-r--r-- | system/hwc2/Android.mk | 1 | ||||
-rw-r--r-- | system/hwc2/ClientComposer.cpp | 144 | ||||
-rw-r--r-- | system/hwc2/ClientComposer.h | 73 | ||||
-rw-r--r-- | system/hwc2/Common.cpp | 4 | ||||
-rw-r--r-- | system/hwc2/Common.h | 1 | ||||
-rw-r--r-- | system/hwc2/Device.cpp | 4 | ||||
-rw-r--r-- | system/hwc3/ClientFrameComposer.cpp | 5 | ||||
-rw-r--r-- | system/hwc3/ClientFrameComposer.h | 6 | ||||
-rw-r--r-- | system/hwc3/Common.cpp | 20 | ||||
-rw-r--r-- | system/hwc3/Common.h | 8 | ||||
-rw-r--r-- | system/hwc3/ComposerClient.cpp | 2 | ||||
-rw-r--r-- | system/hwc3/Device.cpp | 4 | ||||
-rw-r--r-- | system/hwc3/DisplayFinder.cpp | 72 | ||||
-rw-r--r-- | system/hwc3/DisplayFinder.h | 5 | ||||
-rw-r--r-- | system/hwc3/DrmPresenter.cpp | 100 | ||||
-rw-r--r-- | system/hwc3/DrmPresenter.h | 25 | ||||
-rw-r--r-- | system/hwc3/FrameComposer.h | 5 | ||||
-rw-r--r-- | system/hwc3/GuestFrameComposer.h | 6 | ||||
-rw-r--r-- | system/hwc3/HostFrameComposer.h | 11 | ||||
-rw-r--r-- | system/hwc3/LruCache.h | 83 |
20 files changed, 517 insertions, 62 deletions
diff --git a/system/hwc2/Android.mk b/system/hwc2/Android.mk index b53456ce..f2c4f25b 100644 --- a/system/hwc2/Android.mk +++ b/system/hwc2/Android.mk @@ -58,6 +58,7 @@ emulator_hwcomposer_c_includes += \ emulator_hwcomposer_relative_path := hw emulator_hwcomposer2_src_files := \ + ClientComposer.cpp \ Common.cpp \ Device.cpp \ Display.cpp \ diff --git a/system/hwc2/ClientComposer.cpp b/system/hwc2/ClientComposer.cpp new file mode 100644 index 00000000..211667b0 --- /dev/null +++ b/system/hwc2/ClientComposer.cpp @@ -0,0 +1,144 @@ +/* + * Copyright 2022 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 "ClientComposer.h" + +#include "Device.h" +#include "Display.h" +#include "Drm.h" +#include "Layer.h" + +namespace android { + +ClientComposer::ClientComposer(DrmPresenter* drmPresenter) + : mDrmPresenter(drmPresenter) {} + +HWC2::Error ClientComposer::init() { + DEBUG_LOG("%s", __FUNCTION__); + + return HWC2::Error::None; +} + +HWC2::Error ClientComposer::onDisplayCreate(Display* display) { + const auto displayId = display->getId(); + DEBUG_LOG("%s display:%" PRIu64, __FUNCTION__, displayId); + + // Ensure created. + mDisplayInfos.emplace(displayId, DisplayInfo{}); + + return HWC2::Error::None; +} + +HWC2::Error ClientComposer::onDisplayDestroy(Display* display) { + const auto displayId = display->getId(); + DEBUG_LOG("%s display:%" PRIu64, __FUNCTION__, displayId); + + auto it = mDisplayInfos.find(displayId); + if (it == mDisplayInfos.end()) { + ALOGE("%s: display:%" PRIu64 " missing display buffers?", __FUNCTION__, + displayId); + return HWC2::Error::BadDisplay; + } + + mDisplayInfos.erase(it); + + return HWC2::Error::None; +} + +HWC2::Error ClientComposer::onDisplayClientTargetSet(Display* display) { + const auto displayId = display->getId(); + DEBUG_LOG("%s display:%" PRIu64, __FUNCTION__, displayId); + + auto it = mDisplayInfos.find(displayId); + if (it == mDisplayInfos.end()) { + ALOGE("%s: display:%" PRIu64 " missing display buffers?", __FUNCTION__, + displayId); + return HWC2::Error::BadDisplay; + } + + DisplayInfo& displayInfo = it->second; + + auto clientTargetNativeBuffer = display->getClientTarget().getBuffer(); + auto clientTargetDrmBuffer = + std::make_unique<DrmBuffer>(clientTargetNativeBuffer, mDrmPresenter); + if (!clientTargetDrmBuffer) { + ALOGE("%s: display:%" PRIu64 " failed to create client target drm buffer", + __FUNCTION__, displayId); + return HWC2::Error::NoResources; + } + + displayInfo.clientTargetDrmBuffer = std::move(clientTargetDrmBuffer); + + return HWC2::Error::None; +} + +HWC2::Error ClientComposer::onActiveConfigChange(Display*) { + DEBUG_LOG("%s", __FUNCTION__); + + return HWC2::Error::None; +}; + +HWC2::Error ClientComposer::validateDisplay( + Display* display, std::unordered_map<hwc2_layer_t, HWC2::Composition>* changes) { + const auto displayId = display->getId(); + DEBUG_LOG("%s display:%" PRIu64, __FUNCTION__, displayId); + (void)displayId; + + const std::vector<Layer*>& layers = display->getOrderedLayers(); + + for (Layer* layer : layers) { + const auto layerId = layer->getId(); + const auto layerCompositionType = layer->getCompositionType(); + + if (layerCompositionType != HWC2::Composition::Client) { + (*changes)[layerId] = HWC2::Composition::Client; + } + } + + return HWC2::Error::None; +} + +std::tuple<HWC2::Error, base::unique_fd> ClientComposer::presentDisplay( + Display* display) { + ATRACE_CALL(); + + const auto displayId = display->getId(); + DEBUG_LOG("%s display:%" PRIu64, __FUNCTION__, displayId); + + auto displayInfoIt = mDisplayInfos.find(displayId); + if (displayInfoIt == mDisplayInfos.end()) { + ALOGE("%s: failed to find display buffers for display:%" PRIu64, + __FUNCTION__, displayId); + return std::make_tuple(HWC2::Error::BadDisplay, base::unique_fd()); + } + + DisplayInfo& displayInfo = displayInfoIt->second; + + auto clientTargetFence = display->getClientTarget().getFence(); + + auto [error, presentFence] = + displayInfo.clientTargetDrmBuffer->flushToDisplay( + static_cast<int>(displayId), clientTargetFence); + if (error != HWC2::Error::None) { + ALOGE("%s: display:%" PRIu64 " failed to flush drm buffer" PRIu64, + __FUNCTION__, displayId); + return std::make_tuple(error, base::unique_fd()); + } + + return std::make_tuple(HWC2::Error::None, std::move(presentFence)); +} + +} // namespace android
\ No newline at end of file diff --git a/system/hwc2/ClientComposer.h b/system/hwc2/ClientComposer.h new file mode 100644 index 00000000..58d4cceb --- /dev/null +++ b/system/hwc2/ClientComposer.h @@ -0,0 +1,73 @@ +/* + * Copyright 2022 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. + */ + +#ifndef ANDROID_HWC_CLIENTCOMPOSER_H +#define ANDROID_HWC_CLIENTCOMPOSER_H + +#include <unordered_map> + +#include "Common.h" +#include "Composer.h" +#include "Display.h" +#include "DrmPresenter.h" +#include "Layer.h" + +namespace android { + +class ClientComposer : public Composer { + public: + ClientComposer(DrmPresenter* drmPresenter); + + ClientComposer(const ClientComposer&) = delete; + ClientComposer& operator=(const ClientComposer&) = delete; + + ClientComposer(ClientComposer&&) = delete; + ClientComposer& operator=(ClientComposer&&) = delete; + + HWC2::Error init() override; + + HWC2::Error onDisplayCreate(Display*) override; + + HWC2::Error onDisplayDestroy(Display*) override; + + HWC2::Error onDisplayClientTargetSet(Display*) override; + + HWC2::Error onActiveConfigChange(Display*) override; + + // Determines if this composer can compose the given layers on the given + // display and requests changes for layers that can't not be composed. + HWC2::Error validateDisplay( + Display* display, std::unordered_map<hwc2_layer_t, HWC2::Composition>* + outLayerCompositionChanges) override; + + // Performs the actual composition of layers and presents the composed result + // to the display. + std::tuple<HWC2::Error, base::unique_fd> presentDisplay( + Display* display) override; + + private: + struct DisplayInfo { + std::unique_ptr<DrmBuffer> clientTargetDrmBuffer; + }; + + std::unordered_map<int64_t, DisplayInfo> mDisplayInfos; + + DrmPresenter* mDrmPresenter = nullptr; +}; + +} // namespace android + +#endif
\ No newline at end of file diff --git a/system/hwc2/Common.cpp b/system/hwc2/Common.cpp index 3e465c22..021d0322 100644 --- a/system/hwc2/Common.cpp +++ b/system/hwc2/Common.cpp @@ -31,3 +31,7 @@ bool IsCuttlefishFoldable() { bool IsNoOpMode() { return android::base::GetProperty("ro.vendor.hwcomposer.mode", "") == "noop"; } + +bool IsClientCompositionMode() { + return android::base::GetProperty("ro.vendor.hwcomposer.mode", "") == "client"; +} diff --git a/system/hwc2/Common.h b/system/hwc2/Common.h index b0e07700..f13553b7 100644 --- a/system/hwc2/Common.h +++ b/system/hwc2/Common.h @@ -45,5 +45,6 @@ bool IsCuttlefish(); bool IsCuttlefishFoldable(); bool IsNoOpMode(); +bool IsClientCompositionMode(); #endif diff --git a/system/hwc2/Device.cpp b/system/hwc2/Device.cpp index 1be15b3d..f49905df 100644 --- a/system/hwc2/Device.cpp +++ b/system/hwc2/Device.cpp @@ -18,6 +18,7 @@ #include <android-base/properties.h> +#include "ClientComposer.h" #include "DisplayFinder.h" #include "GuestComposer.h" #include "HostComposer.h" @@ -78,6 +79,9 @@ HWC2::Error Device::init() { if (IsNoOpMode()) { DEBUG_LOG("%s: using NoOpComposer", __FUNCTION__); mComposer = std::make_unique<NoOpComposer>(); + } else if (IsClientCompositionMode()) { + DEBUG_LOG("%s: using ClientComposer", __FUNCTION__); + mComposer = std::make_unique<ClientComposer>(mDrmPresenter.get()); } else if (ShouldUseGuestComposer()) { DEBUG_LOG("%s: using GuestComposer", __FUNCTION__); mComposer = std::make_unique<GuestComposer>(mDrmPresenter.get()); diff --git a/system/hwc3/ClientFrameComposer.cpp b/system/hwc3/ClientFrameComposer.cpp index d7f8b559..284a46f9 100644 --- a/system/hwc3/ClientFrameComposer.cpp +++ b/system/hwc3/ClientFrameComposer.cpp @@ -146,6 +146,11 @@ HWC3::Error ClientFrameComposer::presentDisplay( } DisplayInfo& displayInfo = displayInfoIt->second; + if (!displayInfo.clientTargetDrmBuffer) { + ALOGW("%s: display:%" PRIu64 " no client target set, nothing to present.", + __FUNCTION__, displayId); + return HWC3::Error::None; + } ::android::base::unique_fd fence = display->getClientTarget().getFence(); diff --git a/system/hwc3/ClientFrameComposer.h b/system/hwc3/ClientFrameComposer.h index 3fb0ba85..28199b3d 100644 --- a/system/hwc3/ClientFrameComposer.h +++ b/system/hwc3/ClientFrameComposer.h @@ -64,9 +64,13 @@ class ClientFrameComposer : public FrameComposer { std::unordered_map<int64_t, ::android::base::unique_fd>* outLayerFences) override; + const DrmPresenter* getDrmPresenter() const override { + return &mDrmPresenter; + } + private: struct DisplayInfo { - std::unique_ptr<DrmBuffer> clientTargetDrmBuffer;; + std::shared_ptr<DrmBuffer> clientTargetDrmBuffer; }; std::unordered_map<int64_t, DisplayInfo> mDisplayInfos; diff --git a/system/hwc3/Common.cpp b/system/hwc3/Common.cpp index 497f764b..e9ac5073 100644 --- a/system/hwc3/Common.cpp +++ b/system/hwc3/Common.cpp @@ -30,18 +30,34 @@ bool IsCuttlefishFoldable() { std::string::npos; } -bool IsNoOpMode() { +bool IsInNoOpCompositionMode() { const std::string mode = ::android::base::GetProperty("ro.vendor.hwcomposer.mode", ""); DEBUG_LOG("%s: sysprop ro.vendor.hwcomposer.mode is %s", __FUNCTION__, mode.c_str()); return mode == "noop"; } -bool IsClientCompositionMode() { +bool IsInClientCompositionMode() { const std::string mode = ::android::base::GetProperty("ro.vendor.hwcomposer.mode", ""); DEBUG_LOG("%s: sysprop ro.vendor.hwcomposer.mode is %s", __FUNCTION__, mode.c_str()); return mode == "client"; } +bool IsInNoOpDisplayFinderMode() { + const std::string mode = + ::android::base::GetProperty("ro.vendor.hwcomposer.display_finder_mode", ""); + DEBUG_LOG("%s: sysprop ro.vendor.hwcomposer.display_finder_mode is %s", + __FUNCTION__, mode.c_str()); + return mode == "noop"; +} + +bool IsInDrmDisplayFinderMode() { + const std::string mode = + ::android::base::GetProperty("ro.vendor.hwcomposer.display_finder_mode", ""); + DEBUG_LOG("%s: sysprop ro.vendor.hwcomposer.display_finder_mode is %s", + __FUNCTION__, mode.c_str()); + return mode == "drm"; +} + std::string toString(HWC3::Error error) { switch (error) { case HWC3::Error::None: diff --git a/system/hwc3/Common.h b/system/hwc3/Common.h index 5b6587e6..493e5d08 100644 --- a/system/hwc3/Common.h +++ b/system/hwc3/Common.h @@ -44,8 +44,12 @@ namespace aidl::android::hardware::graphics::composer3::impl { bool IsCuttlefish(); bool IsCuttlefishFoldable(); -bool IsNoOpMode(); -bool IsClientCompositionMode(); + +bool IsInNoOpCompositionMode(); +bool IsInClientCompositionMode(); + +bool IsInNoOpDisplayFinderMode(); +bool IsInDrmDisplayFinderMode(); namespace HWC3 { enum class Error : int32_t { diff --git a/system/hwc3/ComposerClient.cpp b/system/hwc3/ComposerClient.cpp index db053837..20984350 100644 --- a/system/hwc3/ComposerClient.cpp +++ b/system/hwc3/ComposerClient.cpp @@ -1237,7 +1237,7 @@ HWC3::Error ComposerClient::createDisplaysLocked() { std::vector<DisplayMultiConfigs> displays; - HWC3::Error error = findDisplays(displays); + HWC3::Error error = findDisplays(mComposer->getDrmPresenter(), &displays); if (error != HWC3::Error::None) { ALOGE("%s failed to find display configs", __FUNCTION__); return error; diff --git a/system/hwc3/Device.cpp b/system/hwc3/Device.cpp index cf4be429..894d48b4 100644 --- a/system/hwc3/Device.cpp +++ b/system/hwc3/Device.cpp @@ -94,10 +94,10 @@ HWC3::Error Device::getComposer(FrameComposer** outComposer) { std::unique_lock<std::mutex> lock(mMutex); if (mComposer == nullptr) { - if (IsNoOpMode()) { + if (IsInNoOpCompositionMode()) { DEBUG_LOG("%s: using NoOpFrameComposer", __FUNCTION__); mComposer = std::make_unique<NoOpFrameComposer>(); - } else if (IsClientCompositionMode()) { + } else if (IsInClientCompositionMode()) { DEBUG_LOG("%s: using ClientFrameComposer", __FUNCTION__); mComposer = std::make_unique<ClientFrameComposer>(); } else if (shouldUseGuestComposer()) { diff --git a/system/hwc3/DisplayFinder.cpp b/system/hwc3/DisplayFinder.cpp index 8e252cb3..10bd5fdb 100644 --- a/system/hwc3/DisplayFinder.cpp +++ b/system/hwc3/DisplayFinder.cpp @@ -31,7 +31,7 @@ constexpr int32_t HertzToPeriodNanos(uint32_t hertz) { return 1000 * 1000 * 1000 / hertz; } -HWC3::Error findCuttlefishDisplays(std::vector<DisplayMultiConfigs>& displays) { +HWC3::Error findCuttlefishDisplays(std::vector<DisplayMultiConfigs>* outDisplays) { DEBUG_LOG("%s", __FUNCTION__); // TODO: replace with initializing directly from DRM info. @@ -55,7 +55,7 @@ HWC3::Error findCuttlefishDisplays(std::vector<DisplayMultiConfigs>& displays) { vsyncPeriodNanos), }, }; - displays.push_back(display); + outDisplays->push_back(display); ++displayId; } @@ -79,7 +79,7 @@ static int getVsyncHzFromProperty() { } HWC3::Error findGoldfishPrimaryDisplay( - std::vector<DisplayMultiConfigs>& displays) { + std::vector<DisplayMultiConfigs>* outDisplays) { DEBUG_LOG("%s", __FUNCTION__); DEFINE_AND_VALIDATE_HOST_CONNECTION @@ -118,13 +118,13 @@ HWC3::Error findGoldfishPrimaryDisplay( } hostCon->unlock(); - displays.push_back(display); + outDisplays->push_back(display); return HWC3::Error::None; } HWC3::Error findGoldfishSecondaryDisplays( - std::vector<DisplayMultiConfigs>& displays) { + std::vector<DisplayMultiConfigs>* outDisplays) { DEBUG_LOG("%s", __FUNCTION__); static constexpr const char kExternalDisplayProp[] = @@ -170,7 +170,7 @@ HWC3::Error findGoldfishSecondaryDisplays( /*dpiYh=*/propIntParts[3], // /*vsyncPeriod=*/HertzToPeriodNanos(160) // )); - displays.push_back(display); + outDisplays->push_back(display); ++secondaryDisplayId; @@ -180,14 +180,14 @@ HWC3::Error findGoldfishSecondaryDisplays( return HWC3::Error::None; } -HWC3::Error findGoldfishDisplays(std::vector<DisplayMultiConfigs>& displays) { - HWC3::Error error = findGoldfishPrimaryDisplay(displays); +HWC3::Error findGoldfishDisplays(std::vector<DisplayMultiConfigs>* outDisplays) { + HWC3::Error error = findGoldfishPrimaryDisplay(outDisplays); if (error != HWC3::Error::None) { ALOGE("%s failed to find Goldfish primary display", __FUNCTION__); return error; } - error = findGoldfishSecondaryDisplays(displays); + error = findGoldfishSecondaryDisplays(outDisplays); if (error != HWC3::Error::None) { ALOGE("%s failed to find Goldfish secondary displays", __FUNCTION__); } @@ -197,8 +197,8 @@ HWC3::Error findGoldfishDisplays(std::vector<DisplayMultiConfigs>& displays) { // This is currently only used for Gem5 bring-up where virtio-gpu and drm // are not currently available. For now, just return a placeholder display. -HWC3::Error findNoOpDisplays(std::vector<DisplayMultiConfigs>& displays) { - displays.push_back(DisplayMultiConfigs{ +HWC3::Error findNoOpDisplays(std::vector<DisplayMultiConfigs>* outDisplays) { + outDisplays->push_back(DisplayMultiConfigs{ .displayId = 0, .activeConfigId = 0, .configs = {DisplayConfig(0, @@ -213,16 +213,54 @@ HWC3::Error findNoOpDisplays(std::vector<DisplayMultiConfigs>& displays) { return HWC3::Error::None; } +HWC3::Error findDrmDisplays(const DrmPresenter& drm, + std::vector<DisplayMultiConfigs>* outDisplays) { + outDisplays->clear(); + + std::vector<DrmPresenter::DisplayConfig> drmDisplayConfigs; + + HWC3::Error error = drm.getDisplayConfigs(&drmDisplayConfigs); + if (error != HWC3::Error::None) { + ALOGE("%s failed to find displays from DRM.", __FUNCTION__); + return error; + } + + for (const DrmPresenter::DisplayConfig drmDisplayConfig : drmDisplayConfigs) { + outDisplays->push_back(DisplayMultiConfigs{ + .displayId = drmDisplayConfig.id, + .activeConfigId = static_cast<int32_t>(drmDisplayConfig.id), + .configs = { + DisplayConfig(static_cast<int32_t>(drmDisplayConfig.id), + drmDisplayConfig.width, + drmDisplayConfig.height, + drmDisplayConfig.dpiX, + drmDisplayConfig.dpiY, + HertzToPeriodNanos(drmDisplayConfig.refreshRateHz)), + }, + }); + } + + return HWC3::Error::None; +} + } // namespace -HWC3::Error findDisplays(std::vector<DisplayMultiConfigs>& displays) { +HWC3::Error findDisplays(const DrmPresenter* drm, + std::vector<DisplayMultiConfigs>* outDisplays) { HWC3::Error error = HWC3::Error::None; - if (IsNoOpMode()) { - error = findNoOpDisplays(displays); + if (IsInNoOpCompositionMode()) { + error = findNoOpDisplays(outDisplays); + } else if (IsInDrmDisplayFinderMode()) { + if (drm == nullptr) { + ALOGE("%s asked to find displays from DRM, but DRM not available.", + __FUNCTION__); + return HWC3::Error::NoResources; + } + error = findDrmDisplays(*drm, outDisplays); } else if (IsCuttlefish()) { - error = findCuttlefishDisplays(displays); + error = findCuttlefishDisplays(outDisplays); } else { - error = findGoldfishDisplays(displays); + error = findGoldfishDisplays(outDisplays); } if (error != HWC3::Error::None) { @@ -230,7 +268,7 @@ HWC3::Error findDisplays(std::vector<DisplayMultiConfigs>& displays) { return error; } - for (auto& display : displays) { + for (auto& display : *outDisplays) { DisplayConfig::addConfigGroups(&display.configs); } diff --git a/system/hwc3/DisplayFinder.h b/system/hwc3/DisplayFinder.h index 8197a82e..171d2048 100644 --- a/system/hwc3/DisplayFinder.h +++ b/system/hwc3/DisplayFinder.h @@ -17,10 +17,12 @@ #ifndef ANDROID_HWC_DISPLAYFINDER_H #define ANDROID_HWC_DISPLAYFINDER_H +#include <optional> #include <vector> #include "Common.h" #include "DisplayConfig.h" +#include "DrmPresenter.h" namespace aidl::android::hardware::graphics::composer3::impl { @@ -31,7 +33,8 @@ struct DisplayMultiConfigs { std::vector<DisplayConfig> configs; }; -HWC3::Error findDisplays(std::vector<DisplayMultiConfigs>& displays); +HWC3::Error findDisplays(const DrmPresenter* drm, + std::vector<DisplayMultiConfigs>* outDisplays); } // namespace aidl::android::hardware::graphics::composer3::impl diff --git a/system/hwc3/DrmPresenter.cpp b/system/hwc3/DrmPresenter.cpp index 6e13209c..b5122778 100644 --- a/system/hwc3/DrmPresenter.cpp +++ b/system/hwc3/DrmPresenter.cpp @@ -80,6 +80,18 @@ HWC3::Error DrmPresenter::init() { ALOGE("%s: Failed to initialize DRM backend", __FUNCTION__); return HWC3::Error::NoResources; } + + constexpr const std::size_t kCachedBuffersPerDisplay = 3; + std::size_t numDisplays = 0; + for (const DrmConnector& connector : mConnectors) { + if (connector.connection == DRM_MODE_CONNECTED) { + ++numDisplays; + } + } + const std::size_t bufferCacheSize = kCachedBuffersPerDisplay * numDisplays; + DEBUG_LOG("%s: initializing DRM buffer cache to size %zu", + __FUNCTION__, bufferCacheSize); + mBufferCache = std::make_unique<DrmBufferCache>(bufferCacheSize); } mDrmEventListener = ::android::sp<DrmEventListener>::make(*this); @@ -93,6 +105,31 @@ HWC3::Error DrmPresenter::init() { return HWC3::Error::None; } +HWC3::Error DrmPresenter::getDisplayConfigs(std::vector<DisplayConfig>* configs) const { + AutoReadLock lock(mStateMutex); + + configs->clear(); + + for (uint32_t i = 0; i < mConnectors.size(); i++) { + const auto& connector = mConnectors[i]; + + if (connector.connection != DRM_MODE_CONNECTED) { + continue; + } + + configs->emplace_back(DisplayConfig{ + .id = i, + .width = connector.mMode.hdisplay, + .height = connector.mMode.vdisplay, + .dpiX = 160, //static_cast<uint32_t>(connector.dpiX), + .dpiY = 160, //static_cast<uint32_t>(connector.dpiY), + .refreshRateHz = connector.mRefreshRateAsInteger, + }); + } + + return HWC3::Error::None; +} + HWC3::Error DrmPresenter::registerOnHotplugCallback(const HotplugCallback& cb) { mHotplugCallback = cb; return HWC3::Error::None; @@ -322,54 +359,59 @@ void DrmPresenter::resetDrmElementsLocked() { mPlanes.clear(); } -std::tuple<HWC3::Error, std::unique_ptr<DrmBuffer>> DrmPresenter::create( +std::tuple<HWC3::Error, std::shared_ptr<DrmBuffer>> DrmPresenter::create( const native_handle_t* handle) { - auto buffer = std::unique_ptr<DrmBuffer>(new DrmBuffer(*this)); - cros_gralloc_handle* crosHandle = (cros_gralloc_handle*)handle; if (crosHandle == nullptr) { ALOGE("%s: invalid cros_gralloc_handle", __FUNCTION__); - return std::make_tuple(HWC3::Error::NoResources, - std::unique_ptr<DrmBuffer>()); + return std::make_tuple(HWC3::Error::NoResources, nullptr); + } + + DrmPrimeBufferHandle primeHandle = 0; + int ret = drmPrimeFDToHandle(mFd.get(), crosHandle->fds[0], &primeHandle); + if (ret) { + ALOGE("%s: drmPrimeFDToHandle failed: %s (errno %d)", __FUNCTION__, + strerror(errno), errno); + return std::make_tuple(HWC3::Error::NoResources, nullptr); } + auto drmBufferPtr = mBufferCache->get(primeHandle); + if (drmBufferPtr != nullptr) { + return std::make_tuple(HWC3::Error::None, + std::shared_ptr<DrmBuffer>(*drmBufferPtr)); + } + + auto buffer = std::shared_ptr<DrmBuffer>(new DrmBuffer(*this)); buffer->mWidth = crosHandle->width; buffer->mHeight = crosHandle->height; buffer->mDrmFormat = crosHandle->format; buffer->mPlaneFds[0] = crosHandle->fds[0]; + buffer->mPlaneHandles[0] = primeHandle; buffer->mPlanePitches[0] = crosHandle->strides[0]; buffer->mPlaneOffsets[0] = crosHandle->offsets[0]; - HWC3::Error error = createDrmFramebuffer(buffer.get()); - return std::make_tuple(error, std::move(buffer)); -} - -HWC3::Error DrmPresenter::createDrmFramebuffer(DrmBuffer* buffer) { - int ret; - - ret = drmPrimeFDToHandle(mFd.get(), buffer->mPlaneFds[0], - &buffer->mPlaneHandles[0]); - if (ret) { - ALOGE("%s: drmPrimeFDToHandle failed: %s (errno %d)", __FUNCTION__, - strerror(errno), errno); - return HWC3::Error::NoResources; - } - uint32_t framebuffer = 0; - ret = drmModeAddFB2(mFd.get(), buffer->mWidth, buffer->mHeight, - buffer->mDrmFormat, buffer->mPlaneHandles, - buffer->mPlanePitches, buffer->mPlaneOffsets, - &framebuffer, 0); + ret = drmModeAddFB2(mFd.get(), + buffer->mWidth, + buffer->mHeight, + buffer->mDrmFormat, + buffer->mPlaneHandles, + buffer->mPlanePitches, + buffer->mPlaneOffsets, + &framebuffer, + 0); if (ret) { ALOGE("%s: drmModeAddFB2 failed: %s (errno %d)", __FUNCTION__, strerror(errno), errno); - return HWC3::Error::NoResources; + return std::make_tuple(HWC3::Error::NoResources, nullptr); } - DEBUG_LOG("%s: created framebuffer:%" PRIu32, __FUNCTION__, framebuffer); + buffer->mDrmFramebuffer = framebuffer; - buffer->mDrmFramebuffer.emplace(framebuffer); - return HWC3::Error::None; + mBufferCache->set(primeHandle, std::shared_ptr<DrmBuffer>(buffer)); + + return std::make_tuple(HWC3::Error::None, + std::shared_ptr<DrmBuffer>(buffer)); } HWC3::Error DrmPresenter::destroyDrmFramebuffer(DrmBuffer* buffer) { @@ -391,6 +433,8 @@ HWC3::Error DrmPresenter::destroyDrmFramebuffer(DrmBuffer* buffer) { strerror(errno), errno); return HWC3::Error::NoResources; } + + mBufferCache->remove(buffer->mPlaneHandles[0]); } return HWC3::Error::None; diff --git a/system/hwc3/DrmPresenter.h b/system/hwc3/DrmPresenter.h index 61e546ae..72e3f5a5 100644 --- a/system/hwc3/DrmPresenter.h +++ b/system/hwc3/DrmPresenter.h @@ -29,6 +29,7 @@ #include <vector> #include "Common.h" +#include "LruCache.h" #include "android/base/synchronization/AndroidLock.h" namespace aidl::android::hardware::graphics::composer3::impl { @@ -60,7 +61,6 @@ class DrmBuffer { uint32_t mPlaneHandles[4] = {0, 0, 0, 0}; uint32_t mPlanePitches[4] = {0, 0, 0, 0}; uint32_t mPlaneOffsets[4] = {0, 0, 0, 0}; - std::optional<uint32_t> mDrmFramebuffer; }; @@ -77,6 +77,17 @@ class DrmPresenter { HWC3::Error init(); + struct DisplayConfig { + uint32_t id; + uint32_t width; + uint32_t height; + uint32_t dpiX; + uint32_t dpiY; + uint32_t refreshRateHz; + }; + + HWC3::Error getDisplayConfigs(std::vector<DisplayConfig>* configs) const; + using HotplugCallback = std::function<void(bool /*connected*/, // uint32_t /*id*/, // uint32_t /*width*/, // @@ -90,7 +101,7 @@ class DrmPresenter { uint32_t refreshRate() const { return mConnectors[0].mRefreshRateAsInteger; } - std::tuple<HWC3::Error, std::unique_ptr<DrmBuffer>> create( + std::tuple<HWC3::Error, std::shared_ptr<DrmBuffer>> create( const native_handle_t* handle); std::tuple<HWC3::Error, ::android::base::unique_fd> flushToDisplay( @@ -100,9 +111,13 @@ class DrmPresenter { std::optional<std::vector<uint8_t>> getEdid(uint32_t id); private: - // Grant visibility for createDrmFramebuffer and clearDrmFB to DrmBuffer. + // TODO: make this cache per display when enabling hotplug support. + using DrmPrimeBufferHandle = uint32_t; + using DrmBufferCache = LruCache<DrmPrimeBufferHandle, std::shared_ptr<DrmBuffer>>; + std::unique_ptr<DrmBufferCache> mBufferCache; + + // Grant visibility to destroyDrmFramebuffer to DrmBuffer. friend class DrmBuffer; - HWC3::Error createDrmFramebuffer(DrmBuffer* buffer); HWC3::Error destroyDrmFramebuffer(DrmBuffer* buffer); // Grant visibility for handleHotplug to DrmEventListener. @@ -117,7 +132,7 @@ class DrmPresenter { std::optional<HotplugCallback> mHotplugCallback; // Protects access to the below drm structs. - ::android::base::guest::ReadWriteLock mStateMutex; + mutable ::android::base::guest::ReadWriteLock mStateMutex; struct DrmPlane { uint32_t mId = -1; diff --git a/system/hwc3/FrameComposer.h b/system/hwc3/FrameComposer.h index fdb6db3f..794855b8 100644 --- a/system/hwc3/FrameComposer.h +++ b/system/hwc3/FrameComposer.h @@ -26,6 +26,7 @@ #include "Common.h" #include "DisplayChanges.h" +#include "DrmPresenter.h" namespace aidl::android::hardware::graphics::composer3::impl { @@ -68,6 +69,10 @@ class FrameComposer { outLayerFences) = 0; virtual HWC3::Error onActiveConfigChange(Display* display) = 0; + + virtual const DrmPresenter* getDrmPresenter() const { + return nullptr; + } }; } // namespace aidl::android::hardware::graphics::composer3::impl diff --git a/system/hwc3/GuestFrameComposer.h b/system/hwc3/GuestFrameComposer.h index af46b3d9..e37ff875 100644 --- a/system/hwc3/GuestFrameComposer.h +++ b/system/hwc3/GuestFrameComposer.h @@ -62,6 +62,10 @@ class GuestFrameComposer : public FrameComposer { HWC3::Error onActiveConfigChange(Display* /*display*/) override; + const DrmPresenter* getDrmPresenter() const override { + return &mDrmPresenter; + } + private: struct DisplayConfig { int width; @@ -91,7 +95,7 @@ class GuestFrameComposer : public FrameComposer { // Additional per display buffer for the composition result. buffer_handle_t compositionResultBuffer = nullptr; - std::unique_ptr<DrmBuffer> compositionResultDrmBuffer; + std::shared_ptr<DrmBuffer> compositionResultDrmBuffer; }; std::unordered_map<int64_t, DisplayInfo> mDisplayInfos; diff --git a/system/hwc3/HostFrameComposer.h b/system/hwc3/HostFrameComposer.h index e99e6f2c..42eb43a6 100644 --- a/system/hwc3/HostFrameComposer.h +++ b/system/hwc3/HostFrameComposer.h @@ -65,6 +65,13 @@ class HostFrameComposer : public FrameComposer { HWC3::Error onActiveConfigChange(Display* display) override; + const DrmPresenter* getDrmPresenter() const override { + if (mDrmPresenter) { + return &*mDrmPresenter; + } + return nullptr; + } + private: HWC3::Error createHostComposerDisplayInfo(Display* display, uint32_t hostDisplayId); @@ -85,10 +92,10 @@ class HostFrameComposer : public FrameComposer { const native_handle_t* compositionResultBuffer = nullptr; // Drm info for the additional composition result buffer. - std::unique_ptr<DrmBuffer> compositionResultDrmBuffer; + std::shared_ptr<DrmBuffer> compositionResultDrmBuffer; // Drm info for the displays client target buffer. - std::unique_ptr<DrmBuffer> clientTargetDrmBuffer; + std::shared_ptr<DrmBuffer> clientTargetDrmBuffer; }; std::unordered_map<int64_t, HostComposerDisplayInfo> mDisplayInfos; diff --git a/system/hwc3/LruCache.h b/system/hwc3/LruCache.h new file mode 100644 index 00000000..9ffca46a --- /dev/null +++ b/system/hwc3/LruCache.h @@ -0,0 +1,83 @@ +// Copyright 2022 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. + +#pragma once + +#include <list> +#include <unordered_map> + +template <typename Key, typename Value> +class LruCache { + public: + LruCache(std::size_t maxSize) : m_maxSize(maxSize) { + m_table.reserve(maxSize); + } + + Value* get(const Key& key) { + auto tableIt = m_table.find(key); + if (tableIt == m_table.end()) { + return nullptr; + } + + // Move to front. + auto elementsIt = tableIt->second; + m_elements.splice(elementsIt, m_elements, m_elements.begin()); + return &elementsIt->value; + } + + void set(const Key& key, Value&& value) { + auto tableIt = m_table.find(key); + if (tableIt == m_table.end()) { + if (m_table.size() >= m_maxSize) { + auto& kv = m_elements.back(); + m_table.erase(kv.key); + m_elements.pop_back(); + } + } else { + auto elementsIt = tableIt->second; + m_elements.erase(elementsIt); + } + m_elements.emplace_front(KeyValue{ + key, + std::forward<Value>(value), + }); + m_table[key] = m_elements.begin(); + } + + void remove(const Key& key) { + auto tableIt = m_table.find(key); + if (tableIt == m_table.end()) { + return; + } + auto elementsIt = tableIt->second; + m_elements.erase(elementsIt); + m_table.erase(tableIt); + } + + void clear() { + m_elements.clear(); + m_table.clear(); + } + + private: + struct KeyValue { + Key key; + Value value; + }; + + const std::size_t m_maxSize; + // Front is the most recently used and back is the least recently used. + std::list<KeyValue> m_elements; + std::unordered_map<Key, typename std::list<KeyValue>::iterator> m_table; +}; |