aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-09-12 23:06:07 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-09-12 23:06:07 +0000
commit4b7b3264fec3e413eedc210c0199366f01298baf (patch)
tree1946a087eae8f2453fe403704b4e390499c22d4b
parent92ee642e5fc0f9cac1512dd247da950775501a8d (diff)
parent35506601ebf83a6bcd83a57510872e90f09c73f9 (diff)
downloadgoldfish-opengl-android13-qpr1-s1-release.tar.gz
Change-Id: If3ec775d1117c7bda789f7700b62a045fb52ece5
-rw-r--r--system/hwc2/Android.mk1
-rw-r--r--system/hwc2/ClientComposer.cpp144
-rw-r--r--system/hwc2/ClientComposer.h73
-rw-r--r--system/hwc2/Common.cpp4
-rw-r--r--system/hwc2/Common.h1
-rw-r--r--system/hwc2/Device.cpp4
-rw-r--r--system/hwc3/ClientFrameComposer.cpp5
-rw-r--r--system/hwc3/ClientFrameComposer.h6
-rw-r--r--system/hwc3/Common.cpp20
-rw-r--r--system/hwc3/Common.h8
-rw-r--r--system/hwc3/ComposerClient.cpp2
-rw-r--r--system/hwc3/Device.cpp4
-rw-r--r--system/hwc3/DisplayFinder.cpp72
-rw-r--r--system/hwc3/DisplayFinder.h5
-rw-r--r--system/hwc3/DrmPresenter.cpp100
-rw-r--r--system/hwc3/DrmPresenter.h25
-rw-r--r--system/hwc3/FrameComposer.h5
-rw-r--r--system/hwc3/GuestFrameComposer.h6
-rw-r--r--system/hwc3/HostFrameComposer.h11
-rw-r--r--system/hwc3/LruCache.h83
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;
+};