summaryrefslogtreecommitdiff
path: root/libhwc2.1
diff options
context:
space:
mode:
authorWiwit Rifa'i <wiwitrifai@google.com>2023-03-06 07:40:41 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2023-03-06 07:40:41 +0000
commit0584de6c22e58abd9420105609ae103710a84a5b (patch)
tree067d416fa3984468c8d9d4bba1c94dc35430dbc2 /libhwc2.1
parent896de26fb1747138175169af681d92d93783113a (diff)
parent1baa6346adfe4d8ede6f2ad6cc8687058bfeab70 (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.cpp16
-rw-r--r--libhwc2.1/libdevice/ExynosDevice.h7
-rw-r--r--libhwc2.1/libdevice/ExynosDisplay.cpp145
-rw-r--r--libhwc2.1/libdevice/ExynosDisplay.h41
-rw-r--r--libhwc2.1/libdevice/ExynosLayer.cpp10
-rw-r--r--libhwc2.1/libdevice/ExynosLayer.h3
-rw-r--r--libhwc2.1/libdisplayinterface/ExynosDeviceDrmInterface.cpp9
-rw-r--r--libhwc2.1/libdisplayinterface/ExynosDeviceDrmInterface.h4
-rw-r--r--libhwc2.1/libdisplayinterface/ExynosDeviceInterface.h16
-rw-r--r--libhwc2.1/libdisplayinterface/ExynosDisplayDrmInterface.cpp4
-rw-r--r--libhwc2.1/libdrmresource/drm/drmeventlistener.cpp70
-rw-r--r--libhwc2.1/libdrmresource/include/drmeventlistener.h30
-rw-r--r--libhwc2.1/libhwcService/ExynosHWCService.cpp13
-rw-r--r--libhwc2.1/libhwcService/ExynosHWCService.h2
-rw-r--r--libhwc2.1/libhwcService/IExynosHWC.cpp23
-rw-r--r--libhwc2.1/libhwcService/IExynosHWC.h1
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 */