aboutsummaryrefslogtreecommitdiff
path: root/system/hwc3
diff options
context:
space:
mode:
Diffstat (limited to 'system/hwc3')
-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
14 files changed, 290 insertions, 62 deletions
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;
+};