diff options
author | Wiwit Rifa'i <wiwitrifai@google.com> | 2023-03-06 07:40:41 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2023-03-06 07:40:41 +0000 |
commit | 0584de6c22e58abd9420105609ae103710a84a5b (patch) | |
tree | 067d416fa3984468c8d9d4bba1c94dc35430dbc2 /libhwc2.1 | |
parent | 896de26fb1747138175169af681d92d93783113a (diff) | |
parent | 1baa6346adfe4d8ede6f2ad6cc8687058bfeab70 (diff) |
Merge changes from topic "hwc-rri-callback-impl" into udc-dev
* changes:
hwc3: add debug to trigger refresh rate indicator update
hwc3: add support for refresh rate indicator callback
Diffstat (limited to 'libhwc2.1')
-rw-r--r-- | libhwc2.1/libdevice/ExynosDevice.cpp | 16 | ||||
-rw-r--r-- | libhwc2.1/libdevice/ExynosDevice.h | 7 | ||||
-rw-r--r-- | libhwc2.1/libdevice/ExynosDisplay.cpp | 145 | ||||
-rw-r--r-- | libhwc2.1/libdevice/ExynosDisplay.h | 41 | ||||
-rw-r--r-- | libhwc2.1/libdevice/ExynosLayer.cpp | 10 | ||||
-rw-r--r-- | libhwc2.1/libdevice/ExynosLayer.h | 3 | ||||
-rw-r--r-- | libhwc2.1/libdisplayinterface/ExynosDeviceDrmInterface.cpp | 9 | ||||
-rw-r--r-- | libhwc2.1/libdisplayinterface/ExynosDeviceDrmInterface.h | 4 | ||||
-rw-r--r-- | libhwc2.1/libdisplayinterface/ExynosDeviceInterface.h | 16 | ||||
-rw-r--r-- | libhwc2.1/libdisplayinterface/ExynosDisplayDrmInterface.cpp | 4 | ||||
-rw-r--r-- | libhwc2.1/libdrmresource/drm/drmeventlistener.cpp | 70 | ||||
-rw-r--r-- | libhwc2.1/libdrmresource/include/drmeventlistener.h | 30 | ||||
-rw-r--r-- | libhwc2.1/libhwcService/ExynosHWCService.cpp | 13 | ||||
-rw-r--r-- | libhwc2.1/libhwcService/ExynosHWCService.h | 2 | ||||
-rw-r--r-- | libhwc2.1/libhwcService/IExynosHWC.cpp | 23 | ||||
-rw-r--r-- | libhwc2.1/libhwcService/IExynosHWC.h | 1 |
16 files changed, 366 insertions, 28 deletions
diff --git a/libhwc2.1/libdevice/ExynosDevice.cpp b/libhwc2.1/libdevice/ExynosDevice.cpp index f2eddbf..b4de1ae 100644 --- a/libhwc2.1/libdevice/ExynosDevice.cpp +++ b/libhwc2.1/libdevice/ExynosDevice.cpp @@ -1209,3 +1209,19 @@ void ExynosDevice::onVsyncIdle(hwc2_display_t displayId) { hwc2_display_t hwcDisplay)>(callbackInfo.funcPointer); callbackFunc(callbackInfo.callbackData, displayId); } + +void ExynosDevice::onRefreshRateChangedDebug(hwc2_display_t displayId, uint32_t vsyncPeriod) { + Mutex::Autolock lock(mDeviceCallbackMutex); + const auto &refreshRateCallback = + mHwc3CallbackInfos.find(IComposerCallback::TRANSACTION_onRefreshRateChangedDebug); + + if (refreshRateCallback == mHwc3CallbackInfos.end()) return; + + const auto &callbackInfo = refreshRateCallback->second; + if (callbackInfo.funcPointer == nullptr || callbackInfo.callbackData == nullptr) return; + + auto callbackFunc = + reinterpret_cast<void (*)(hwc2_callback_data_t callbackData, hwc2_display_t hwcDisplay, + hwc2_vsync_period_t)>(callbackInfo.funcPointer); + callbackFunc(callbackInfo.callbackData, displayId, vsyncPeriod); +} diff --git a/libhwc2.1/libdevice/ExynosDevice.h b/libhwc2.1/libdevice/ExynosDevice.h index 8b3d9e1..3569643 100644 --- a/libhwc2.1/libdevice/ExynosDevice.h +++ b/libhwc2.1/libdevice/ExynosDevice.h @@ -17,8 +17,8 @@ #ifndef _EXYNOSDEVICE_H #define _EXYNOSDEVICE_H -#include <aidl/com/google/hardware/pixel/display/BnDisplay.h> #include <aidl/android/hardware/graphics/composer3/OverlayProperties.h> +#include <aidl/com/google/hardware/pixel/display/BnDisplay.h> #include <cutils/atomic.h> #include <displaycolor/displaycolor.h> #include <hardware/hwcomposer2.h> @@ -36,6 +36,7 @@ #include <map> #include <thread> +#include "ExynosDeviceInterface.h" #include "ExynosHWC.h" #include "ExynosHWCHelper.h" #include "ExynosHWCModule.h" @@ -143,10 +144,8 @@ enum { GEOMETRY_ERROR_CASE = 1ULL << 63, }; -class ExynosDevice; class ExynosDisplay; class ExynosResourceManager; -class ExynosDeviceInterface; class ExynosDevice { public: @@ -346,6 +345,8 @@ class ExynosDevice { return HWC2_ERROR_UNSUPPORTED; } + void onRefreshRateChangedDebug(hwc2_display_t displayId, uint32_t vsyncPeriod); + protected: void initDeviceInterface(uint32_t interfaceType); protected: diff --git a/libhwc2.1/libdevice/ExynosDisplay.cpp b/libhwc2.1/libdevice/ExynosDisplay.cpp index 6542984..d050dee 100644 --- a/libhwc2.1/libdevice/ExynosDisplay.cpp +++ b/libhwc2.1/libdevice/ExynosDisplay.cpp @@ -31,6 +31,7 @@ #include <sys/ioctl.h> #include <utils/CallStack.h> +#include <charconv> #include <future> #include <map> @@ -988,6 +989,7 @@ ExynosDisplay::ExynosDisplay(uint32_t type, uint32_t index, ExynosDevice *device mClientCompositionInfo(COMPOSITION_CLIENT), mExynosCompositionInfo(COMPOSITION_EXYNOS), mGeometryChanged(0x0), + mBufferUpdates(0), mRenderingState(RENDERING_STATE_NONE), mHWCRenderingState(RENDERING_STATE_NONE), mDisplayBW(0), @@ -1475,11 +1477,16 @@ void ExynosDisplay::setGeometryChanged(uint64_t changedBit) { void ExynosDisplay::clearGeometryChanged() { mGeometryChanged = 0; + mBufferUpdates = 0; for (size_t i=0; i < mLayers.size(); i++) { mLayers[i]->clearGeometryChanged(); } } +bool ExynosDisplay::isFrameUpdate() { + return mGeometryChanged > 0 || mBufferUpdates > 0; +} + int ExynosDisplay::handleStaticLayers(ExynosCompositionInfo& compositionInfo) { if (compositionInfo.mType != COMPOSITION_CLIENT) @@ -1701,11 +1708,13 @@ int ExynosDisplay::skipStaticLayers(ExynosCompositionInfo& compositionInfo) return NO_ERROR; } -bool ExynosDisplay::skipSignalIdleForVideoLayer(void) { - /* ignore the frame update in case we have video layer but ui layer is not updated */ +bool ExynosDisplay::skipSignalIdle(void) { for (size_t i = 0; i < mLayers.size(); i++) { - if (!mLayers[i]->isLayerFormatYuv() && - mLayers[i]->mLastLayerBuffer != mLayers[i]->mLayerBuffer) { + // Frame update for refresh rate overlay indicator layer can be ignored + if (mLayers[i]->mCompositionType == HWC2_COMPOSITION_REFRESH_RATE_INDICATOR) continue; + // Frame update for video layer can be ignored + if (mLayers[i]->isLayerFormatYuv()) continue; + if (mLayers[i]->mLastLayerBuffer != mLayers[i]->mLayerBuffer) { return false; } } @@ -3024,6 +3033,9 @@ int32_t ExynosDisplay::getLayerCompositionTypeForValidationType(uint32_t layerIn } else if ((mLayers[layerIndex]->mCompositionType == HWC2_COMPOSITION_SOLID_COLOR) && (mLayers[layerIndex]->mValidateCompositionType == HWC2_COMPOSITION_DEVICE)) { type = HWC2_COMPOSITION_SOLID_COLOR; + } else if ((mLayers[layerIndex]->mCompositionType == HWC2_COMPOSITION_REFRESH_RATE_INDICATOR) && + (mLayers[layerIndex]->mValidateCompositionType == HWC2_COMPOSITION_DEVICE)) { + type = HWC2_COMPOSITION_REFRESH_RATE_INDICATOR; } else { type = mLayers[layerIndex]->mValidateCompositionType; } @@ -3601,10 +3613,14 @@ int32_t ExynosDisplay::presentDisplay(int32_t* outRetireFence) { goto err; } - if (mGeometryChanged != 0 || !skipSignalIdleForVideoLayer()) { + if (mGeometryChanged != 0 || !skipSignalIdle()) { mPowerHalHint.signalIdle(); } + if (isFrameUpdate()) { + updateRefreshRateIndicator(); + } + handleWindowUpdate(); setDisplayWinConfigData(); @@ -6149,3 +6165,122 @@ bool ExynosDisplay::RotatingLogFileWriter::chooseOpenedFile() { } return false; } + +ExynosDisplay::RefreshRateIndicatorHandler::RefreshRateIndicatorHandler(ExynosDisplay *display) + : mDisplay(display), mLastRefreshRate(0), mLastCallbackTime(0) {} + +int32_t ExynosDisplay::RefreshRateIndicatorHandler::init() { + auto path = String8::format(kRefreshRateStatePathFormat, mDisplay->mIndex); + mFd.Set(open(path.c_str(), O_RDONLY)); + if (mFd.get() < 0) { + ALOGE("Failed to open sysfs(%s) for refresh rate debug event: %s", path.c_str(), + strerror(errno)); + return -errno; + } + + return NO_ERROR; +} + +void ExynosDisplay::RefreshRateIndicatorHandler::updateRefreshRateLocked(int refreshRate) { + ATRACE_CALL(); + ATRACE_INT("Refresh rate indicator event", refreshRate); + auto lastUpdate = mDisplay->getLastLayerUpdateTime(); + // Ignore refresh rate increase that is caused by refresh rate indicator update but there's + // no update for the other layers + if (refreshRate > mLastRefreshRate && mLastRefreshRate > 0 && lastUpdate < mLastCallbackTime) { + mIgnoringLastUpdate = true; + return; + } + mIgnoringLastUpdate = false; + if (refreshRate == mLastRefreshRate) { + return; + } + mLastRefreshRate = refreshRate; + mLastCallbackTime = systemTime(CLOCK_MONOTONIC); + ATRACE_INT("Refresh rate indicator callback", mLastRefreshRate); + mDisplay->mDevice->onRefreshRateChangedDebug(mDisplay->mDisplayId, s2ns(1) / mLastRefreshRate); +} + +void ExynosDisplay::RefreshRateIndicatorHandler::handleSysfsEvent() { + ATRACE_CALL(); + std::scoped_lock lock(mMutex); + + char buffer[1024]; + lseek(mFd.get(), 0, SEEK_SET); + int ret = read(mFd.get(), &buffer, sizeof(buffer)); + if (ret < 0) { + ALOGE("%s: Failed to read refresh rate from fd %d: %s", __func__, mFd.get(), + strerror(errno)); + return; + } + std::string_view bufferView(buffer); + auto pos = bufferView.find('@'); + if (pos == std::string::npos) { + ALOGE("%s: Failed to parse refresh rate event (invalid format)", __func__); + return; + } + int refreshRate = 0; + std::from_chars(bufferView.data() + pos + 1, bufferView.data() + bufferView.size() - 1, + refreshRate); + updateRefreshRateLocked(refreshRate); +} + +void ExynosDisplay::RefreshRateIndicatorHandler::updateRefreshRate(int refreshRate) { + std::scoped_lock lock(mMutex); + updateRefreshRateLocked(refreshRate); +} + +int32_t ExynosDisplay::setRefreshRateChangedCallbackDebugEnabled(bool enabled) { + if ((!!mRefreshRateIndicatorHandler) == enabled) { + ALOGW("%s: RefreshRateChangedCallbackDebug is already %s", __func__, + enabled ? "enabled" : "disabled"); + return NO_ERROR; + } + int32_t ret = NO_ERROR; + if (enabled) { + mRefreshRateIndicatorHandler = std::make_shared<RefreshRateIndicatorHandler>(this); + if (!mRefreshRateIndicatorHandler) { + ALOGE("%s: Failed to create refresh rate debug handler", __func__); + return -ENOMEM; + } + ret = mRefreshRateIndicatorHandler->init(); + if (ret != NO_ERROR) { + ALOGE("%s: Failed to initialize refresh rate debug handler: %d", __func__, ret); + mRefreshRateIndicatorHandler.reset(); + return ret; + } + ret = mDevice->mDeviceInterface->registerSysfsEventHandler(mRefreshRateIndicatorHandler); + if (ret != NO_ERROR) { + ALOGE("%s: Failed to register sysfs event handler: %d", __func__, ret); + mRefreshRateIndicatorHandler.reset(); + return ret; + } + // Call the callback immediately + mRefreshRateIndicatorHandler->handleSysfsEvent(); + } else { + ret = mDevice->mDeviceInterface->unregisterSysfsEventHandler( + mRefreshRateIndicatorHandler->getFd()); + mRefreshRateIndicatorHandler.reset(); + } + return ret; +} + +nsecs_t ExynosDisplay::getLastLayerUpdateTime() { + Mutex::Autolock lock(mDRMutex); + nsecs_t time = 0; + for (size_t i = 0; i < mLayers.size(); ++i) { + // The update from refresh rate indicator layer should be ignored + if (mLayers[i]->mCompositionType == HWC2_COMPOSITION_REFRESH_RATE_INDICATOR) continue; + time = max(time, mLayers[i]->mLastUpdateTime); + } + return time; +} + +void ExynosDisplay::updateRefreshRateIndicator() { + // Update refresh rate indicator if the last update event is ignored to make sure that + // the refresh rate caused by the current frame update will be applied immediately since + // we may not receive the sysfs event if the refresh rate is the same as the last ignored one. + if (!mRefreshRateIndicatorHandler || !mRefreshRateIndicatorHandler->isIgnoringLastUpdate()) + return; + mRefreshRateIndicatorHandler->handleSysfsEvent(); +} diff --git a/libhwc2.1/libdevice/ExynosDisplay.h b/libhwc2.1/libdevice/ExynosDisplay.h index aaae5cb..65dd936 100644 --- a/libhwc2.1/libdevice/ExynosDisplay.h +++ b/libhwc2.1/libdevice/ExynosDisplay.h @@ -27,6 +27,7 @@ #include <chrono> #include <set> +#include "DeconHeader.h" #include "ExynosDisplayInterface.h" #include "ExynosHWC.h" #include "ExynosHWCDebug.h" @@ -34,8 +35,8 @@ #include "ExynosHwc3Types.h" #include "ExynosMPP.h" #include "ExynosResourceManager.h" +#include "drmeventlistener.h" #include "worker.h" -#include "DeconHeader.h" #define HWC_CLEARDISPLAY_WITH_COLORMAP #define HWC_PRINT_FRAME_NUM 10 @@ -449,10 +450,17 @@ class ExynosDisplay { * Geometry change info is described by bit map. * This flag is cleared when resource assignment for all displays * is done. + * Geometry changed to layer REFRESH_RATE_INDICATOR will be excluded. */ uint64_t mGeometryChanged; /** + * The number of buffer updates in the current frame. + * Buffer update for layer REFRESH_RATE_INDICATOR will be excluded. + */ + uint32_t mBufferUpdates; + + /** * Rendering step information that is seperated by * VALIDATED, ACCEPTED_CHANGE, PRESENTED. */ @@ -1190,6 +1198,7 @@ class ExynosDisplay { void setHWCControl(uint32_t ctrl, int32_t val); void setGeometryChanged(uint64_t changedBit); void clearGeometryChanged(); + bool isFrameUpdate(); virtual void setDDIScalerEnable(int width, int height); virtual int getDDIScalerMode(int width, int height); @@ -1293,7 +1302,7 @@ class ExynosDisplay { private: bool skipStaticLayerChanged(ExynosCompositionInfo& compositionInfo); - bool skipSignalIdleForVideoLayer(); + bool skipSignalIdle(); /// minimum possible dim rate in the case hbm peak is 1000 nits and norml // display brightness is 2 nits @@ -1589,6 +1598,34 @@ class ExynosDisplay { public: std::unique_ptr<OperationRateManager> mOperationRateManager; bool isOperationRateSupported() { return mOperationRateManager != nullptr; } + + class RefreshRateIndicatorHandler : public DrmSysfsEventHandler { + public: + RefreshRateIndicatorHandler(ExynosDisplay* display); + int32_t init(); + virtual void handleSysfsEvent() override; + virtual int getFd() override { return mFd.get(); }; + bool isIgnoringLastUpdate() { return mIgnoringLastUpdate; } + void updateRefreshRate(int refreshRate); + + private: + void updateRefreshRateLocked(int refreshRate) REQUIRES(mMutex); + + ExynosDisplay* mDisplay; + int mLastRefreshRate GUARDED_BY(mMutex); + nsecs_t mLastCallbackTime GUARDED_BY(mMutex); + std::atomic_bool mIgnoringLastUpdate = false; + UniqueFd mFd; + std::mutex mMutex; + + static constexpr auto kRefreshRateStatePathFormat = + "/sys/class/backlight/panel%d-backlight/state"; + }; + + std::shared_ptr<RefreshRateIndicatorHandler> mRefreshRateIndicatorHandler; + int32_t setRefreshRateChangedCallbackDebugEnabled(bool enabled); + void updateRefreshRateIndicator(); + nsecs_t getLastLayerUpdateTime(); }; #endif //_EXYNOSDISPLAY_H diff --git a/libhwc2.1/libdevice/ExynosLayer.cpp b/libhwc2.1/libdevice/ExynosLayer.cpp index 436f7a2..2c6feaf 100644 --- a/libhwc2.1/libdevice/ExynosLayer.cpp +++ b/libhwc2.1/libdevice/ExynosLayer.cpp @@ -59,6 +59,7 @@ ExynosLayer::ExynosLayer(ExynosDisplay* display) mNextLastFpsTime(0), mLastLayerBuffer(NULL), mLayerBuffer(NULL), + mLastUpdateTime(0), mDamageNum(0), mBlending(HWC2_BLEND_MODE_NONE), mPlaneAlpha(1.0), @@ -419,6 +420,11 @@ int32_t ExynosLayer::setLayerBuffer(buffer_handle_t buffer, int32_t acquireFence Mutex::Autolock lock(mDisplay->mDRMutex); mLayerBuffer = buffer; checkFps(mLastLayerBuffer != mLayerBuffer); + if (mLayerBuffer != mLastLayerBuffer) { + mLastUpdateTime = systemTime(CLOCK_MONOTONIC); + if (mCompositionType != HWC2_COMPOSITION_REFRESH_RATE_INDICATOR) + mDisplay->mBufferUpdates++; + } } mPrevAcquireFence = fence_close(mPrevAcquireFence, mDisplay, FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_UNDEFINED); @@ -1157,8 +1163,10 @@ void ExynosLayer::printLayer() void ExynosLayer::setGeometryChanged(uint64_t changedBit) { + mLastUpdateTime = systemTime(CLOCK_MONOTONIC); mGeometryChanged |= changedBit; - mDisplay->setGeometryChanged(changedBit); + if (mCompositionType != HWC2_COMPOSITION_REFRESH_RATE_INDICATOR) + mDisplay->setGeometryChanged(changedBit); } int ExynosLayer::allocMetaParcel() diff --git a/libhwc2.1/libdevice/ExynosLayer.h b/libhwc2.1/libdevice/ExynosLayer.h index c180fb3..4dc2423 100644 --- a/libhwc2.1/libdevice/ExynosLayer.h +++ b/libhwc2.1/libdevice/ExynosLayer.h @@ -77,6 +77,7 @@ typedef struct pre_processed_layer_info enum { HWC2_COMPOSITION_DISPLAY_DECORATION = toUnderlying(Composition::DISPLAY_DECORATION), + HWC2_COMPOSITION_REFRESH_RATE_INDICATOR = toUnderlying(Composition::REFRESH_RATE_INDICATOR), /*add after hwc2_composition_t, margin number here*/ HWC2_COMPOSITION_EXYNOS = 32, }; @@ -178,6 +179,8 @@ class ExynosLayer : public ExynosMPPSource { */ buffer_handle_t mLayerBuffer; + nsecs_t mLastUpdateTime; + /** * Surface Damage */ diff --git a/libhwc2.1/libdisplayinterface/ExynosDeviceDrmInterface.cpp b/libhwc2.1/libdisplayinterface/ExynosDeviceDrmInterface.cpp index febd76d..eab4cd1 100644 --- a/libhwc2.1/libdisplayinterface/ExynosDeviceDrmInterface.cpp +++ b/libhwc2.1/libdisplayinterface/ExynosDeviceDrmInterface.cpp @@ -312,3 +312,12 @@ void ExynosDeviceDrmInterface::ExynosDrmEventHandler::handleIdleEnterEvent(char primaryDisplay->handleDisplayIdleEnter(idleTeVrefresh); } } + +int32_t ExynosDeviceDrmInterface::registerSysfsEventHandler( + std::shared_ptr<DrmSysfsEventHandler> handler) { + return mDrmDevice->event_listener()->RegisterSysfsHandler(std::move(handler)); +} + +int32_t ExynosDeviceDrmInterface::unregisterSysfsEventHandler(int sysfsFd) { + return mDrmDevice->event_listener()->UnRegisterSysfsHandler(sysfsFd); +} diff --git a/libhwc2.1/libdisplayinterface/ExynosDeviceDrmInterface.h b/libhwc2.1/libdisplayinterface/ExynosDeviceDrmInterface.h index 9aa2798..69fc4f0 100644 --- a/libhwc2.1/libdisplayinterface/ExynosDeviceDrmInterface.h +++ b/libhwc2.1/libdisplayinterface/ExynosDeviceDrmInterface.h @@ -31,6 +31,10 @@ class ExynosDeviceDrmInterface : public ExynosDeviceInterface { virtual int32_t initDisplayInterface( std::unique_ptr<ExynosDisplayInterface> &dispInterface) override; virtual void updateRestrictions() override; + virtual int32_t registerSysfsEventHandler( + std::shared_ptr<DrmSysfsEventHandler> handler) override; + virtual int32_t unregisterSysfsEventHandler(int sysfsFd) override; + protected: class ExynosDrmEventHandler : public DrmEventHandler, public DrmHistogramEventHandler, diff --git a/libhwc2.1/libdisplayinterface/ExynosDeviceInterface.h b/libhwc2.1/libdisplayinterface/ExynosDeviceInterface.h index 747f016..dd976b0 100644 --- a/libhwc2.1/libdisplayinterface/ExynosDeviceInterface.h +++ b/libhwc2.1/libdisplayinterface/ExynosDeviceInterface.h @@ -17,8 +17,9 @@ #ifndef _EXYNOSDEVICEINTERFACE_H #define _EXYNOSDEVICEINTERFACE_H -#include "ExynosHWCHelper.h" #include "ExynosDisplayInterface.h" +#include "ExynosHWCHelper.h" +#include "drmeventlistener.h" struct hwc_dpp_size_range { uint32_t min; @@ -82,12 +83,21 @@ class ExynosDeviceInterface { virtual ~ExynosDeviceInterface(){}; virtual void init(ExynosDevice *exynosDevice) = 0; virtual int32_t initDisplayInterface( - std::unique_ptr<ExynosDisplayInterface> &dispInterface) - { return 0;}; + std::unique_ptr<ExynosDisplayInterface> __unused &dispInterface) { + return 0; + }; /* Fill mDPUInfo according to interface type */ virtual void updateRestrictions() = 0; virtual bool getUseQuery() { return mUseQuery; }; + virtual int32_t registerSysfsEventHandler( + std::shared_ptr<DrmSysfsEventHandler> __unused handler) { + return android::INVALID_OPERATION; + } + virtual int32_t unregisterSysfsEventHandler(int __unused sysfsFd) { + return android::INVALID_OPERATION; + } + uint32_t getNumDPPChs() { return mDPUInfo.dpuInfo.dpp_chs.size(); }; uint32_t getNumSPPChs() { return mDPUInfo.dpuInfo.spp_chs.size(); }; uint32_t getSPPChId(uint32_t index) { return mDPUInfo.dpuInfo.spp_chs.at(index).id; }; diff --git a/libhwc2.1/libdisplayinterface/ExynosDisplayDrmInterface.cpp b/libhwc2.1/libdisplayinterface/ExynosDisplayDrmInterface.cpp index 3746a46..7f565e4 100644 --- a/libhwc2.1/libdisplayinterface/ExynosDisplayDrmInterface.cpp +++ b/libhwc2.1/libdisplayinterface/ExynosDisplayDrmInterface.cpp @@ -1698,7 +1698,9 @@ int32_t ExynosDisplayDrmInterface::deliverWinConfigData() android::String8 result; bool hasSecureFrameBuffer = false; - mFrameCounter++; + if (mExynosDisplay->isFrameUpdate()) { + mFrameCounter++; + } funcReturnCallback retCallback([&]() { if ((ret == NO_ERROR) && !drmReq.getError()) { mFBManager.flip(hasSecureFrameBuffer); diff --git a/libhwc2.1/libdrmresource/drm/drmeventlistener.cpp b/libhwc2.1/libdrmresource/drm/drmeventlistener.cpp index 3132bc5..bd12d30 100644 --- a/libhwc2.1/libdrmresource/drm/drmeventlistener.cpp +++ b/libhwc2.1/libdrmresource/drm/drmeventlistener.cpp @@ -17,19 +17,21 @@ #define LOG_TAG "hwc-drm-event-listener" #include "drmeventlistener.h" -#include "drmdevice.h" -#include <drm/samsung_drm.h> #include <assert.h> +#include <drm/samsung_drm.h> #include <errno.h> -#include <linux/netlink.h> -#include <sys/socket.h> - #include <hardware/hardware.h> #include <hardware/hwcomposer.h> +#include <inttypes.h> +#include <linux/netlink.h> #include <log/log.h> +#include <sys/socket.h> +#include <utils/String8.h> #include <xf86drm.h> +#include "drmdevice.h" + namespace android { DrmEventListener::DrmEventListener(DrmDevice *drm) @@ -143,6 +145,43 @@ void DrmEventListener::UnRegisterPanelIdleHandler(DrmPanelIdleEventHandler *hand panel_idle_handler_ = NULL; } +int DrmEventListener::RegisterSysfsHandler(std::shared_ptr<DrmSysfsEventHandler> handler) { + if (!handler) + return -EINVAL; + if (handler->getFd() < 0) + return -EINVAL; + std::scoped_lock lock(mutex_); + if (sysfs_handlers_.find(handler->getFd()) != sysfs_handlers_.end()) { + ALOGE("%s: DrmSysfsEventHandler for fd:%d has been added to epoll", __func__, handler->getFd()); + return -EINVAL; + } + + struct epoll_event ev; + ev.events = EPOLLPRI; + ev.data.fd = handler->getFd(); + if (epoll_ctl(epoll_fd_.get(), EPOLL_CTL_ADD, handler->getFd(), &ev) < 0) { + ALOGE("%s: Failed to add fd into epoll: %s", __func__, strerror(errno)); + return -errno; + } + sysfs_handlers_.emplace(handler->getFd(), std::move(handler)); + return 0; +} + +int DrmEventListener::UnRegisterSysfsHandler(int sysfs_fd) { + std::scoped_lock lock(mutex_); + auto it = sysfs_handlers_.find(sysfs_fd); + if (it == sysfs_handlers_.end()) { + ALOGE("%s: DrmSysfsEventHandler for fd:%d not found", __func__, sysfs_fd); + return -EINVAL; + } + if (epoll_ctl(epoll_fd_.get(), EPOLL_CTL_DEL, sysfs_fd, nullptr) < 0) { + ALOGE("%s: Failed to remove fd from epoll: %s", __func__, strerror(errno)); + return -errno; + } + sysfs_handlers_.erase(it); + return 0; +} + bool DrmEventListener::IsDrmInTUI() { char buffer[1024]; int ret; @@ -267,6 +306,23 @@ void DrmEventListener::TUIEventHandler() { tui_handler_->handleTUIEvent(); } +void DrmEventListener::SysfsEventHandler(int fd) { + std::shared_ptr<DrmSysfsEventHandler> handler; + { + std::scoped_lock lock(mutex_); + // Copy the shared_ptr to avoid the handler object gets destroyed + // while it's handling the event without holding mutex_ + auto it = sysfs_handlers_.find(fd); + if (it != sysfs_handlers_.end()) + handler = it->second; + } + if (handler) { + handler->handleSysfsEvent(); + } else { + ALOGW("Unhandled sysfs event from fd:%d", fd); + } +} + void DrmEventListener::Routine() { struct epoll_event events[maxFds]; int nfds, n; @@ -280,11 +336,13 @@ void DrmEventListener::Routine() { if (events[n].data.fd == uevent_fd_.get()) { UEventHandler(); } else if (events[n].data.fd == drm_->fd()) { - DRMEventHandler(); + DRMEventHandler(); } } else if (events[n].events & EPOLLPRI) { if (tuievent_fd_.get() >= 0 && events[n].data.fd == tuievent_fd_.get()) { TUIEventHandler(); + } else { + SysfsEventHandler(events[n].data.fd); } } } diff --git a/libhwc2.1/libdrmresource/include/drmeventlistener.h b/libhwc2.1/libdrmresource/include/drmeventlistener.h index 474b116..e85ca0a 100644 --- a/libhwc2.1/libdrmresource/include/drmeventlistener.h +++ b/libhwc2.1/libdrmresource/include/drmeventlistener.h @@ -17,11 +17,13 @@ #ifndef ANDROID_DRM_EVENT_LISTENER_H_ #define ANDROID_DRM_EVENT_LISTENER_H_ +#include <sys/epoll.h> + +#include <map> + #include "autofd.h" #include "worker.h" -#include <sys/epoll.h> - namespace android { class DrmDevice; @@ -62,9 +64,19 @@ class DrmPanelIdleEventHandler { virtual void handleIdleEnterEvent(char const *event) = 0; }; +class DrmSysfsEventHandler { + public: + DrmSysfsEventHandler() {} + virtual ~DrmSysfsEventHandler() {} + + virtual void handleSysfsEvent() = 0; + virtual int getFd() = 0; +}; + class DrmEventListener : public Worker { - static constexpr const char kTUIStatusPath[] = "/sys/devices/platform/exynos-drm/tui_status"; - static const uint32_t maxFds = 3; + static constexpr const char kTUIStatusPath[] = "/sys/devices/platform/exynos-drm/tui_status"; + static const uint32_t maxFds = 4; + public: DrmEventListener(DrmDevice *drm); virtual ~DrmEventListener(); @@ -79,11 +91,13 @@ class DrmEventListener : public Worker { void UnRegisterTUIHandler(DrmTUIEventHandler *handler); void RegisterPanelIdleHandler(DrmPanelIdleEventHandler *handler); void UnRegisterPanelIdleHandler(DrmPanelIdleEventHandler *handler); + int RegisterSysfsHandler(std::shared_ptr<DrmSysfsEventHandler> handler); + int UnRegisterSysfsHandler(int sysfs_fd); bool IsDrmInTUI(); - static void FlipHandler(int fd, unsigned int sequence, unsigned int tv_sec, - unsigned int tv_usec, void *user_data); + static void FlipHandler(int fd, unsigned int sequence, unsigned int tv_sec, unsigned int tv_usec, + void *user_data); protected: virtual void Routine(); @@ -92,6 +106,7 @@ class DrmEventListener : public Worker { void UEventHandler(); void DRMEventHandler(); void TUIEventHandler(); + void SysfsEventHandler(int fd); UniqueFd epoll_fd_; UniqueFd uevent_fd_; @@ -102,7 +117,10 @@ class DrmEventListener : public Worker { std::unique_ptr<DrmHistogramEventHandler> histogram_handler_; std::unique_ptr<DrmTUIEventHandler> tui_handler_; std::unique_ptr<DrmPanelIdleEventHandler> panel_idle_handler_; + std::mutex mutex_; + std::map<int, std::shared_ptr<DrmSysfsEventHandler>> sysfs_handlers_; }; + } // namespace android #endif diff --git a/libhwc2.1/libhwcService/ExynosHWCService.cpp b/libhwc2.1/libhwcService/ExynosHWCService.cpp index df2d65f..fd8278b 100644 --- a/libhwc2.1/libhwcService/ExynosHWCService.cpp +++ b/libhwc2.1/libhwcService/ExynosHWCService.cpp @@ -503,4 +503,17 @@ int32_t ExynosHWCService::setDisplayMultiThreadedPresent(const int32_t& displayI return NO_ERROR; } +int32_t ExynosHWCService::triggerRefreshRateIndicatorUpdate(uint32_t displayId, + uint32_t refreshRate) { + auto display = mHWCCtx->device->getDisplay(displayId); + + if (display == nullptr) return -EINVAL; + + ALOGD("ExynosHWCService::%s() displayID(%u) refreshRate(%u)", __func__, displayId, refreshRate); + if (display->mRefreshRateIndicatorHandler) { + display->mRefreshRateIndicatorHandler->updateRefreshRate(refreshRate); + } + return NO_ERROR; +} + } //namespace android diff --git a/libhwc2.1/libhwcService/ExynosHWCService.h b/libhwc2.1/libhwcService/ExynosHWCService.h index d9cfe1c..abb525f 100644 --- a/libhwc2.1/libhwcService/ExynosHWCService.h +++ b/libhwc2.1/libhwcService/ExynosHWCService.h @@ -81,6 +81,8 @@ public: virtual int32_t setDisplayMultiThreadedPresent(const int32_t& display_id, const bool& enable) override; + virtual int32_t triggerRefreshRateIndicatorUpdate(uint32_t displayId, + uint32_t refreshRate) override; private: friend class Singleton<ExynosHWCService>; diff --git a/libhwc2.1/libhwcService/IExynosHWC.cpp b/libhwc2.1/libhwcService/IExynosHWC.cpp index 1efe9fc..f092696 100644 --- a/libhwc2.1/libhwcService/IExynosHWC.cpp +++ b/libhwc2.1/libhwcService/IExynosHWC.cpp @@ -65,6 +65,7 @@ enum { TRIGGER_DISPLAY_IDLE_ENTER = 1008, SET_DISPLAY_DBM = 1009, SET_DISPLAY_MULTI_THREADED_PRESENT = 1010, + TRIGGER_REFRESH_RATE_INDICATOR_UPDATE = 1011, }; class BpExynosHWCService : public BpInterface<IExynosHWCService> { @@ -446,7 +447,7 @@ public: data.writeUint32(displayIndex); data.writeUint32(idleTeRefreshRate); - auto result = remote()->transact(SET_DISPLAY_RCDLAYER_ENABLED, data, &reply); + auto result = remote()->transact(TRIGGER_DISPLAY_IDLE_ENTER, data, &reply); ALOGE_IF(result != NO_ERROR, "TRIGGER_DISPLAY_IDLE_ENTER transact error(%d)", result); return result; } @@ -471,6 +472,19 @@ public: if (result) ALOGE("SET_DISPLAY_MULTI_THREADED_PRESENT transact error(%d)", result); return result; } + + virtual int32_t triggerRefreshRateIndicatorUpdate(uint32_t displayId, + uint32_t refreshRate) override { + Parcel data, reply; + data.writeInterfaceToken(IExynosHWCService::getInterfaceDescriptor()); + data.writeUint32(displayId); + data.writeUint32(refreshRate); + + auto result = remote()->transact(TRIGGER_REFRESH_RATE_INDICATOR_UPDATE, data, &reply); + ALOGE_IF(result != NO_ERROR, "TRIGGER_REFRESH_RATE_INDICATOR_UPDATE transact error(%d)", + result); + return result; + } }; IMPLEMENT_META_INTERFACE(ExynosHWCService, "android.hal.ExynosHWCService"); @@ -734,6 +748,13 @@ status_t BnExynosHWCService::onTransact( return NO_ERROR; } break; + case TRIGGER_REFRESH_RATE_INDICATOR_UPDATE: { + CHECK_INTERFACE(IExynosHWCService, data, reply); + uint32_t displayId = data.readUint32(); + uint32_t refreshRate = data.readUint32(); + return triggerRefreshRateIndicatorUpdate(displayId, refreshRate); + } break; + default: return BBinder::onTransact(code, data, reply, flags); } diff --git a/libhwc2.1/libhwcService/IExynosHWC.h b/libhwc2.1/libhwcService/IExynosHWC.h index 75d95cb..bf51c85 100644 --- a/libhwc2.1/libhwcService/IExynosHWC.h +++ b/libhwc2.1/libhwcService/IExynosHWC.h @@ -76,6 +76,7 @@ public: virtual int32_t setDisplayDbm(int32_t display_id, uint32_t on) = 0; virtual int32_t setDisplayMultiThreadedPresent(const int32_t& displayId, const bool& enable) = 0; + virtual int32_t triggerRefreshRateIndicatorUpdate(uint32_t displayId, uint32_t refreshRate) = 0; }; /* Native Interface */ |