diff options
author | Jason Macnak <natsu@google.com> | 2022-09-07 14:25:46 -0700 |
---|---|---|
committer | Alistair Delva <adelva@google.com> | 2022-09-07 22:08:48 +0000 |
commit | 482e759862dc1aa0dd8167bd681e9476d9432e75 (patch) | |
tree | 1a57d4d0e58591a923a5f19118d3f7f8b87953d3 | |
parent | ea0971361df87dac267181a7b413075cbdfd7644 (diff) | |
download | goldfish-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.cpp | 14 | ||||
-rw-r--r-- | system/hwc2/ClientComposer.h | 3 | ||||
-rw-r--r-- | system/hwc2/DrmPresenter.cpp | 190 | ||||
-rw-r--r-- | system/hwc2/DrmPresenter.h | 35 | ||||
-rw-r--r-- | system/hwc2/GuestComposer.cpp | 18 | ||||
-rw-r--r-- | system/hwc2/GuestComposer.h | 2 | ||||
-rw-r--r-- | system/hwc2/HostComposer.cpp | 34 | ||||
-rw-r--r-- | system/hwc2/HostComposer.h | 5 | ||||
-rw-r--r-- | system/hwc2/LruCache.h | 83 |
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; +}; |