aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Macnak <natsu@google.com>2022-09-07 14:25:46 -0700
committerAlistair Delva <adelva@google.com>2022-09-07 22:08:48 +0000
commit482e759862dc1aa0dd8167bd681e9476d9432e75 (patch)
tree1a57d4d0e58591a923a5f19118d3f7f8b87953d3
parentea0971361df87dac267181a7b413075cbdfd7644 (diff)
downloadgoldfish-opengl-android11-gsi.tar.gz
Fix flickering with client frame composerandroid11-gsi
... by caching the DRM buffers. This is kind of a cherry-pick of aosp/2208477 for use in older branches. Bug: b/239855014 Test: cherry-pick aosp/2210356 to re-enable hwcomposer2.4 on CF cvd start --gpu_mode=gfxstream cvd start --gpu_mode=guest_swiftshader Change-Id: I3b134fcc7787f48f6d71ed2091ab695b93245d0b
-rw-r--r--system/hwc2/ClientComposer.cpp14
-rw-r--r--system/hwc2/ClientComposer.h3
-rw-r--r--system/hwc2/DrmPresenter.cpp190
-rw-r--r--system/hwc2/DrmPresenter.h35
-rw-r--r--system/hwc2/GuestComposer.cpp18
-rw-r--r--system/hwc2/GuestComposer.h2
-rw-r--r--system/hwc2/HostComposer.cpp34
-rw-r--r--system/hwc2/HostComposer.h5
-rw-r--r--system/hwc2/LruCache.h83
9 files changed, 264 insertions, 120 deletions
diff --git a/system/hwc2/ClientComposer.cpp b/system/hwc2/ClientComposer.cpp
index 9110956f..ee494cdc 100644
--- a/system/hwc2/ClientComposer.cpp
+++ b/system/hwc2/ClientComposer.cpp
@@ -71,16 +71,15 @@ HWC2::Error ClientComposer::onDisplayClientTargetSet(Display* display) {
DisplayInfo& displayInfo = it->second;
- auto clientTargetNativeBuffer = display->getClientTarget().getBuffer();
- auto clientTargetDrmBuffer =
- std::make_unique<DrmBuffer>(clientTargetNativeBuffer, mDrmPresenter);
- if (!clientTargetDrmBuffer) {
+ auto [drmBufferCreateError, drmBuffer] =
+ mDrmPresenter->create(display->getClientTarget().getBuffer());
+ if (drmBufferCreateError != HWC2::Error::None) {
ALOGE("%s: display:%" PRIu64 " failed to create client target drm buffer",
__FUNCTION__, displayId);
return HWC2::Error::NoResources;
}
+ displayInfo.clientTargetDrmBuffer = std::move(drmBuffer);
- displayInfo.clientTargetDrmBuffer = std::move(clientTargetDrmBuffer);
return HWC2::Error::None;
}
@@ -134,9 +133,8 @@ std::tuple<HWC2::Error, base::unique_fd> ClientComposer::presentDisplay(
auto clientTargetFence = display->getClientTarget().getFence();
- auto [error, presentFence] =
- displayInfo.clientTargetDrmBuffer->flushToDisplay(
- static_cast<int>(displayId), clientTargetFence);
+ auto [error, presentFence] = mDrmPresenter->flushToDisplay(
+ displayId, *displayInfo.clientTargetDrmBuffer, clientTargetFence);
if (error != HWC2::Error::None) {
ALOGE("%s: display:%" PRIu64 " failed to flush drm buffer" PRIu64,
__FUNCTION__, displayId);
diff --git a/system/hwc2/ClientComposer.h b/system/hwc2/ClientComposer.h
index 58d4cceb..216a67e7 100644
--- a/system/hwc2/ClientComposer.h
+++ b/system/hwc2/ClientComposer.h
@@ -17,6 +17,7 @@
#ifndef ANDROID_HWC_CLIENTCOMPOSER_H
#define ANDROID_HWC_CLIENTCOMPOSER_H
+#include <memory>
#include <unordered_map>
#include "Common.h"
@@ -60,7 +61,7 @@ class ClientComposer : public Composer {
private:
struct DisplayInfo {
- std::unique_ptr<DrmBuffer> clientTargetDrmBuffer;
+ std::shared_ptr<DrmBuffer> clientTargetDrmBuffer;
};
std::unordered_map<int64_t, DisplayInfo> mDisplayInfos;
diff --git a/system/hwc2/DrmPresenter.cpp b/system/hwc2/DrmPresenter.cpp
index c84aceb7..d437ad62 100644
--- a/system/hwc2/DrmPresenter.cpp
+++ b/system/hwc2/DrmPresenter.cpp
@@ -26,6 +26,11 @@ using android::base::guest::ReadWriteLock;
namespace android {
+DrmBuffer::DrmBuffer(DrmPresenter& DrmPresenter)
+ : mDrmPresenter(DrmPresenter) {}
+
+DrmBuffer::~DrmBuffer() { mDrmPresenter.destroyDrmFramebuffer(this); }
+
bool DrmPresenter::init(const HotplugCallback& cb) {
DEBUG_LOG("%s", __FUNCTION__);
@@ -59,6 +64,18 @@ bool DrmPresenter::init(const HotplugCallback& cb) {
ALOGE("%s: Failed to initialize DRM backend", __FUNCTION__);
return false;
}
+
+ 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.reset(new DrmEventListener(*this));
@@ -316,45 +333,6 @@ HWC2::Error DrmPresenter::getDisplayConfigs(std::vector<DisplayConfig>* configs)
return HWC2::Error::None;
}
-int DrmPresenter::getDrmFB(hwc_drm_bo_t& bo) {
- int ret = drmPrimeFDToHandle(mFd.get(), bo.prime_fds[0], &bo.gem_handles[0]);
- if (ret) {
- ALOGE("%s: drmPrimeFDToHandle failed: %s (errno %d)", __FUNCTION__,
- strerror(errno), errno);
- return -1;
- }
- ret = drmModeAddFB2(mFd.get(), bo.width, bo.height, bo.format, bo.gem_handles,
- bo.pitches, bo.offsets, &bo.fb_id, 0);
- if (ret) {
- ALOGE("%s: drmModeAddFB2 failed: %s (errno %d)", __FUNCTION__,
- strerror(errno), errno);
- return -1;
- }
- return 0;
-}
-
-int DrmPresenter::clearDrmFB(hwc_drm_bo_t& bo) {
- int ret = 0;
- if (bo.fb_id) {
- if (drmModeRmFB(mFd.get(), bo.fb_id)) {
- ALOGE("%s: drmModeRmFB failed: %s (errno %d)", __FUNCTION__,
- strerror(errno), errno);
- }
- ret = -1;
- }
- if (bo.gem_handles[0]) {
- struct drm_gem_close gem_close = {};
- gem_close.handle = bo.gem_handles[0];
- if (drmIoctl(mFd.get(), DRM_IOCTL_GEM_CLOSE, &gem_close)) {
- ALOGE("%s: DRM_IOCTL_GEM_CLOSE failed: %s (errno %d)", __FUNCTION__,
- strerror(errno), errno);
- }
- ret = -1;
- }
- ALOGV("%s: drm FB %d", __FUNCTION__, bo.fb_id);
- return ret;
-}
-
bool DrmPresenter::handleHotplug() {
std::vector<DrmConnector> oldConnectors(mConnectors);
{
@@ -403,10 +381,97 @@ bool DrmPresenter::handleHotplug() {
return true;
}
+std::tuple<HWC2::Error, std::shared_ptr<DrmBuffer>> DrmPresenter::create(
+ const native_handle_t* handle) {
+ cros_gralloc_handle* crosHandle = (cros_gralloc_handle*)handle;
+ if (crosHandle == nullptr) {
+ ALOGE("%s: invalid cros_gralloc_handle", __FUNCTION__);
+ return std::make_tuple(HWC2::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(HWC2::Error::NoResources, nullptr);
+ }
+
+ auto drmBufferPtr = mBufferCache->get(primeHandle);
+ if (drmBufferPtr != nullptr) {
+ return std::make_tuple(HWC2::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];
+
+ uint32_t 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 std::make_tuple(HWC2::Error::NoResources, nullptr);
+ }
+ DEBUG_LOG("%s: created framebuffer:%" PRIu32, __FUNCTION__, framebuffer);
+ buffer->mDrmFramebuffer = framebuffer;
+
+ mBufferCache->set(primeHandle, std::shared_ptr<DrmBuffer>(buffer));
+
+ return std::make_tuple(HWC2::Error::None,
+ std::shared_ptr<DrmBuffer>(buffer));
+}
+
+HWC2::Error DrmPresenter::destroyDrmFramebuffer(DrmBuffer* buffer) {
+ if (buffer->mDrmFramebuffer) {
+ uint32_t framebuffer = *buffer->mDrmFramebuffer;
+ if (drmModeRmFB(mFd.get(), framebuffer)) {
+ ALOGE("%s: drmModeRmFB failed: %s (errno %d)", __FUNCTION__,
+ strerror(errno), errno);
+ return HWC2::Error::NoResources;
+ }
+ DEBUG_LOG("%s: destroyed framebuffer:%" PRIu32, __FUNCTION__, framebuffer);
+ buffer->mDrmFramebuffer.reset();
+ }
+ if (buffer->mPlaneHandles[0]) {
+ struct drm_gem_close gem_close = {};
+ gem_close.handle = buffer->mPlaneHandles[0];
+ if (drmIoctl(mFd.get(), DRM_IOCTL_GEM_CLOSE, &gem_close)) {
+ ALOGE("%s: DRM_IOCTL_GEM_CLOSE failed: %s (errno %d)", __FUNCTION__,
+ strerror(errno), errno);
+ return HWC2::Error::NoResources;
+ }
+
+ mBufferCache->remove(buffer->mPlaneHandles[0]);
+ }
+
+ return HWC2::Error::None;
+}
+
std::tuple<HWC2::Error, base::unique_fd> DrmPresenter::flushToDisplay(
- int display, hwc_drm_bo_t& bo, base::borrowed_fd inSyncFd) {
+ int display, const DrmBuffer& buffer, base::borrowed_fd inSyncFd) {
ATRACE_CALL();
+ if (!buffer.mDrmFramebuffer) {
+ ALOGE("%s: failed, no framebuffer created.", __FUNCTION__);
+ return std::make_tuple(HWC2::Error::NoResources,
+ ::android::base::unique_fd());
+ }
+
AutoReadLock lock(mStateMutex);
DrmConnector& connector = mConnectors[display];
@@ -460,7 +525,8 @@ std::tuple<HWC2::Error, base::unique_fd> DrmPresenter::flushToDisplay(
DrmPlane& plane = mPlanes[crtc.mPlaneId];
DEBUG_LOG("%s: set plane: plane id %d crtc id %d fbid %d bo w h %d %d\n",
- __FUNCTION__, plane.mId, crtc.mId, bo.fb_id, bo.width, bo.height);
+ __FUNCTION__, plane.mId, crtc.mId, *buffer.mDrmFramebuffer,
+ buffer.mWidth, buffer.mHeight);
ret = drmModeAtomicAddProperty(pset, plane.mId, plane.mCrtcPropertyId,
crtc.mId);
@@ -473,8 +539,8 @@ std::tuple<HWC2::Error, base::unique_fd> DrmPresenter::flushToDisplay(
ALOGE("%s:%d: set IN_FENCE_FD failed %d errno %d\n", __FUNCTION__, __LINE__,
ret, errno);
}
- ret =
- drmModeAtomicAddProperty(pset, plane.mId, plane.mFbPropertyId, bo.fb_id);
+ ret = drmModeAtomicAddProperty(pset, plane.mId, plane.mFbPropertyId,
+ *buffer.mDrmFramebuffer);
if (ret < 0) {
ALOGE("%s:%d: failed %d errno %d\n", __FUNCTION__, __LINE__, ret, errno);
}
@@ -487,12 +553,12 @@ std::tuple<HWC2::Error, base::unique_fd> DrmPresenter::flushToDisplay(
ALOGE("%s:%d: failed %d errno %d\n", __FUNCTION__, __LINE__, ret, errno);
}
ret = drmModeAtomicAddProperty(pset, plane.mId, plane.mCrtcWPropertyId,
- bo.width);
+ buffer.mWidth);
if (ret < 0) {
ALOGE("%s:%d: failed %d errno %d\n", __FUNCTION__, __LINE__, ret, errno);
}
ret = drmModeAtomicAddProperty(pset, plane.mId, plane.mCrtcHPropertyId,
- bo.height);
+ buffer.mHeight);
if (ret < 0) {
ALOGE("%s:%d: failed %d errno %d\n", __FUNCTION__, __LINE__, ret, errno);
}
@@ -505,12 +571,12 @@ std::tuple<HWC2::Error, base::unique_fd> DrmPresenter::flushToDisplay(
ALOGE("%s:%d: failed %d errno %d\n", __FUNCTION__, __LINE__, ret, errno);
}
ret = drmModeAtomicAddProperty(pset, plane.mId, plane.mSrcWPropertyId,
- bo.width << 16);
+ buffer.mWidth << 16);
if (ret < 0) {
ALOGE("%s:%d: failed %d errno %d\n", __FUNCTION__, __LINE__, ret, errno);
}
ret = drmModeAtomicAddProperty(pset, plane.mId, plane.mSrcHPropertyId,
- bo.height << 16);
+ buffer.mHeight << 16);
if (ret < 0) {
ALOGE("%s:%d: failed %d errno %d\n", __FUNCTION__, __LINE__, ret, errno);
}
@@ -555,36 +621,6 @@ std::optional<std::vector<uint8_t>> DrmPresenter::getEdid(uint32_t id) {
return edid;
}
-DrmBuffer::DrmBuffer(const native_handle_t* handle, DrmPresenter* drmPresenter)
- : mDrmPresenter(drmPresenter), mBo({}) {
- if (!convertBoInfo(handle)) {
- mDrmPresenter->getDrmFB(mBo);
- }
-}
-
-DrmBuffer::~DrmBuffer() { mDrmPresenter->clearDrmFB(mBo); }
-
-int DrmBuffer::convertBoInfo(const native_handle_t* handle) {
- cros_gralloc_handle* gr_handle = (cros_gralloc_handle*)handle;
- if (!gr_handle) {
- ALOGE("%s: Null buffer handle", __FUNCTION__);
- return -1;
- }
- mBo.width = gr_handle->width;
- mBo.height = gr_handle->height;
- mBo.hal_format = gr_handle->droid_format;
- mBo.format = gr_handle->format;
- mBo.usage = gr_handle->usage;
- mBo.prime_fds[0] = gr_handle->fds[0];
- mBo.pitches[0] = gr_handle->strides[0];
- return 0;
-}
-
-std::tuple<HWC2::Error, base::unique_fd> DrmBuffer::flushToDisplay(
- int display, base::borrowed_fd inWaitSyncFd) {
- return mDrmPresenter->flushToDisplay(display, mBo, inWaitSyncFd);
-}
-
DrmPresenter::DrmEventListener::DrmEventListener(DrmPresenter& presenter)
: mPresenter(presenter) {}
diff --git a/system/hwc2/DrmPresenter.h b/system/hwc2/DrmPresenter.h
index be52ef64..86630fd9 100644
--- a/system/hwc2/DrmPresenter.h
+++ b/system/hwc2/DrmPresenter.h
@@ -28,8 +28,8 @@
#include <vector>
#include "Common.h"
+#include "LruCache.h"
#include "android/base/synchronization/AndroidLock.h"
-#include "drmhwcgralloc.h"
namespace android {
@@ -39,7 +39,6 @@ class DrmPresenter;
// A RAII object that will clear a drm framebuffer upon destruction.
class DrmBuffer {
public:
- DrmBuffer(const native_handle_t* handle, DrmPresenter* drmPresenter);
~DrmBuffer();
DrmBuffer(const DrmBuffer&) = delete;
@@ -48,14 +47,21 @@ class DrmBuffer {
DrmBuffer(DrmBuffer&&) = delete;
DrmBuffer& operator=(DrmBuffer&&) = delete;
- std::tuple<HWC2::Error, base::unique_fd> flushToDisplay(
- int display, base::borrowed_fd inWaitSyncFd);
-
private:
- int convertBoInfo(const native_handle_t* handle);
+ friend class DrmPresenter;
+ DrmBuffer(DrmPresenter& drmPresenter);
+
+ DrmPresenter& mDrmPresenter;
- DrmPresenter* mDrmPresenter;
- hwc_drm_bo_t mBo;
+ uint32_t mWidth = 0;
+ uint32_t mHeight = 0;
+ uint32_t mDrmFormat = 0;
+ uint32_t mPlaneFds[4] = {0, 0, 0, 0};
+ 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;
};
class DrmPresenter {
@@ -95,16 +101,23 @@ class DrmPresenter {
return -1;
}
+ std::tuple<HWC2::Error, std::shared_ptr<DrmBuffer>> create(
+ const native_handle_t* handle);
+
std::tuple<HWC2::Error, base::unique_fd> flushToDisplay(
- int display, hwc_drm_bo_t& fb, base::borrowed_fd inWaitSyncFd);
+ int display, const DrmBuffer& buffer, base::borrowed_fd inWaitSyncFd);
std::optional<std::vector<uint8_t>> getEdid(uint32_t id);
private:
+ using DrmPrimeBufferHandle = uint32_t;
+ using DrmBufferCache = LruCache<DrmPrimeBufferHandle, std::shared_ptr<DrmBuffer>>;
+ std::unique_ptr<DrmBufferCache> mBufferCache;
+
// Grant visibility for getDrmFB and clearDrmFB to DrmBuffer.
+ // Grant visibility to destroyDrmFramebuffer to DrmBuffer.
friend class DrmBuffer;
- int getDrmFB(hwc_drm_bo_t& bo);
- int clearDrmFB(hwc_drm_bo_t& bo);
+ HWC2::Error destroyDrmFramebuffer(DrmBuffer* buffer);
// Grant visibility for handleHotplug to DrmEventListener.
bool handleHotplug();
diff --git a/system/hwc2/GuestComposer.cpp b/system/hwc2/GuestComposer.cpp
index 9f8dc055..2c911925 100644
--- a/system/hwc2/GuestComposer.cpp
+++ b/system/hwc2/GuestComposer.cpp
@@ -463,12 +463,17 @@ HWC2::Error GuestComposer::onDisplayCreate(Display* display) {
displayInfo.compositionResultBuffer = bufferHandle;
- displayInfo.compositionResultDrmBuffer = std::make_unique<DrmBuffer>(
- displayInfo.compositionResultBuffer, mDrmPresenter);
+ auto [drmBufferCreateError, drmBuffer] = mDrmPresenter->create(bufferHandle);
+ if (drmBufferCreateError != HWC2::Error::None) {
+ ALOGE("%s: display:%" PRIu64 " failed to create client target drm buffer",
+ __FUNCTION__, displayId);
+ return HWC2::Error::NoResources;
+ }
+ displayInfo.compositionResultDrmBuffer = std::move(drmBuffer);
if (displayId == 0) {
- auto [flushError, flushSyncFd] =
- displayInfo.compositionResultDrmBuffer->flushToDisplay(displayId, -1);
+ auto [flushError, flushSyncFd] = mDrmPresenter->flushToDisplay(
+ displayId, *displayInfo.compositionResultDrmBuffer, -1);
if (flushError != HWC2::Error::None) {
ALOGW(
"%s: Initial display flush failed. HWComposer assuming that we are "
@@ -835,9 +840,8 @@ std::tuple<HWC2::Error, base::unique_fd> GuestComposer::presentDisplay(
DEBUG_LOG("%s display:%" PRIu64 " flushing drm buffer", __FUNCTION__,
displayId);
- auto [error, outRetireFence] =
- displayInfo.compositionResultDrmBuffer->flushToDisplay(
- static_cast<int>(displayId), -1);
+ auto [error, outRetireFence] = mDrmPresenter->flushToDisplay(
+ displayId, *displayInfo.compositionResultDrmBuffer, -1);
if (error != HWC2::Error::None) {
ALOGE("%s: display:%" PRIu64 " failed to flush drm buffer" PRIu64,
__FUNCTION__, displayId);
diff --git a/system/hwc2/GuestComposer.h b/system/hwc2/GuestComposer.h
index a7a8be73..d9579a0e 100644
--- a/system/hwc2/GuestComposer.h
+++ b/system/hwc2/GuestComposer.h
@@ -90,7 +90,7 @@ class GuestComposer : public Composer {
// 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<hwc2_display_t, GuestComposerDisplayInfo> mDisplayInfos;
diff --git a/system/hwc2/HostComposer.cpp b/system/hwc2/HostComposer.cpp
index 5bf324e0..92f8409d 100644
--- a/system/hwc2/HostComposer.cpp
+++ b/system/hwc2/HostComposer.cpp
@@ -134,8 +134,13 @@ HostComposer::CompositionResultBuffer::createWithDrmBuffer(
if (!res) {
return nullptr;
}
- res->mDrmBuffer = std::make_unique<DrmBuffer>(res->mFencedBuffer->getBuffer(),
- &drmPresenter);
+
+ auto [error, buffer] = drmPresenter.create(res->mFencedBuffer->getBuffer());
+ if (error != HWC2::Error::None) {
+ return nullptr;
+ }
+ res->mDrmBuffer = std::move(buffer);
+
return res;
}
@@ -441,8 +446,14 @@ HWC2::Error HostComposer::onDisplayClientTargetSet(Display* display) {
if (mIsMinigbm) {
FencedBuffer& clientTargetFencedBuffer = display->getClientTarget();
- displayInfo.clientTargetDrmBuffer.reset(
- new DrmBuffer(clientTargetFencedBuffer.getBuffer(), mDrmPresenter));
+ auto [drmBufferCreateError, drmBuffer] =
+ mDrmPresenter->create(clientTargetFencedBuffer.getBuffer());
+ if (drmBufferCreateError != HWC2::Error::None) {
+ ALOGE("%s: display:%" PRIu64 " failed to create client target drm buffer",
+ __FUNCTION__, displayId);
+ return HWC2::Error::NoResources;
+ }
+ displayInfo.clientTargetDrmBuffer = std::move(drmBuffer);
}
return HWC2::Error::None;
@@ -578,9 +589,8 @@ std::tuple<HWC2::Error, base::unique_fd> HostComposer::presentDisplay(
if (displayClientTarget.getBuffer() != nullptr) {
base::unique_fd fence = displayClientTarget.getFence();
if (mIsMinigbm) {
- auto [_, flushCompleteFence] =
- displayInfo.clientTargetDrmBuffer->flushToDisplay(
- display->getId(), fence);
+ auto [_, flushCompleteFence] = mDrmPresenter->flushToDisplay(
+ display->getId(), *displayInfo.clientTargetDrmBuffer, fence);
outRetireFence = std::move(flushCompleteFence);
} else {
post(hostCon, rcEnc, displayClientTarget.getBuffer());
@@ -725,9 +735,8 @@ std::tuple<HWC2::Error, base::unique_fd> HostComposer::presentDisplay(
}
if (mIsMinigbm) {
- auto [_, fence] =
- compositionResultBuffer.waitAndGetDrmBuffer().flushToDisplay(
- display->getId(), -1);
+ auto [_, fence] = mDrmPresenter->flushToDisplay(
+ display->getId(), compositionResultBuffer.waitAndGetDrmBuffer(), -1);
retire_fd = std::move(fence);
} else {
int fd;
@@ -756,9 +765,8 @@ std::tuple<HWC2::Error, base::unique_fd> HostComposer::presentDisplay(
FencedBuffer& displayClientTarget = display->getClientTarget();
base::unique_fd fence = displayClientTarget.getFence();
if (mIsMinigbm) {
- auto [_, outRetireFence] =
- displayInfo.clientTargetDrmBuffer->flushToDisplay(display->getId(),
- fence);
+ auto [_, outRetireFence] = mDrmPresenter->flushToDisplay(
+ display->getId(), *displayInfo.clientTargetDrmBuffer, fence);
outRetireFence = std::move(fence);
} else {
post(hostCon, rcEnc, displayClientTarget.getBuffer());
diff --git a/system/hwc2/HostComposer.h b/system/hwc2/HostComposer.h
index f17b6102..72026661 100644
--- a/system/hwc2/HostComposer.h
+++ b/system/hwc2/HostComposer.h
@@ -19,6 +19,7 @@
#include <android-base/unique_fd.h>
+#include <memory>
#include <tuple>
#include <vector>
@@ -92,7 +93,7 @@ class HostComposer : public Composer {
std::unique_ptr<FencedBuffer> mFencedBuffer;
// Drm info for the additional composition result buffer.
- std::unique_ptr<DrmBuffer> mDrmBuffer;
+ std::shared_ptr<DrmBuffer> mDrmBuffer;
};
class HostComposerDisplayInfo {
public:
@@ -103,7 +104,7 @@ class HostComposer : public Composer {
uint32_t hostDisplayId = 0;
// Drm info for the displays client target buffer.
- std::unique_ptr<DrmBuffer> clientTargetDrmBuffer;
+ std::shared_ptr<DrmBuffer> clientTargetDrmBuffer;
private:
// Additional per display buffer for the composition result.
diff --git a/system/hwc2/LruCache.h b/system/hwc2/LruCache.h
new file mode 100644
index 00000000..9ffca46a
--- /dev/null
+++ b/system/hwc2/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;
+};