summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-03-14 07:06:04 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-03-14 07:06:04 +0000
commitbfe32204bab9bb9155a8d664841da7955b834315 (patch)
treedc74442534bbbee9f73a499b5e580fd4ec575842
parent34e98cc0d62920fbbe969c315a21acf1f34aad11 (diff)
parent07ea90a5c3cf941e4e0db6a2086fe48d7e362b6f (diff)
downloadcommon-main-cg-testing-release.tar.gz
Snap for 8294919 from 07ea90a5c3cf941e4e0db6a2086fe48d7e362b6f to main-cg-testing-releasemain-cg-testing-release
Change-Id: I8b08f23686921b70c77cfa28602e1124d580f877
-rw-r--r--Android.mk2
-rw-r--r--include/displaycolor/displaycolor.h67
-rw-r--r--libhwc2.1/Android.mk60
-rw-r--r--libhwc2.1/ExynosHWC.cpp1
-rw-r--r--libhwc2.1/libdevice/ExynosDevice.cpp35
-rw-r--r--libhwc2.1/libdevice/ExynosDevice.h4
-rw-r--r--libhwc2.1/libdevice/ExynosDisplay.cpp183
-rw-r--r--libhwc2.1/libdevice/ExynosDisplay.h53
-rw-r--r--libhwc2.1/libdevice/ExynosLayer.cpp22
-rw-r--r--libhwc2.1/libdevice/ExynosLayer.h1
-rw-r--r--libhwc2.1/libdisplayinterface/ExynosDeviceDrmInterface.cpp2
-rw-r--r--libhwc2.1/libdisplayinterface/ExynosDisplayDrmInterface.cpp114
-rw-r--r--libhwc2.1/libdisplayinterface/ExynosDisplayDrmInterface.h11
-rw-r--r--libhwc2.1/libdrmresource/drm/drmeventlistener.cpp4
-rw-r--r--libhwc2.1/libdrmresource/drm/vsyncworker.cpp1
-rw-r--r--libhwc2.1/libdrmresource/include/drmeventlistener.h3
-rw-r--r--libhwc2.1/libdrmresource/utils/worker.cpp1
-rw-r--r--libhwc2.1/libexternaldisplay/ExynosExternalDisplay.cpp2
-rw-r--r--libhwc2.1/libhwcService/ExynosHWCService.cpp47
-rw-r--r--libhwc2.1/libhwcService/ExynosHWCService.h4
-rw-r--r--libhwc2.1/libhwcService/IExynosHWC.cpp56
-rw-r--r--libhwc2.1/libhwcService/IExynosHWC.h3
-rw-r--r--libhwc2.1/libmaindisplay/ExynosPrimaryDisplay.cpp254
-rw-r--r--libhwc2.1/libmaindisplay/ExynosPrimaryDisplay.h24
-rw-r--r--libhwc2.1/libresource/ExynosResourceManager.cpp1
-rw-r--r--libhwc2.1/libvirtualdisplay/ExynosVirtualDisplay.h2
-rw-r--r--libhwc2.1/pixel-display-default.xml2
-rw-r--r--libhwc2.1/pixel-display.cpp24
-rw-r--r--libhwc2.1/pixel-display.h2
29 files changed, 840 insertions, 145 deletions
diff --git a/Android.mk b/Android.mk
index 3680649..aeaba30 100644
--- a/Android.mk
+++ b/Android.mk
@@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-ifneq ($(filter gs101,$(TARGET_BOARD_PLATFORM)),)
+ifeq (google,$(TARGET_SOC_NAME))
build_dirs := \
libhwjpeg \
libscaler \
diff --git a/include/displaycolor/displaycolor.h b/include/displaycolor/displaycolor.h
index ef1ba4e..b82ff43 100644
--- a/include/displaycolor/displaycolor.h
+++ b/include/displaycolor/displaycolor.h
@@ -30,6 +30,36 @@ using android::hardware::graphics::common::V1_2::ColorMode;
using android::hardware::graphics::common::V1_2::Dataspace;
} // namespace hwc
+/**
+ * hwc/displaycolor interface history
+ *
+ * 3.0.0.2021-11-18 calibration info intf
+ * 2.0.0.2021-08-27 pass brightness table for hdr10+
+ * 1.0.0.2021-08-25 Initial release
+ */
+
+constexpr struct DisplayColorIntfVer {
+ uint16_t major; // increase it for new functionalities
+ uint16_t minor; // for bug fix and cause binary incompatible
+ uint16_t patch; // for bug fix and binary compatible
+
+ bool operator==(const DisplayColorIntfVer &rhs) const {
+ return major == rhs.major &&
+ minor == rhs.minor &&
+ patch == rhs.patch;
+ }
+
+ bool Compatible(const DisplayColorIntfVer &rhs) const {
+ return major == rhs.major &&
+ minor == rhs.minor;
+ }
+
+} kInterfaceVersion {
+ 3,
+ 0,
+ 0,
+};
+
/// A map associating supported RenderIntents for each supported ColorMode
using ColorModesMap = std::map<hwc::ColorMode, std::vector<hwc::RenderIntent>>;
@@ -52,6 +82,25 @@ enum BrightnessMode {
BM_MAX = 2,
};
+struct DisplayBrightnessTable {
+ float nbm_nits_min;
+ float nbm_nits_max;
+ float hbm_nits_min;
+ float hbm_nits_max;
+
+ uint32_t nbm_dbv_min;
+ uint32_t nbm_dbv_max;
+ uint32_t hbm_dbv_min;
+ uint32_t hbm_dbv_max;
+};
+
+struct DisplayInfo {
+ std::string panel_name;
+ std::string panel_serial;
+
+ DisplayBrightnessTable brightness_table;
+};
+
struct LayerColorData {
bool operator==(const LayerColorData &rhs) const {
return dataspace == rhs.dataspace && matrix == rhs.matrix &&
@@ -219,6 +268,13 @@ struct DisplayScene {
bool hdr_full_screen;
};
+struct CalibrationInfo {
+ bool factory_cal_loaded;
+ bool golden_cal_loaded;
+ bool common_cal_loaded;
+ bool dev_cal_loaded;
+};
+
/// An interface specifying functions that are HW-agnostic.
class IDisplayColorGeneric {
public:
@@ -282,6 +338,13 @@ class IDisplayColorGeneric {
virtual bool IsRrCompensationEnabled(DisplayType display) = 0;
/**
+ * @brief Get calibration information for each profiles.
+ * @param display The display to get the calibration information.
+ */
+ virtual const CalibrationInfo &GetCalibrationInfo(
+ DisplayType display) const = 0;
+
+ /**
* @brief Get a map of supported ColorModes, and supported RenderIntents for
* each ColorMode.
* @param display The display to get the color modes and render intents.
@@ -290,6 +353,10 @@ class IDisplayColorGeneric {
DisplayType display) const = 0;
};
+extern "C" {
+ const DisplayColorIntfVer *GetInterfaceVersion();
+}
+
} // namespace displaycolor
#endif // DISPLAYCOLOR_H_
diff --git a/libhwc2.1/Android.mk b/libhwc2.1/Android.mk
index 3b87ecf..a6d4078 100644
--- a/libhwc2.1/Android.mk
+++ b/libhwc2.1/Android.mk
@@ -12,6 +12,9 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+# TODO(b/186905324): Switch soc_ver with TARGET_BOARD_PLATFORM
+soc_ver := $(TARGET_BOARD_PLATFORM)
+
LOCAL_PATH:= $(call my-dir)
# HAL module implemenation, not prelinked and stored in
# hw/<COPYPIX_HARDWARE_MODULE_ID>.<ro.product.board>.so
@@ -40,6 +43,7 @@ LOCAL_SRC_FILES := \
LOCAL_CFLAGS := -DHLOG_CODE=0
LOCAL_CFLAGS += -Wno-unused-parameter
+LOCAL_CFLAGS += -DSOC_VERSION=$(soc_ver)
LOCAL_EXPORT_SHARED_LIBRARY_HEADERS := libdrm
LOCAL_MODULE := libdrmresource
@@ -63,7 +67,7 @@ LOCAL_SHARED_LIBRARIES := liblog libcutils libhardware \
libvendorgraphicbuffer libbinder_ndk \
android.hardware.power-V1-ndk pixel-power-ext-V1-ndk
-LOCAL_SHARED_LIBRARIES += com.google.hardware.pixel.display-V3-ndk \
+LOCAL_SHARED_LIBRARIES += com.google.hardware.pixel.display-V4-ndk \
libbinder_ndk \
libbase \
libpng \
@@ -85,14 +89,14 @@ LOCAL_C_INCLUDES += \
$(TOP)/hardware/google/graphics/common/libhwc2.1/libvirtualdisplay \
$(TOP)/hardware/google/graphics/common/libhwc2.1/libhwchelper \
$(TOP)/hardware/google/graphics/common/libhwc2.1/libresource \
- $(TOP)/hardware/google/graphics/$(TARGET_BOARD_PLATFORM)/libhwc2.1 \
- $(TOP)/hardware/google/graphics/$(TARGET_BOARD_PLATFORM)/libhwc2.1/libmaindisplay \
- $(TOP)/hardware/google/graphics/$(TARGET_BOARD_PLATFORM)/libhwc2.1/libexternaldisplay \
- $(TOP)/hardware/google/graphics/$(TARGET_BOARD_PLATFORM)/libhwc2.1/libvirtualdisplay \
- $(TOP)/hardware/google/graphics/$(TARGET_BOARD_PLATFORM)/libhwc2.1/libresource \
- $(TOP)/hardware/google/graphics/$(TARGET_BOARD_PLATFORM)/libhwc2.1/libdevice \
- $(TOP)/hardware/google/graphics/$(TARGET_BOARD_PLATFORM)/libhwc2.1/libresource \
- $(TOP)/hardware/google/graphics/$(TARGET_BOARD_PLATFORM)/libhwc2.1/libdisplayinterface \
+ $(TOP)/hardware/google/graphics/$(soc_ver)/libhwc2.1 \
+ $(TOP)/hardware/google/graphics/$(soc_ver)/libhwc2.1/libmaindisplay \
+ $(TOP)/hardware/google/graphics/$(soc_ver)/libhwc2.1/libexternaldisplay \
+ $(TOP)/hardware/google/graphics/$(soc_ver)/libhwc2.1/libvirtualdisplay \
+ $(TOP)/hardware/google/graphics/$(soc_ver)/libhwc2.1/libresource \
+ $(TOP)/hardware/google/graphics/$(soc_ver)/libhwc2.1/libdevice \
+ $(TOP)/hardware/google/graphics/$(soc_ver)/libhwc2.1/libresource \
+ $(TOP)/hardware/google/graphics/$(soc_ver)/libhwc2.1/libdisplayinterface \
$(TOP)/hardware/google/graphics/common/libhwc2.1/libhwcService \
$(TOP)/hardware/google/graphics/common/libhwc2.1/libdisplayinterface \
$(TOP)/hardware/google/graphics/common/libhwc2.1/libdrmresource/include
@@ -118,11 +122,12 @@ LOCAL_EXPORT_SHARED_LIBRARY_HEADERS += libacryl libdrm libui libvendorgraphicbuf
LOCAL_VINTF_FRAGMENTS += pixel-display-default.xml
-include $(TOP)/hardware/google/graphics/$(TARGET_BOARD_PLATFORM)/libhwc2.1/Android.mk
+include $(TOP)/hardware/google/graphics/$(soc_ver)/libhwc2.1/Android.mk
LOCAL_CFLAGS += -DHLOG_CODE=0
LOCAL_CFLAGS += -DLOG_TAG=\"display\"
LOCAL_CFLAGS += -Wno-unused-parameter
+LOCAL_CFLAGS += -DSOC_VERSION=$(soc_ver)
LOCAL_MODULE := libexynosdisplay
LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
@@ -146,7 +151,7 @@ LOCAL_SHARED_LIBRARIES := liblog libcutils libutils libbinder libexynosdisplay l
android.hardware.graphics.allocator@2.0 \
android.hardware.graphics.mapper@2.0
-LOCAL_SHARED_LIBRARIES += com.google.hardware.pixel.display-V3-ndk \
+LOCAL_SHARED_LIBRARIES += com.google.hardware.pixel.display-V4-ndk \
libbinder_ndk \
libbase
@@ -161,13 +166,13 @@ LOCAL_C_INCLUDES += \
$(TOP)/hardware/google/graphics/common/libhwc2.1/libvirtualdisplay \
$(TOP)/hardware/google/graphics/common/libhwc2.1/libhwchelper \
$(TOP)/hardware/google/graphics/common/libhwc2.1/libresource \
- $(TOP)/hardware/google/graphics/$(TARGET_BOARD_PLATFORM)/libhwc2.1 \
- $(TOP)/hardware/google/graphics/$(TARGET_BOARD_PLATFORM)/libhwc2.1/libmaindisplay \
- $(TOP)/hardware/google/graphics/$(TARGET_BOARD_PLATFORM)/libhwc2.1/libexternaldisplay \
- $(TOP)/hardware/google/graphics/$(TARGET_BOARD_PLATFORM)/libhwc2.1/libvirtualdisplay \
- $(TOP)/hardware/google/graphics/$(TARGET_BOARD_PLATFORM)/libhwc2.1/libresource \
- $(TOP)/hardware/google/graphics/$(TARGET_BOARD_PLATFORM)/libhwc2.1/libdevice \
- $(TOP)/hardware/google/graphics/$(TARGET_BOARD_PLATFORM)/libhwc2.1/libresource \
+ $(TOP)/hardware/google/graphics/$(soc_ver)/libhwc2.1 \
+ $(TOP)/hardware/google/graphics/$(soc_ver)/libhwc2.1/libmaindisplay \
+ $(TOP)/hardware/google/graphics/$(soc_ver)/libhwc2.1/libexternaldisplay \
+ $(TOP)/hardware/google/graphics/$(soc_ver)/libhwc2.1/libvirtualdisplay \
+ $(TOP)/hardware/google/graphics/$(soc_ver)/libhwc2.1/libresource \
+ $(TOP)/hardware/google/graphics/$(soc_ver)/libhwc2.1/libdevice \
+ $(TOP)/hardware/google/graphics/$(soc_ver)/libhwc2.1/libresource \
$(TOP)/hardware/google/graphics/common/libhwc2.1/libhwcService \
$(TOP)/hardware/google/graphics/common/libhwc2.1/libdisplayinterface \
$(TOP)/hardware/google/graphics/common/libhwc2.1/libdrmresource/include
@@ -177,6 +182,7 @@ LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_C_INCLUDES)
LOCAL_CFLAGS := -DHLOG_CODE=0
LOCAL_CFLAGS += -DLOG_TAG=\"hwcservice\"
+LOCAL_CFLAGS += -DSOC_VERSION=$(soc_ver)
LOCAL_SRC_FILES := \
libhwcService/IExynosHWC.cpp \
@@ -205,7 +211,7 @@ LOCAL_SHARED_LIBRARIES := liblog libcutils libutils libexynosdisplay libacryl \
android.hardware.graphics.mapper@2.0 \
libui
-LOCAL_SHARED_LIBRARIES += com.google.hardware.pixel.display-V3-ndk \
+LOCAL_SHARED_LIBRARIES += com.google.hardware.pixel.display-V4-ndk \
libbinder_ndk \
libbase
@@ -215,6 +221,7 @@ LOCAL_HEADER_LIBRARIES += libgralloc_headers
LOCAL_CFLAGS := -DHLOG_CODE=0
LOCAL_CFLAGS += -DLOG_TAG=\"hwcomposer\"
+LOCAL_CFLAGS += -DSOC_VERSION=$(soc_ver)
ifeq ($(BOARD_USES_HWC_SERVICES),true)
LOCAL_CFLAGS += -DUSES_HWC_SERVICES
@@ -230,13 +237,14 @@ LOCAL_C_INCLUDES += \
$(TOP)/hardware/google/graphics/common/libhwc2.1/libvirtualdisplay \
$(TOP)/hardware/google/graphics/common/libhwc2.1/libhwchelper \
$(TOP)/hardware/google/graphics/common/libhwc2.1/libresource \
- $(TOP)/hardware/google/graphics/$(TARGET_BOARD_PLATFORM)/libhwc2.1 \
- $(TOP)/hardware/google/graphics/$(TARGET_BOARD_PLATFORM)/libhwc2.1/libmaindisplay \
- $(TOP)/hardware/google/graphics/$(TARGET_BOARD_PLATFORM)/libhwc2.1/libexternaldisplay \
- $(TOP)/hardware/google/graphics/$(TARGET_BOARD_PLATFORM)/libhwc2.1/libvirtualdisplay \
- $(TOP)/hardware/google/graphics/$(TARGET_BOARD_PLATFORM)/libhwc2.1/libresource \
- $(TOP)/hardware/google/graphics/$(TARGET_BOARD_PLATFORM)/libhwc2.1/libdevice \
- $(TOP)/hardware/google/graphics/$(TARGET_BOARD_PLATFORM)/libhwc2.1/libresource \
+ $(TOP)/hardware/google/graphics/$(soc_ver)/libhwc2.1 \
+ $(TOP)/hardware/google/graphics/$(soc_ver)/libhwc2.1/libmaindisplay \
+ $(TOP)/hardware/google/graphics/$(soc_ver)/libhwc2.1/libexternaldisplay \
+ $(TOP)/hardware/google/graphics/$(soc_ver)/libhwc2.1/libvirtualdisplay \
+ $(TOP)/hardware/google/graphics/$(soc_ver)/libhwc2.1/libresource \
+ $(TOP)/hardware/google/graphics/$(soc_ver)/libhwc2.1/libdevice \
+ $(TOP)/hardware/google/graphics/$(soc_ver)/libhwc2.1/libresource \
+ $(TOP)/hardware/google/graphics/$(soc_ver)/include \
$(TOP)/hardware/google/graphics/common/libhwc2.1/libhwcService \
$(TOP)/hardware/google/graphics/common/libhwc2.1/libdisplayinterface
diff --git a/libhwc2.1/ExynosHWC.cpp b/libhwc2.1/ExynosHWC.cpp
index 0a8b412..8b3d9a4 100644
--- a/libhwc2.1/ExynosHWC.cpp
+++ b/libhwc2.1/ExynosHWC.cpp
@@ -32,6 +32,7 @@
class ExynosHWCService;
using namespace android;
+using namespace SOC_VERSION;
uint32_t hwcApiVersion(const hwc_composer_device_1_t* hwc) {
uint32_t hwcVersion = hwc->common.version;
diff --git a/libhwc2.1/libdevice/ExynosDevice.cpp b/libhwc2.1/libdevice/ExynosDevice.cpp
index b32e250..a2308f6 100644
--- a/libhwc2.1/libdevice/ExynosDevice.cpp
+++ b/libhwc2.1/libdevice/ExynosDevice.cpp
@@ -30,6 +30,7 @@
#include "VendorGraphicBuffer.h"
using namespace vendor::graphics;
+using namespace SOC_VERSION;
/**
* ExynosDevice implementation
@@ -440,6 +441,11 @@ int32_t ExynosDevice::registerCallback (
callbackFunc(callbackData, getDisplayId(it->mType, it->mIndex),
HWC2_CONNECTION_CONNECTED);
}
+ } else {
+ // unregistering callback can be used as a sign of ComposerClient's death
+ for (auto it : mDisplays) {
+ it->cleanupAfterClientDeath();
+ }
}
}
@@ -1006,6 +1012,11 @@ bool ExynosDevice::isLbeSupported() {
return mLbeSupported;
}
+bool ExynosDevice::isColorCalibratedByDevice() {
+ ExynosDisplay *display = getDisplay(getDisplayId(HWC_DISPLAY_PRIMARY, 0));
+ return display->isColorCalibratedByDevice();
+}
+
void ExynosDevice::setLbeState(LbeState state) {
if (mLbeSupported) {
ExynosDisplay *primary_display = getDisplay(getDisplayId(HWC_DISPLAY_PRIMARY, 0));
@@ -1048,3 +1059,27 @@ bool ExynosDevice::getLhbmState() {
}
return false;
}
+
+int ExynosDevice::setMinIdleRefreshRate(const int fps) {
+ ExynosDisplay *display = getDisplay(getDisplayId(HWC_DISPLAY_PRIMARY, 0));
+ if (display) {
+ return display->setMinIdleRefreshRate(fps);
+ }
+ return BAD_VALUE;
+}
+
+int ExynosDevice::setRefreshRateThrottle(const int delayMs) {
+ if (delayMs < 0) {
+ ALOGE("%s fail: delayMs(%d) is less than 0", __func__, delayMs);
+ return BAD_VALUE;
+ }
+
+ ExynosDisplay *display = getDisplay(getDisplayId(HWC_DISPLAY_PRIMARY, 0));
+ if (display) {
+ return display->setRefreshRateThrottleNanos(
+ std::chrono::duration_cast<std::chrono::nanoseconds>(
+ std::chrono::milliseconds(delayMs))
+ .count());
+ }
+ return BAD_VALUE;
+}
diff --git a/libhwc2.1/libdevice/ExynosDevice.h b/libhwc2.1/libdevice/ExynosDevice.h
index 51b7e30..5c4fd6a 100644
--- a/libhwc2.1/libdevice/ExynosDevice.h
+++ b/libhwc2.1/libdevice/ExynosDevice.h
@@ -332,6 +332,10 @@ class ExynosDevice {
bool isLhbmSupported();
int32_t setLhbmState(bool enabled);
bool getLhbmState();
+ int setMinIdleRefreshRate(const int fps);
+ int setRefreshRateThrottle(const int delayMs);
+
+ bool isColorCalibratedByDevice();
public:
void enterToTUI() { mIsInTUI = true; };
diff --git a/libhwc2.1/libdevice/ExynosDisplay.cpp b/libhwc2.1/libdevice/ExynosDisplay.cpp
index 2eaa5d0..7aa6a47 100644
--- a/libhwc2.1/libdevice/ExynosDisplay.cpp
+++ b/libhwc2.1/libdevice/ExynosDisplay.cpp
@@ -61,13 +61,27 @@ ExynosDisplay::PowerHalHintWorker::PowerHalHintWorker()
mPrevRefreshRate(0),
mPendingPrevRefreshRate(0),
mIdleHintIsEnabled(false),
+ mForceUpdateIdleHint(false),
mIdleHintDeadlineTime(0),
mIdleHintSupportIsChecked(false),
mIdleHintIsSupported(false),
mPowerModeState(HWC2_POWER_MODE_OFF),
mVsyncPeriod(16666666),
- mPowerHalExtAidl(nullptr) {
- InitWorker();
+ mPowerHalExtAidl(nullptr),
+ mDeathRecipient(AIBinder_DeathRecipient_new(BinderDiedCallback)) {}
+
+ExynosDisplay::PowerHalHintWorker::~PowerHalHintWorker() {
+ Exit();
+}
+
+int ExynosDisplay::PowerHalHintWorker::Init() {
+ return InitWorker();
+}
+
+void ExynosDisplay::PowerHalHintWorker::BinderDiedCallback(void *cookie) {
+ ALOGE("PowerHal is died");
+ auto powerHint = reinterpret_cast<PowerHalHintWorker *>(cookie);
+ powerHint->forceUpdateHints();
}
int32_t ExynosDisplay::PowerHalHintWorker::connectPowerHalExt() {
@@ -78,6 +92,7 @@ int32_t ExynosDisplay::PowerHalHintWorker::connectPowerHalExt() {
const std::string kInstance = std::string(IPower::descriptor) + "/default";
ndk::SpAIBinder pwBinder = ndk::SpAIBinder(AServiceManager_getService(kInstance.c_str()));
ndk::SpAIBinder pwExtBinder;
+
AIBinder_getExtension(pwBinder.get(), pwExtBinder.getR());
mPowerHalExtAidl = IPowerExt::fromBinder(pwExtBinder);
if (!mPowerHalExtAidl) {
@@ -85,6 +100,9 @@ int32_t ExynosDisplay::PowerHalHintWorker::connectPowerHalExt() {
return -EINVAL;
}
+ AIBinder_linkToDeath(pwExtBinder.get(), mDeathRecipient.get(), reinterpret_cast<void *>(this));
+
+ forceUpdateHints();
ALOGI("connect power HAL extension successfully");
return NO_ERROR;
}
@@ -140,6 +158,7 @@ int32_t ExynosDisplay::PowerHalHintWorker::sendPowerHalExtHint(const std::string
}
return -EINVAL;
}
+
return NO_ERROR;
}
@@ -266,16 +285,17 @@ int32_t ExynosDisplay::PowerHalHintWorker::checkIdleHintSupport(void) {
return ret;
}
-int32_t ExynosDisplay::PowerHalHintWorker::updateIdleHint(uint64_t deadlineTime) {
+int32_t ExynosDisplay::PowerHalHintWorker::updateIdleHint(int64_t deadlineTime, bool forceUpdate) {
int32_t ret = checkIdleHintSupport();
if (ret != NO_ERROR) {
return ret;
}
- bool enableIdleHint = (deadlineTime < systemTime(SYSTEM_TIME_MONOTONIC));
+ bool enableIdleHint =
+ (deadlineTime < systemTime(SYSTEM_TIME_MONOTONIC) && CC_LIKELY(deadlineTime > 0));
ATRACE_INT("HWCIdleHintTimer:", enableIdleHint);
- if (mIdleHintIsEnabled != enableIdleHint) {
+ if (mIdleHintIsEnabled != enableIdleHint || forceUpdate) {
ret = sendPowerHalExtHint("DISPLAY_IDLE", enableIdleHint);
if (ret == NO_ERROR) {
mIdleHintIsEnabled = enableIdleHint;
@@ -284,6 +304,19 @@ int32_t ExynosDisplay::PowerHalHintWorker::updateIdleHint(uint64_t deadlineTime)
return ret;
}
+void ExynosDisplay::PowerHalHintWorker::forceUpdateHints(void) {
+ Lock();
+ mPrevRefreshRate = 0;
+ mNeedUpdateRefreshRateHint = true;
+ if (mIdleHintSupportIsChecked && mIdleHintIsSupported) {
+ mForceUpdateIdleHint = true;
+ }
+
+ Unlock();
+
+ Signal();
+}
+
void ExynosDisplay::PowerHalHintWorker::signalRefreshRate(hwc2_power_mode_t powerMode,
uint32_t vsyncPeriod) {
Lock();
@@ -310,19 +343,28 @@ void ExynosDisplay::PowerHalHintWorker::signalIdle() {
Signal();
}
+bool ExynosDisplay::PowerHalHintWorker::needUpdateIdleHintLocked(int64_t &timeout) {
+ if (!mIdleHintIsSupported) {
+ return false;
+ }
+
+ int64_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
+ bool shouldEnableIdleHint =
+ (mIdleHintDeadlineTime < currentTime) && CC_LIKELY(mIdleHintDeadlineTime > 0);
+ if (mIdleHintIsEnabled != shouldEnableIdleHint || mForceUpdateIdleHint) {
+ return true;
+ }
+
+ timeout = mIdleHintDeadlineTime - currentTime;
+ return false;
+}
+
void ExynosDisplay::PowerHalHintWorker::Routine() {
Lock();
int ret = 0;
- if (!mNeedUpdateRefreshRateHint) {
- if (!mIdleHintIsSupported || mIdleHintIsEnabled) {
- ret = WaitForSignalOrExitLocked();
- } else {
- uint64_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
- if (mIdleHintDeadlineTime > currentTime) {
- uint64_t timeout = mIdleHintDeadlineTime - currentTime;
- ret = WaitForSignalOrExitLocked(timeout);
- }
- }
+ int64_t timeout = -1;
+ if (!mNeedUpdateRefreshRateHint && !needUpdateIdleHintLocked(timeout)) {
+ ret = WaitForSignalOrExitLocked(timeout);
}
if (ret == -EINTR) {
@@ -331,7 +373,7 @@ void ExynosDisplay::PowerHalHintWorker::Routine() {
}
bool needUpdateRefreshRateHint = mNeedUpdateRefreshRateHint;
- uint64_t deadlineTime = mIdleHintDeadlineTime;
+ int64_t deadlineTime = mIdleHintDeadlineTime;
hwc2_power_mode_t powerMode = mPowerModeState;
uint32_t vsyncPeriod = mVsyncPeriod;
@@ -343,9 +385,12 @@ void ExynosDisplay::PowerHalHintWorker::Routine() {
* errors.
*/
mNeedUpdateRefreshRateHint = false;
+
+ bool forceUpdateIdleHint = mForceUpdateIdleHint;
+ mForceUpdateIdleHint = false;
Unlock();
- updateIdleHint(deadlineTime);
+ updateIdleHint(deadlineTime, forceUpdateIdleHint);
if (needUpdateRefreshRateHint) {
int32_t rc = updateRefreshRateHintInternal(powerMode, vsyncPeriod);
@@ -655,6 +700,8 @@ ExynosDisplay::ExynosDisplay(uint32_t index, ExynosDevice *device)
mLowFpsLayerInfo.initializeInfos();
+ mPowerHalHint.Init();
+
mUseDpu = true;
mBrightnessState.reset();
@@ -2923,6 +2970,11 @@ int32_t ExynosDisplay::canSkipValidate() {
return SKIP_ERR_SKIP_STATIC_CHANGED;
}
+ if (mClientCompositionInfo.mHasCompositionLayer &&
+ mClientCompositionInfo.mTargetBuffer == NULL) {
+ return SKIP_ERR_INVALID_CLIENT_TARGET_BUFFER;
+ }
+
/*
* If there is hwc2_layer_request_t
* validateDisplay() can't be skipped
@@ -3535,9 +3587,17 @@ int32_t ExynosDisplay::getConfigAppliedTime(const uint64_t desiredTime,
{
uint32_t transientDuration = mDisplayInterface->getConfigChangeDuration();
appliedTime = actualChangeTime;
- while (desiredTime > appliedTime) {
- DISPLAY_LOGD(eDebugDisplayConfig, "desired time(%" PRId64 ") > applied time(%" PRId64 ")", desiredTime, appliedTime);;
- appliedTime += mVsyncPeriod;
+
+ if (desiredTime > appliedTime) {
+ const int64_t originalAppliedTime = appliedTime;
+ const int64_t diff = desiredTime - appliedTime;
+ appliedTime += (diff + mVsyncPeriod - 1) / mVsyncPeriod * mVsyncPeriod;
+ DISPLAY_LOGD(eDebugDisplayConfig,
+ "desired time(%" PRId64 "), applied time(%" PRId64 "->%" PRId64 ")",
+ desiredTime, originalAppliedTime, appliedTime);
+ } else {
+ DISPLAY_LOGD(eDebugDisplayConfig, "desired time(%" PRId64 "), applied time(%" PRId64 ")",
+ desiredTime, appliedTime);
}
refreshTime = appliedTime - (transientDuration * mVsyncPeriod);
@@ -3545,6 +3605,26 @@ int32_t ExynosDisplay::getConfigAppliedTime(const uint64_t desiredTime,
return NO_ERROR;
}
+void ExynosDisplay::calculateTimeline(
+ hwc2_config_t config, hwc_vsync_period_change_constraints_t *vsyncPeriodChangeConstraints,
+ hwc_vsync_period_change_timeline_t *outTimeline) {
+ int64_t actualChangeTime = 0;
+ /* actualChangeTime includes transient duration */
+ mDisplayInterface->getVsyncAppliedTime(config, &actualChangeTime);
+
+ outTimeline->refreshRequired = true;
+ getConfigAppliedTime(mVsyncPeriodChangeConstraints.desiredTimeNanos, actualChangeTime,
+ outTimeline->newVsyncAppliedTimeNanos, outTimeline->refreshTimeNanos);
+
+ DISPLAY_LOGD(eDebugDisplayConfig,
+ "requested config : %d(%d)->%d(%d), "
+ "desired %" PRId64 ", newVsyncAppliedTimeNanos : %" PRId64 "",
+ mActiveConfig, mDisplayConfigs[mActiveConfig].vsyncPeriod, config,
+ mDisplayConfigs[config].vsyncPeriod,
+ mVsyncPeriodChangeConstraints.desiredTimeNanos,
+ outTimeline->newVsyncAppliedTimeNanos);
+}
+
int32_t ExynosDisplay::setActiveConfigWithConstraints(hwc2_config_t config,
hwc_vsync_period_change_constraints_t* vsyncPeriodChangeConstraints,
hwc_vsync_period_change_timeline_t* outTimeline)
@@ -3552,11 +3632,11 @@ int32_t ExynosDisplay::setActiveConfigWithConstraints(hwc2_config_t config,
ATRACE_CALL();
Mutex::Autolock lock(mDisplayMutex);
- DISPLAY_LOGD(eDebugDisplayConfig, "%s:: config(%d), seamless(%d), "
- "desiredTime(%" PRId64, ")",
- config,
- vsyncPeriodChangeConstraints->seamlessRequired,
- vsyncPeriodChangeConstraints->desiredTimeNanos);
+ DISPLAY_LOGD(eDebugDisplayConfig,
+ "config(%d), seamless(%d), "
+ "desiredTime(%" PRId64 ")",
+ config, vsyncPeriodChangeConstraints->seamlessRequired,
+ vsyncPeriodChangeConstraints->desiredTimeNanos);
if (isBadConfig(config)) return HWC2_ERROR_BAD_CONFIG;
@@ -3588,22 +3668,7 @@ int32_t ExynosDisplay::setActiveConfigWithConstraints(hwc2_config_t config,
mVsyncPeriodChangeConstraints = *vsyncPeriodChangeConstraints;
mDesiredConfig = config;
- int64_t actualChangeTime = 0;
- /* actualChangeTime includes transient duration */
- mDisplayInterface->getVsyncAppliedTime(config, &actualChangeTime);
-
- outTimeline->refreshRequired = true;
- getConfigAppliedTime(mVsyncPeriodChangeConstraints.desiredTimeNanos,
- actualChangeTime,
- outTimeline->newVsyncAppliedTimeNanos,
- outTimeline->refreshTimeNanos);
-
- DISPLAY_LOGD(eDebugDisplayConfig, "requested config : %d(%d)->%d(%d), "
- "desired %" PRId64 ", newVsyncAppliedTimeNanos : %" PRId64 "",
- mActiveConfig, mDisplayConfigs[mActiveConfig].vsyncPeriod,
- config, mDisplayConfigs[config].vsyncPeriod,
- mVsyncPeriodChangeConstraints.desiredTimeNanos,
- outTimeline->newVsyncAppliedTimeNanos);
+ calculateTimeline(config, vsyncPeriodChangeConstraints, outTimeline);
/* mActiveConfig should be changed immediately for internal status */
mActiveConfig = config;
@@ -3696,9 +3761,23 @@ int32_t ExynosDisplay::updateInternalDisplayConfigVariables(
return NO_ERROR;
}
-void ExynosDisplay::updateBtsVsyncPeriod(uint32_t vsync_period, bool forceUpdate) {
- if (forceUpdate || vsync_period < mBtsVsyncPeriod) {
- mBtsVsyncPeriod = vsync_period;
+void ExynosDisplay::updateBtsVsyncPeriod(uint32_t vsyncPeriod, bool forceUpdate) {
+ if (vsyncPeriod < mBtsVsyncPeriod) {
+ mBtsVsyncPeriod = vsyncPeriod;
+
+ if (mType == HWC_DISPLAY_PRIMARY) {
+ uint32_t btsRefreshRate = getBtsRefreshRate();
+
+ for (size_t i = 0; i < mLayers.size(); i++) {
+ if (!mLayers[i]->checkDownscaleCap(btsRefreshRate)) {
+ setGeometryChanged(GEOMETRY_DEVICE_CONFIG_CHANGED);
+ break;
+ }
+ }
+ }
+ } else if (forceUpdate) {
+ /* TODO: add check for resource can re-assign to Device */
+ mBtsVsyncPeriod = vsyncPeriod;
}
}
@@ -3716,8 +3795,8 @@ void ExynosDisplay::updateRefreshRateHint() {
int32_t ExynosDisplay::resetConfigRequestStateLocked() {
mVsyncPeriod = getDisplayVsyncPeriodFromConfig(mActiveConfig);
updateBtsVsyncPeriod(mVsyncPeriod, true);
- DISPLAY_LOGD(eDebugDisplayConfig,"Update mVsyncPeriod %d",
- mVsyncPeriod);
+ DISPLAY_LOGD(eDebugDisplayConfig, "Update mVsyncPeriod %d by mActiveConfig(%d)", mVsyncPeriod,
+ mActiveConfig);
updateRefreshRateHint();
@@ -3728,6 +3807,7 @@ int32_t ExynosDisplay::resetConfigRequestStateLocked() {
DISPLAY_LOGD(eDebugDisplayInterfaceConfig, "%s: Change mConfigRequestState (%d) to NONE",
__func__, mConfigRequestState);
mConfigRequestState = hwc_request_state_t::SET_CONFIG_STATE_NONE;
+ updateAppliedActiveConfig(mActiveConfig, systemTime(SYSTEM_TIME_MONOTONIC));
}
return NO_ERROR;
}
@@ -3821,8 +3901,10 @@ int32_t ExynosDisplay::doDisplayConfigPostProcess(ExynosDevice *dev)
if (actualChangeTime >= mVsyncPeriodChangeConstraints.desiredTimeNanos) {
DISPLAY_LOGD(eDebugDisplayConfig, "Request setActiveConfig");
needSetActiveConfig = true;
+ ATRACE_INT("Pending ActiveConfig", 0);
} else {
DISPLAY_LOGD(eDebugDisplayConfig, "setActiveConfig still pending");
+ ATRACE_INT("Pending ActiveConfig", mDesiredConfig);
}
if (needSetActiveConfig) {
@@ -5338,3 +5420,12 @@ void ExynosDisplay::updateBrightnessState() {
ALOGW("Failed to update brighntess");
}
}
+
+void ExynosDisplay::cleanupAfterClientDeath() {
+ // Invalidate the client target buffer because it will be freed when the client dies
+ mClientCompositionInfo.mTargetBuffer = NULL;
+ // Invalidate the skip static flag so that we have to get a new target buffer first
+ // before we can skip the static layers
+ mClientCompositionInfo.mSkipStaticInitFlag = false;
+ mClientCompositionInfo.mSkipFlag = false;
+}
diff --git a/libhwc2.1/libdevice/ExynosDisplay.h b/libhwc2.1/libdevice/ExynosDisplay.h
index c892aab..90bbb76 100644
--- a/libhwc2.1/libdevice/ExynosDisplay.h
+++ b/libhwc2.1/libdevice/ExynosDisplay.h
@@ -520,7 +520,7 @@ class ExynosDisplay {
ExynosLowFpsLayerInfo mLowFpsLayerInfo;
// HDR capabilities
- std::vector<android_hdr_t> mHdrTypes;
+ std::vector<int32_t> mHdrTypes;
float mMaxLuminance;
float mMaxAverageLuminance;
float mMinLuminance;
@@ -726,7 +726,8 @@ class ExynosDisplay {
SKIP_ERR_HAS_REQUEST,
SKIP_ERR_DISP_NOT_CONNECTED,
SKIP_ERR_DISP_NOT_POWER_ON,
- SKIP_ERR_FORCE_VALIDATE
+ SKIP_ERR_FORCE_VALIDATE,
+ SKIP_ERR_INVALID_CLIENT_TARGET_BUFFER
};
virtual int32_t canSkipValidate();
@@ -874,7 +875,7 @@ class ExynosDisplay {
* HWC2_ERROR_BAD_PARAMETER when the brightness is invalid, or
* HWC2_ERROR_NO_RESOURCES when the brightness cannot be applied.
*/
- int32_t setDisplayBrightness(float brightness);
+ virtual int32_t setDisplayBrightness(float brightness);
/* getDisplayConnectionType(..., outType)
* Descriptor: HWC2_FUNCTION_GET_DISPLAY_CONNECTION_TYPE
@@ -1056,7 +1057,7 @@ class ExynosDisplay {
int32_t getConfigAppliedTime(const uint64_t desiredTime,
const uint64_t actualChangeTime,
int64_t &appliedTime, int64_t &refreshTime);
- void updateBtsVsyncPeriod(uint32_t vsync_period, bool forceUpdate = false);
+ void updateBtsVsyncPeriod(uint32_t vsyncPeriod, bool forceUpdate = false);
uint32_t getBtsRefreshRate() const;
/* TODO : TBD */
@@ -1070,7 +1071,7 @@ class ExynosDisplay {
/* This function is called by ExynosDisplayInterface class to set acquire fence*/
int32_t setReadbackBufferAcqFence(int32_t acqFence);
- void dump(String8& result);
+ virtual void dump(String8& result);
virtual int32_t startPostProcessing();
@@ -1112,6 +1113,7 @@ class ExynosDisplay {
virtual int32_t updateColorConversionInfo() { return NO_ERROR; };
virtual int32_t updatePresentColorConversionInfo() { return NO_ERROR; };
virtual bool checkRrCompensationEnabled() { return false; };
+ virtual bool isColorCalibratedByDevice() { return false; };
virtual int32_t getColorAdjustedDbv(uint32_t &) { return NO_ERROR; }
virtual int32_t SetCurrentPanelGammaSource(const displaycolor::DisplayType /* type */,
const PanelGammaSource& /* source */) {
@@ -1141,6 +1143,8 @@ class ExynosDisplay {
}
void requestEnhancedHbm(bool on) { mBrightnessState.enhanced_hbm = on; };
+ void cleanupAfterClientDeath();
+
protected:
virtual bool getHDRException(ExynosLayer *layer);
virtual int32_t getActiveConfigInternal(hwc2_config_t* outConfig);
@@ -1169,18 +1173,19 @@ class ExynosDisplay {
mDevice->invalidate();
}
+ virtual int setMinIdleRefreshRate(const int __unused fps) { return NO_ERROR; }
+ virtual int setRefreshRateThrottleNanos(const int64_t __unused delayNanos) {
+ return NO_ERROR;
+ }
+
+ virtual void updateAppliedActiveConfig(const hwc2_config_t /*newConfig*/,
+ const int64_t /*ts*/) {}
+
private:
bool skipStaticLayerChanged(ExynosCompositionInfo& compositionInfo);
bool skipSignalIdleForVideoLayer();
- inline uint32_t getDisplayVsyncPeriodFromConfig(hwc2_config_t config) {
- int32_t vsync_period;
- getDisplayAttribute(config, HWC2_ATTRIBUTE_VSYNC_PERIOD, &vsync_period);
- assert(vsync_period > 0);
- return static_cast<uint32_t>(vsync_period);
- }
-
/// minimum possible dim rate in the case hbm peak is 1000 nits and norml
// display brightness is 2 nits
static constexpr float kGhbmMinDimRatio = 0.002;
@@ -1200,6 +1205,8 @@ class ExynosDisplay {
class PowerHalHintWorker : public Worker {
public:
PowerHalHintWorker();
+ virtual ~PowerHalHintWorker();
+ int Init();
void signalRefreshRate(hwc2_power_mode_t powerMode, uint32_t vsyncPeriod);
void signalIdle();
@@ -1208,6 +1215,7 @@ class ExynosDisplay {
void Routine() override;
private:
+ static void BinderDiedCallback(void*);
int32_t connectPowerHalExt();
int32_t checkPowerHalExtHintSupport(const std::string& mode);
int32_t sendPowerHalExtHint(const std::string& mode, bool enabled);
@@ -1216,9 +1224,11 @@ class ExynosDisplay {
int32_t updateRefreshRateHintInternal(hwc2_power_mode_t powerMode,
uint32_t vsyncPeriod);
int32_t sendRefreshRateHint(int refreshRate, bool enabled);
+ void forceUpdateHints();
int32_t checkIdleHintSupport();
- int32_t updateIdleHint(uint64_t deadlineTime);
+ int32_t updateIdleHint(int64_t deadlineTime, bool forceUpdate);
+ bool needUpdateIdleHintLocked(int64_t& timeout) REQUIRES(mutex_);
bool mNeedUpdateRefreshRateHint;
@@ -1232,7 +1242,8 @@ class ExynosDisplay {
std::map<int, bool> mRefreshRateHintSupportMap;
bool mIdleHintIsEnabled;
- uint64_t mIdleHintDeadlineTime;
+ bool mForceUpdateIdleHint;
+ int64_t mIdleHintDeadlineTime;
// whether idle hint support is checked
bool mIdleHintSupportIsChecked;
@@ -1246,9 +1257,23 @@ class ExynosDisplay {
// for power HAL extension hints
std::shared_ptr<aidl::google::hardware::power::extension::pixel::IPowerExt>
mPowerHalExtAidl;
+ ndk::ScopedAIBinder_DeathRecipient mDeathRecipient;
};
PowerHalHintWorker mPowerHalHint;
+
+ protected:
+ inline uint32_t getDisplayVsyncPeriodFromConfig(hwc2_config_t config) {
+ int32_t vsync_period;
+ getDisplayAttribute(config, HWC2_ATTRIBUTE_VSYNC_PERIOD, &vsync_period);
+ assert(vsync_period > 0);
+ return static_cast<uint32_t>(vsync_period);
+ }
+
+ virtual void calculateTimeline(
+ hwc2_config_t config,
+ hwc_vsync_period_change_constraints_t* vsyncPeriodChangeConstraints,
+ hwc_vsync_period_change_timeline_t* outTimeline);
};
#endif //_EXYNOSDISPLAY_H
diff --git a/libhwc2.1/libdevice/ExynosLayer.cpp b/libhwc2.1/libdevice/ExynosLayer.cpp
index 826074b..8a86ef0 100644
--- a/libhwc2.1/libdevice/ExynosLayer.cpp
+++ b/libhwc2.1/libdevice/ExynosLayer.cpp
@@ -891,6 +891,28 @@ int32_t ExynosLayer::resetAssignedResource()
return ret;
}
+bool ExynosLayer::checkDownscaleCap(uint32_t bts_refresh_rate)
+{
+ if (mOtfMPP == nullptr) return true;
+
+ exynos_image src_img;
+ exynos_image dst_img;
+
+ setSrcExynosImage(&src_img);
+ setDstExynosImage(&dst_img);
+
+ const bool isPerpendicular = !!(src_img.transform & HAL_TRANSFORM_ROT_90);
+ const uint32_t srcWidth = isPerpendicular ? src_img.h : src_img.w;
+ const uint32_t srcHeight = isPerpendicular ? src_img.w : src_img.h;
+ const bool scaleDown = (srcWidth > dst_img.w || srcHeight > dst_img.h);
+
+ if (!scaleDown) return true;
+
+ const float resolution = float(src_img.w) * float(src_img.h) * bts_refresh_rate / 1000;
+
+ return mOtfMPP->checkDownscaleCap(resolution, float(dst_img.h) / float(mDisplay->mYres));
+}
+
void ExynosLayer::setSrcAcquireFence() {
if (mAcquireFence == -1 && mPrevAcquireFence != -1) {
mAcquireFence = hwcCheckFenceDebug(mDisplay, FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_LAYER,
diff --git a/libhwc2.1/libdevice/ExynosLayer.h b/libhwc2.1/libdevice/ExynosLayer.h
index 994d045..8ea71e1 100644
--- a/libhwc2.1/libdevice/ExynosLayer.h
+++ b/libhwc2.1/libdevice/ExynosLayer.h
@@ -421,6 +421,7 @@ class ExynosLayer : public ExynosMPPSource {
int32_t setSrcExynosImage(exynos_image *src_img);
int32_t setDstExynosImage(exynos_image *dst_img);
int32_t resetAssignedResource();
+ bool checkDownscaleCap(uint32_t btsRefreshRate);
void setSrcAcquireFence();
diff --git a/libhwc2.1/libdisplayinterface/ExynosDeviceDrmInterface.cpp b/libhwc2.1/libdisplayinterface/ExynosDeviceDrmInterface.cpp
index 21b7f92..c844b72 100644
--- a/libhwc2.1/libdisplayinterface/ExynosDeviceDrmInterface.cpp
+++ b/libhwc2.1/libdisplayinterface/ExynosDeviceDrmInterface.cpp
@@ -63,6 +63,8 @@ static void set_dpp_ch_restriction(struct hwc_dpp_ch_restriction &hwc_dpp_restri
hwc_dpp_restriction.restriction.scale_up = 1;
}
+using namespace SOC_VERSION;
+
ExynosDeviceDrmInterface::ExynosDeviceDrmInterface(ExynosDevice *exynosDevice)
{
mType = INTERFACE_TYPE_DRM;
diff --git a/libhwc2.1/libdisplayinterface/ExynosDisplayDrmInterface.cpp b/libhwc2.1/libdisplayinterface/ExynosDisplayDrmInterface.cpp
index 997b3e1..a38fb2c 100644
--- a/libhwc2.1/libdisplayinterface/ExynosDisplayDrmInterface.cpp
+++ b/libhwc2.1/libdisplayinterface/ExynosDisplayDrmInterface.cpp
@@ -405,6 +405,11 @@ ExynosDisplayDrmInterface::~ExynosDisplayDrmInterface()
mDrmDevice->DestroyPropertyBlob(mDesiredModeState.old_blob_id);
if (mPartialRegionState.blob_id)
mDrmDevice->DestroyPropertyBlob(mPartialRegionState.blob_id);
+ if (mHbmSvDimmingThreadRunning) {
+ mHbmSvDimmingThreadRunning = false;
+ mHbmSvDimmingCond.signal();
+ mDimmingThread.join();
+ }
}
void ExynosDisplayDrmInterface::init(ExynosDisplay *exynosDisplay)
@@ -642,24 +647,21 @@ void ExynosDisplayDrmInterface::Callback(
}
ExynosDevice *exynosDevice = mExynosDisplay->mDevice;
- exynosDevice->compareVsyncPeriod();
- if (exynosDevice->mVsyncDisplayId == mExynosDisplay->mDisplayId) {
- auto vsync_2_4CallbackInfo =
- exynosDevice->mCallbackInfos[HWC2_CALLBACK_VSYNC_2_4];
- if (vsync_2_4CallbackInfo.funcPointer && vsync_2_4CallbackInfo.callbackData) {
- ((HWC2_PFN_VSYNC_2_4)vsync_2_4CallbackInfo.funcPointer)(
- vsync_2_4CallbackInfo.callbackData,
- mExynosDisplay->mDisplayId,
- timestamp, mExynosDisplay->mVsyncPeriod);
- ATRACE_INT(vsyncPeriodTag, static_cast<int32_t>(mExynosDisplay->mVsyncPeriod));
- return;
- }
-
- auto vsyncCallbackInfo = exynosDevice->mCallbackInfos[HWC2_CALLBACK_VSYNC];
- if (vsyncCallbackInfo.funcPointer && vsyncCallbackInfo.callbackData)
- ((HWC2_PFN_VSYNC)vsyncCallbackInfo.funcPointer)(vsyncCallbackInfo.callbackData,
- mExynosDisplay->mDisplayId, timestamp);
+ auto vsync_2_4CallbackInfo =
+ exynosDevice->mCallbackInfos[HWC2_CALLBACK_VSYNC_2_4];
+ if (vsync_2_4CallbackInfo.funcPointer && vsync_2_4CallbackInfo.callbackData) {
+ ((HWC2_PFN_VSYNC_2_4)vsync_2_4CallbackInfo.funcPointer)(
+ vsync_2_4CallbackInfo.callbackData,
+ mExynosDisplay->mDisplayId,
+ timestamp, mExynosDisplay->mVsyncPeriod);
+ ATRACE_INT(vsyncPeriodTag, static_cast<int32_t>(mExynosDisplay->mVsyncPeriod));
+ return;
}
+
+ auto vsyncCallbackInfo = exynosDevice->mCallbackInfos[HWC2_CALLBACK_VSYNC];
+ if (vsyncCallbackInfo.funcPointer && vsyncCallbackInfo.callbackData)
+ ((HWC2_PFN_VSYNC)vsyncCallbackInfo.funcPointer)(vsyncCallbackInfo.callbackData,
+ mExynosDisplay->mDisplayId, timestamp);
}
bool ExynosDisplayDrmInterface::ExynosVsyncCallback::Callback(
@@ -993,7 +995,8 @@ int32_t ExynosDisplayDrmInterface::setColorMode(int32_t mode)
int32_t ExynosDisplayDrmInterface::setActiveConfigWithConstraints(
hwc2_config_t config, bool test)
{
- ALOGD("%s:: %s config(%d)", __func__, mExynosDisplay->mDisplayName.string(), config);
+ ALOGD("%s:: %s config(%d) test(%d)", __func__, mExynosDisplay->mDisplayName.string(), config,
+ test);
auto mode = std::find_if(mDrmConnector->modes().begin(), mDrmConnector->modes().end(),
[config](DrmMode const &m) { return m.id() == config;});
if (mode == mDrmConnector->modes().end()) {
@@ -1092,6 +1095,7 @@ int32_t ExynosDisplayDrmInterface::setActiveConfig(hwc2_config_t config) {
return HWC2_ERROR_BAD_CONFIG;
}
+ mExynosDisplay->updateAppliedActiveConfig(config, systemTime(SYSTEM_TIME_MONOTONIC));
if (!setActiveDrmMode(*mode)) {
ALOGI("%s:: %s config(%d)", __func__, mExynosDisplay->mDisplayName.string(), config);
} else {
@@ -1214,6 +1218,9 @@ int32_t ExynosDisplayDrmInterface::updateHdrCapabilities()
std::tie(typeBit, ret) = prop_hdr_formats.GetEnumValueWithName("HDR10");
if ((ret == 0) && (hdr_formats & (1 << typeBit))) {
mExynosDisplay->mHdrTypes.push_back(HAL_HDR_HDR10);
+ if (mExynosDisplay->mDevice->mResourceManager->hasHDR10PlusMPP()) {
+ mExynosDisplay->mHdrTypes.push_back(HAL_HDR_HDR10_PLUS);
+ }
HDEBUGLOGD(eDebugHWC, "%s: supported hdr types : %d",
mExynosDisplay->mDisplayName.string(), HAL_HDR_HDR10);
}
@@ -1654,6 +1661,7 @@ int32_t ExynosDisplayDrmInterface::deliverWinConfigData()
if (mBrightnessCtrl.LhbmOn.is_dirty()) {
auto dbv = mBrightnessLevel.get();
+ auto old_dbv = dbv;
if (mBrightnessCtrl.LhbmOn.get()) {
uint32_t dbv_adj = 0;
if (mExynosDisplay->getColorAdjustedDbv(dbv_adj)) {
@@ -1668,7 +1676,7 @@ int32_t ExynosDisplayDrmInterface::deliverWinConfigData()
}
}
- if ((ret = drmReq.atomicAddProperty(mDrmConnector->id(),
+ if ((dbv != old_dbv) && (ret = drmReq.atomicAddProperty(mDrmConnector->id(),
mDrmConnector->brightness_level(), dbv)) < 0) {
HWC_LOGE(mExynosDisplay, "%s: Fail to set brightness_level property", __func__);
}
@@ -1754,6 +1762,10 @@ int32_t ExynosDisplayDrmInterface::deliverWinConfigData()
return ret;
}
drmReq.restorePset();
+ if (out_fences[mDrmCrtc->pipe()] >= 0) {
+ fence_close((int)out_fences[mDrmCrtc->pipe()], mExynosDisplay, FENCE_TYPE_RETIRE,
+ FENCE_IP_DPP);
+ }
if ((ret = updateColorSettings(drmReq, dqeEnable)) != 0) {
HWC_LOGE(mExynosDisplay, "failed to update color settings, ret=%d", ret);
return ret;
@@ -2319,6 +2331,43 @@ int32_t ExynosDisplayDrmInterface::getDisplayIdentificationData(
return HWC2_ERROR_NONE;
}
+void ExynosDisplayDrmInterface::checkHbmSvDimming() {
+ status_t ret = 0;
+ uint32_t wait = 0;
+
+ while (mHbmSvDimmingThreadRunning) {
+ if (wait == 0) {
+ Mutex::Autolock lock(mHbmSvDimmingMutex);
+ ret = mHbmSvDimmingCond.wait(mHbmSvDimmingMutex);
+ } else {
+ Mutex::Autolock lock(mHbmSvDimmingMutex);
+ ret = mHbmSvDimmingCond.waitRelative(mHbmSvDimmingMutex, us2ns(wait));
+ }
+ // When the time out, it turns dimming off(hbm sv dimming done).
+ // Then, it waits the next hbm sv dimming event.
+ if (ret == TIMED_OUT) {
+ ret = 0;
+ wait = 0;
+ ALOGI("checking the dimming status");
+ endHbmSvDimming();
+ } else {
+ wait = mHbmDimmingTimeUs;
+ }
+ }
+}
+
+void ExynosDisplayDrmInterface::endHbmSvDimming() {
+ Mutex::Autolock lock(mBrightnessUpdateMutex);
+ if (!mHbmSvDimming) return;
+ mHbmSvDimming = false;
+ mBrightnessCtrl.DimmingOn.store(false);
+
+ if (mDimmingOnFd && mBrightnessCtrl.DimmingOn.is_dirty()) {
+ writeFileNode(mDimmingOnFd, mBrightnessCtrl.DimmingOn.get());
+ mBrightnessCtrl.DimmingOn.clear_dirty();
+ }
+}
+
void ExynosDisplayDrmInterface::getBrightnessInterfaceSupport() {
if (mDrmConnector->brightness_cap().id() == 0) {
ALOGD("the brightness_cap is not supported");
@@ -2365,17 +2414,25 @@ void ExynosDisplayDrmInterface::getBrightnessInterfaceSupport() {
mBrightnessState.reset();
mBrightnessCtrl.reset();
- mHbmModeFd = fopen(kHbmModeFileNode, "w+");
- if (mHbmModeFd == NULL) ALOGE("%s open failed! %s", kHbmModeFileNode, strerror(errno));
+ String8 node_name;
+ node_name.appendFormat(kHbmModeFileNode, mExynosDisplay->mIndex);
+ mHbmModeFd = fopen(node_name.string(), "w+");
+ if (mHbmModeFd == NULL) ALOGE("%s open failed! %s", node_name.string(), strerror(errno));
- mDimmingOnFd = fopen(kDimmingOnFileNode, "w+");
- if (mDimmingOnFd == NULL) ALOGE("%s open failed! %s", kDimmingOnFileNode, strerror(errno));
+ node_name.clear();
+ node_name.appendFormat(kDimmingOnFileNode, mExynosDisplay->mIndex);
+ mDimmingOnFd = fopen(node_name.string(), "w+");
+ if (mDimmingOnFd == NULL) ALOGE("%s open failed! %s", node_name.string(), strerror(errno));
if (mDimmingOnFd) {
mBrightnessDimmingUsage = static_cast<BrightnessDimmingUsage>(
property_get_int32("vendor.display.brightness.dimming.usage", 0));
mHbmDimmingTimeUs =
property_get_int32("vendor.display.brightness.dimming.hbm_time", kHbmDimmingTimeUs);
+ if (mBrightnessDimmingUsage == BrightnessDimmingUsage::HBM) {
+ mHbmSvDimmingThreadRunning = true;
+ mDimmingThread = std::thread(&ExynosDisplayDrmInterface::checkHbmSvDimming, this);
+ }
}
return;
@@ -2489,21 +2546,14 @@ void ExynosDisplayDrmInterface::setupBrightnessConfig() {
case BrightnessDimmingUsage::HBM:
if ((static_cast<uint32_t>(hbm_mode) > static_cast<uint32_t>(HbmMode::OFF)) !=
mBrightnessCtrl.HbmMode.get() > static_cast<uint32_t>(HbmMode::OFF)) {
- gettimeofday(&mHbmDimmingStart, NULL);
if (brightness_state.hdr_full_screen != mBrightnessState.hdr_full_screen) {
mBrightnessState.hdr_full_screen = brightness_state.hdr_full_screen;
} else {
mHbmSvDimming = true;
+ mHbmSvDimmingCond.signal();
}
}
-
- if (mHbmSvDimming) {
- struct timeval curr_time;
- gettimeofday(&curr_time, NULL);
- curr_time.tv_usec += (curr_time.tv_sec - mHbmDimmingStart.tv_sec) * 1000000;
- long duration = curr_time.tv_usec - mHbmDimmingStart.tv_usec;
- if (duration > mHbmDimmingTimeUs) mHbmSvDimming = false;
- }
+ if (mBrightnessLevel.get() == 0) mHbmSvDimming = false;
dimming_on = dimming_on && (mHbmSvDimming);
break;
case BrightnessDimmingUsage::NONE:
diff --git a/libhwc2.1/libdisplayinterface/ExynosDisplayDrmInterface.h b/libhwc2.1/libdisplayinterface/ExynosDisplayDrmInterface.h
index 62ab701..5345329 100644
--- a/libhwc2.1/libdisplayinterface/ExynosDisplayDrmInterface.h
+++ b/libhwc2.1/libdisplayinterface/ExynosDisplayDrmInterface.h
@@ -429,6 +429,8 @@ class ExynosDisplayDrmInterface :
void getBrightnessInterfaceSupport();
void setupBrightnessConfig();
void parseHbmModeEnums(const DrmProperty &property);
+ void checkHbmSvDimming();
+ void endHbmSvDimming();
FILE *mHbmModeFd;
FILE *mDimmingOnFd;
bool mBrightntessIntfSupported = false;
@@ -491,9 +493,9 @@ class ExynosDisplayDrmInterface :
// TODO: hbm in dual display is not supported. It should support it in
// the furture.
static constexpr const char *kHbmModeFileNode =
- "/sys/class/backlight/panel0-backlight/hbm_mode";
+ "/sys/class/backlight/panel%d-backlight/hbm_mode";
static constexpr const char *kDimmingOnFileNode =
- "/sys/class/backlight/panel0-backlight/dimming_on";
+ "/sys/class/backlight/panel%d-backlight/dimming_on";
static constexpr int32_t kHbmDimmingTimeUs = 5000000;
@@ -514,7 +516,10 @@ class ExynosDisplayDrmInterface :
BrightnessDimmingUsage mBrightnessDimmingUsage;
bool mHbmSvDimming;
int32_t mHbmDimmingTimeUs;
- struct timeval mHbmDimmingStart;
+ std::thread mDimmingThread;
+ bool mHbmSvDimmingThreadRunning;
+ Condition mHbmSvDimmingCond;
+ Mutex mHbmSvDimmingMutex;
private:
int32_t getDisplayFakeEdid(uint8_t &outPort, uint32_t &outDataSize, uint8_t *outData);
diff --git a/libhwc2.1/libdrmresource/drm/drmeventlistener.cpp b/libhwc2.1/libdrmresource/drm/drmeventlistener.cpp
index 20193ab..d847c2b 100644
--- a/libhwc2.1/libdrmresource/drm/drmeventlistener.cpp
+++ b/libhwc2.1/libdrmresource/drm/drmeventlistener.cpp
@@ -36,6 +36,10 @@ DrmEventListener::DrmEventListener(DrmDevice *drm)
: Worker("drm-event-listener", HAL_PRIORITY_URGENT_DISPLAY), drm_(drm) {
}
+DrmEventListener::~DrmEventListener() {
+ Exit();
+}
+
int DrmEventListener::Init() {
struct epoll_event ev;
char buffer[1024];
diff --git a/libhwc2.1/libdrmresource/drm/vsyncworker.cpp b/libhwc2.1/libdrmresource/drm/vsyncworker.cpp
index 97dc0dd..d2b4a02 100644
--- a/libhwc2.1/libdrmresource/drm/vsyncworker.cpp
+++ b/libhwc2.1/libdrmresource/drm/vsyncworker.cpp
@@ -49,6 +49,7 @@ VSyncWorker::VSyncWorker()
}
VSyncWorker::~VSyncWorker() {
+ Exit();
}
int VSyncWorker::Init(DrmDevice *drm, int display) {
diff --git a/libhwc2.1/libdrmresource/include/drmeventlistener.h b/libhwc2.1/libdrmresource/include/drmeventlistener.h
index 541d074..dbecadb 100644
--- a/libhwc2.1/libdrmresource/include/drmeventlistener.h
+++ b/libhwc2.1/libdrmresource/include/drmeventlistener.h
@@ -51,8 +51,7 @@ class DrmEventListener : public Worker {
static const uint32_t maxFds = 3;
public:
DrmEventListener(DrmDevice *drm);
- virtual ~DrmEventListener() {
- }
+ virtual ~DrmEventListener();
int Init();
diff --git a/libhwc2.1/libdrmresource/utils/worker.cpp b/libhwc2.1/libdrmresource/utils/worker.cpp
index 3b24312..4dbd0d9 100644
--- a/libhwc2.1/libdrmresource/utils/worker.cpp
+++ b/libhwc2.1/libdrmresource/utils/worker.cpp
@@ -26,7 +26,6 @@ Worker::Worker(const char *name, int priority, bool is_rt)
}
Worker::~Worker() {
- Exit();
}
int Worker::InitWorker() {
diff --git a/libhwc2.1/libexternaldisplay/ExynosExternalDisplay.cpp b/libhwc2.1/libexternaldisplay/ExynosExternalDisplay.cpp
index be61d68..8ba3020 100644
--- a/libhwc2.1/libexternaldisplay/ExynosExternalDisplay.cpp
+++ b/libhwc2.1/libexternaldisplay/ExynosExternalDisplay.cpp
@@ -28,6 +28,8 @@
#define SKIP_FRAME_COUNT 3
extern struct exynos_hwc_control exynosHWCControl;
+using namespace SOC_VERSION;
+
ExynosExternalDisplay::ExynosExternalDisplay(uint32_t index, ExynosDevice *device)
: ExynosDisplay(index, device)
{
diff --git a/libhwc2.1/libhwcService/ExynosHWCService.cpp b/libhwc2.1/libhwcService/ExynosHWCService.cpp
index da936a8..33d42ea 100644
--- a/libhwc2.1/libhwcService/ExynosHWCService.cpp
+++ b/libhwc2.1/libhwcService/ExynosHWCService.cpp
@@ -13,10 +13,14 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
#include "ExynosHWCService.h"
-#include "ExynosVirtualDisplayModule.h"
-#include "ExynosVirtualDisplay.h"
+
+#include <chrono>
+
#include "ExynosExternalDisplay.h"
+#include "ExynosVirtualDisplay.h"
+#include "ExynosVirtualDisplayModule.h"
#define HWC_SERVICE_DEBUG 0
namespace android {
@@ -261,6 +265,18 @@ void ExynosHWCService::setScaleDownRatio(uint32_t physicalType,
mHWCCtx->device->invalidate();
}
+void ExynosHWCService::setLbeCtrl(uint32_t display_id, uint32_t state, uint32_t lux) {
+ ALOGD("%s:: display_id(%d), state(%d), lux(%d)", __func__, display_id, state, lux);
+ if (mHWCCtx) {
+ auto display = mHWCCtx->device->getDisplay(display_id);
+
+ if (display != nullptr) {
+ display->setLbeState(static_cast<LbeState>(state));
+ display->setLbeAmbientLight(lux);
+ }
+ }
+}
+
void ExynosHWCService::setHWCDebug(int debug)
{
ALOGD_IF(HWC_SERVICE_DEBUG, "%s, debug %d", __func__, debug);
@@ -428,4 +444,31 @@ int32_t ExynosHWCService::setDisplayLhbm(int32_t display_id, uint32_t on) {
return -EINVAL;
}
+int32_t ExynosHWCService::setMinIdleRefreshRate(uint32_t display_id, int32_t fps) {
+ ALOGD("ExynosHWCService::%s() display_id(%u) fps(%d)", __func__, display_id, fps);
+
+ auto display = mHWCCtx->device->getDisplay(display_id);
+
+ if (display != nullptr) {
+ return display->setMinIdleRefreshRate(fps);
+ }
+
+ return -EINVAL;
+}
+
+int32_t ExynosHWCService::setRefreshRateThrottle(uint32_t display_id, int32_t delayMs) {
+ ALOGD("ExynosHWCService::%s() display_id(%u) delayMs(%d)", __func__, display_id, delayMs);
+
+ auto display = mHWCCtx->device->getDisplay(display_id);
+
+ if (display != nullptr) {
+ return display->setRefreshRateThrottleNanos(
+ std::chrono::duration_cast<std::chrono::nanoseconds>(
+ std::chrono::milliseconds(delayMs))
+ .count());
+ }
+
+ return -EINVAL;
+}
+
} //namespace android
diff --git a/libhwc2.1/libhwcService/ExynosHWCService.h b/libhwc2.1/libhwcService/ExynosHWCService.h
index 25f4516..cb47655 100644
--- a/libhwc2.1/libhwcService/ExynosHWCService.h
+++ b/libhwc2.1/libhwcService/ExynosHWCService.h
@@ -66,6 +66,7 @@ public:
virtual int setHWCCtl(uint32_t display, uint32_t ctrl, int32_t val);
virtual int setDDIScaler(uint32_t width, uint32_t height);
+ virtual void setLbeCtrl(uint32_t display_id, uint32_t state, uint32_t lux) override;
#if 0
void setPSRExitCallback(void (*callback)(exynos_hwc_composer_device_1_t *));
virtual void notifyPSRExit();
@@ -75,6 +76,9 @@ public:
virtual int32_t setDisplayBrightness(int32_t display_id, float brightness);
virtual int32_t setDisplayLhbm(int32_t display_id, uint32_t on);
+ virtual int32_t setMinIdleRefreshRate(uint32_t display_id, int32_t fps);
+ virtual int32_t setRefreshRateThrottle(uint32_t display_id, int32_t delayMs);
+
private:
friend class Singleton<ExynosHWCService>;
ExynosHWCService();
diff --git a/libhwc2.1/libhwcService/IExynosHWC.cpp b/libhwc2.1/libhwcService/IExynosHWC.cpp
index 62f52fe..51a2fba 100644
--- a/libhwc2.1/libhwcService/IExynosHWC.cpp
+++ b/libhwc2.1/libhwcService/IExynosHWC.cpp
@@ -61,6 +61,9 @@ enum {
SET_PANEL_GAMMA_TABLE_SOURCE = 1001,
SET_DISPLAY_BRIGHTNESS = 1002,
SET_DISPLAY_LHBM = 1003,
+ SET_LBE_CTRL = 1004,
+ SET_MIN_IDLE_REFRESH_RATE = 1005,
+ SET_REFRESH_RATE_THROTTLE = 1006,
};
class BpExynosHWCService : public BpInterface<IExynosHWCService> {
@@ -295,6 +298,16 @@ public:
ALOGE("SET_SCALE_DOWN_RATIO transact error(%d)", result);
}
+ virtual void setLbeCtrl(uint32_t display_id, uint32_t state, uint32_t lux) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IExynosHWCService::getInterfaceDescriptor());
+ data.writeInt32(display_id);
+ data.writeInt32(state);
+ data.writeInt32(lux);
+ int result = remote()->transact(SET_LBE_CTRL, data, &reply);
+ if (result != NO_ERROR) ALOGE("SET_LBE_CTRL transact error(%d)", result);
+ }
+
virtual void setHWCDebug(int debug)
{
Parcel data, reply;
@@ -402,6 +415,26 @@ public:
if (result) ALOGE("SET_DISPLAY_LHBM transact error(%d)", result);
return result;
}
+
+ virtual int32_t setMinIdleRefreshRate(uint32_t display_id, int32_t fps) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IExynosHWCService::getInterfaceDescriptor());
+ data.writeUint32(display_id);
+ data.writeInt32(fps);
+ int result = remote()->transact(SET_MIN_IDLE_REFRESH_RATE, data, &reply);
+ if (result) ALOGE("SET_MIN_IDLE_REFRESH_RATE transact error(%d)", result);
+ return result;
+ }
+
+ virtual int32_t setRefreshRateThrottle(uint32_t display_id, int32_t delay_ms) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IExynosHWCService::getInterfaceDescriptor());
+ data.writeUint32(display_id);
+ data.writeInt32(delay_ms);
+ int result = remote()->transact(SET_REFRESH_RATE_THROTTLE, data, &reply);
+ if (result) ALOGE("SET_REFRESH_RATE_THROTTLE transact error(%d)", result);
+ return result;
+ }
};
IMPLEMENT_META_INTERFACE(ExynosHWCService, "android.hal.ExynosHWCService");
@@ -647,6 +680,29 @@ status_t BnExynosHWCService::onTransact(
return NO_ERROR;
} break;
+ case SET_LBE_CTRL: {
+ CHECK_INTERFACE(IExynosHWCService, data, reply);
+ uint32_t display_id = data.readInt32();
+ uint32_t state = data.readInt32();
+ uint32_t lux = data.readInt32();
+ setLbeCtrl(display_id, state, lux);
+ return NO_ERROR;
+ } break;
+
+ case SET_MIN_IDLE_REFRESH_RATE: {
+ CHECK_INTERFACE(IExynosHWCService, data, reply);
+ uint32_t display_id = data.readUint32();
+ int32_t fps = data.readInt32();
+ return setMinIdleRefreshRate(display_id, fps);
+ } break;
+
+ case SET_REFRESH_RATE_THROTTLE: {
+ CHECK_INTERFACE(IExynosHWCService, data, reply);
+ uint32_t display_id = data.readUint32();
+ int32_t delay_ms = data.readInt32();
+ return setRefreshRateThrottle(display_id, delay_ms);
+ } break;
+
default:
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/libhwc2.1/libhwcService/IExynosHWC.h b/libhwc2.1/libhwcService/IExynosHWC.h
index 30af1c3..a410008 100644
--- a/libhwc2.1/libhwcService/IExynosHWC.h
+++ b/libhwc2.1/libhwcService/IExynosHWC.h
@@ -66,11 +66,14 @@ public:
virtual int32_t setDisplayDeviceMode(int32_t display_id, int32_t mode) = 0;
virtual int32_t setPanelGammaTableSource(int32_t display_id, int32_t type, int32_t source) = 0;
+ virtual void setLbeCtrl(uint32_t display_id, uint32_t state, uint32_t lux) = 0;
/*
virtual void notifyPSRExit() = 0;
*/
virtual int32_t setDisplayBrightness(int32_t display_id, float brightness) = 0;
virtual int32_t setDisplayLhbm(int32_t display_id, uint32_t on) = 0;
+ virtual int32_t setMinIdleRefreshRate(uint32_t display_id, int32_t refresh_rate) = 0;
+ virtual int32_t setRefreshRateThrottle(uint32_t display_id, int32_t throttle) = 0;
};
/* Native Interface */
diff --git a/libhwc2.1/libmaindisplay/ExynosPrimaryDisplay.cpp b/libhwc2.1/libmaindisplay/ExynosPrimaryDisplay.cpp
index c69388c..26727f2 100644
--- a/libhwc2.1/libmaindisplay/ExynosPrimaryDisplay.cpp
+++ b/libhwc2.1/libmaindisplay/ExynosPrimaryDisplay.cpp
@@ -19,6 +19,10 @@
#include "ExynosPrimaryDisplay.h"
+#include <linux/fb.h>
+#include <poll.h>
+
+#include <chrono>
#include <fstream>
#include "ExynosDevice.h"
@@ -28,10 +32,10 @@
#include "ExynosHWCDebug.h"
#include "ExynosHWCHelper.h"
-#include <linux/fb.h>
-
extern struct exynos_hwc_control exynosHWCControl;
+using namespace SOC_VERSION;
+
static const std::map<const DisplayType, const std::string> panelSysfsPath =
{{DisplayType::DISPLAY_PRIMARY, "/sys/devices/platform/exynos-drm/primary-panel/"},
{DisplayType::DISPLAY_SECONDARY, "/sys/devices/platform/exynos-drm/secondary-panel/"}};
@@ -65,8 +69,11 @@ static std::string loadPanelGammaCalibration(const std::string &file) {
}
ExynosPrimaryDisplay::ExynosPrimaryDisplay(uint32_t index, ExynosDevice *device)
- : ExynosDisplay(index, device)
-{
+ : ExynosDisplay(index, device),
+ mMinIdleRefreshRate(0),
+ mRefreshRateDelayNanos(0),
+ mLastRefreshRateAppliedNanos(0),
+ mAppliedActiveConfig(0) {
// TODO : Hard coded here
mNumMaxPriorityAllowed = 5;
@@ -94,9 +101,28 @@ ExynosPrimaryDisplay::ExynosPrimaryDisplay(uint32_t index, ExynosDevice *device)
mResolutionInfo.nDSCXSliceSize[2] = 720;
mResolutionInfo.nPanelType[2] = PANEL_LEGACY;
-#if defined(MAX_BRIGHTNESS_NODE_BASE) && defined(BRIGHTNESS_NODE_BASE)
- FILE *maxBrightnessFd = fopen(MAX_BRIGHTNESS_NODE_BASE, "r");
- ALOGI("Trying %s open for get max brightness", MAX_BRIGHTNESS_NODE_BASE);
+ static_assert(sizeof(BRIGHTNESS_NODE_0_BASE) != 0 && sizeof(MAX_BRIGHTNESS_NODE_0_BASE) != 0,
+ "Invalid brightness 0 node");
+ static_assert(sizeof(BRIGHTNESS_NODE_1_BASE) != 0 && sizeof(MAX_BRIGHTNESS_NODE_1_BASE) != 0,
+ "Invalid brightness 1 node");
+ std::string brightness_node;
+ std::string max_brightness_node;
+ switch (mIndex) {
+ case 0:
+ max_brightness_node = MAX_BRIGHTNESS_NODE_0_BASE;
+ brightness_node = BRIGHTNESS_NODE_0_BASE;
+ break;
+ case 1:
+ max_brightness_node = MAX_BRIGHTNESS_NODE_1_BASE;
+ brightness_node = BRIGHTNESS_NODE_1_BASE;
+ break;
+ default:
+ ALOGE("assgin brightness node failed (mIndex: %d)", mIndex);
+ break;
+ }
+
+ FILE *maxBrightnessFd = fopen(max_brightness_node.c_str(), "r");
+ ALOGI("Trying %s open for get max brightness", max_brightness_node.c_str());
if (maxBrightnessFd != NULL) {
char val[MAX_BRIGHTNESS_LEN] = {0};
@@ -105,11 +131,11 @@ ExynosPrimaryDisplay::ExynosPrimaryDisplay(uint32_t index, ExynosDevice *device)
mMaxBrightness = atoi(val);
ALOGI("Max brightness : %d", mMaxBrightness);
- mBrightnessFd = fopen(BRIGHTNESS_NODE_BASE, "w+");
- ALOGI("Trying %s open for brightness control", BRIGHTNESS_NODE_BASE);
+ mBrightnessFd = fopen(brightness_node.c_str(), "w+");
+ ALOGI("Trying %s open for brightness control", brightness_node.c_str());
if (mBrightnessFd == NULL)
- ALOGE("%s open failed! %s", BRIGHTNESS_NODE_BASE, strerror(errno));
+ ALOGE("%s open failed! %s", brightness_node.c_str(), strerror(errno));
} else {
ALOGE("Max brightness read failed (size: %zu)", size);
@@ -122,7 +148,6 @@ ExynosPrimaryDisplay::ExynosPrimaryDisplay(uint32_t index, ExynosDevice *device)
} else {
ALOGE("Brightness node is not opened");
}
-#endif
#if defined EARLY_WAKUP_NODE_BASE
mEarlyWakeupFd = fopen(EARLY_WAKUP_NODE_BASE, "w");
@@ -228,7 +253,7 @@ int32_t ExynosPrimaryDisplay::applyPendingConfig() {
int32_t ExynosPrimaryDisplay::setPowerOn() {
ATRACE_CALL();
-
+ updateAppliedActiveConfig(0, 0);
int ret = applyPendingConfig();
if (mPowerModeState == HWC2_POWER_MODE_OFF) {
@@ -441,12 +466,36 @@ int32_t ExynosPrimaryDisplay::SetCurrentPanelGammaSource(const DisplayType type,
return HWC2_ERROR_NONE;
}
+// Both setDisplayBrightness and setLhbmState will change display brightness and
+// each goes different path (sysfs and drm/kms)
+//
+// case 1: setDisplayBrightness happens before setLhbmState
+// Don't care. brightness change by setLhbmState will happen after brightness
+// change by setDisplayBrightness.
+//
+// case 2: setLhbmState happends before setDisplayBrightness
+// block current call until brightness change by setLhbmState completes.
+int32_t ExynosPrimaryDisplay::setDisplayBrightness(float brightness) {
+ if (mLhbmStatusPending) {
+ // This could be done in setLhbmState and block this call on
+ // mLhbmStatusPending. But it may increase the time for UDFPS path
+ checkLhbmMode(mLastRequestedLhbm, ms2ns(200));
+ mLhbmStatusPending = false;
+ }
+ return ExynosDisplay::setDisplayBrightness(brightness);
+}
+
int32_t ExynosPrimaryDisplay::setLhbmState(bool enabled) {
+ ATRACE_CALL();
requestLhbm(enabled);
ALOGI("setLhbmState =%d", enabled);
std::unique_lock<std::mutex> lk(lhbm_mutex_);
mLhbmChanged = false;
+
+ mLhbmStatusPending = true;
+ mLastRequestedLhbm = enabled;
+
if (!lhbm_cond_.wait_for(lk, std::chrono::milliseconds(1000),
[this] { return mLhbmChanged; })) {
ALOGI("setLhbmState =%d timeout !", enabled);
@@ -458,6 +507,75 @@ int32_t ExynosPrimaryDisplay::setLhbmState(bool enabled) {
}
}
+// return immediately if it's already in the status. Otherwise poll the status
+bool ExynosPrimaryDisplay::checkLhbmMode(bool status, nsecs_t timeoutNs) {
+ ATRACE_CALL();
+ char buf[1];
+ auto startTime = systemTime(SYSTEM_TIME_MONOTONIC);
+
+ UniqueFd fd = open(kLocalHbmModeFileNode, O_RDONLY);
+
+ int size = read(fd.get(), buf, 1);
+ if (size != 1) {
+ ALOGE("%s failed to read from %s", __func__, kLocalHbmModeFileNode);
+ return false;
+ }
+
+ if (buf[0] == (status ? '1' : '0')) {
+ return true;
+ }
+
+ struct pollfd pfds[1];
+ int ret = EINVAL;
+
+ pfds[0].fd = fd.get();
+ pfds[0].events = POLLPRI;
+ while (true) {
+ auto currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
+ // int64_t for nsecs_t
+ auto remainTimeNs = timeoutNs - (currentTime - startTime);
+ if (remainTimeNs <= 0) {
+ remainTimeNs = ms2ns(1);
+ }
+ int pollRet = poll(&pfds[0], 1, ns2ms(remainTimeNs));
+ if (pollRet == 0) {
+ ALOGW("%s poll timeout", __func__);
+ // time out
+ ret = ETIMEDOUT;
+ break;
+ } else if (pollRet > 0) {
+ if (!(pfds[0].revents & POLLPRI)) {
+ continue;
+ }
+
+ lseek(fd.get(), 0, SEEK_SET);
+ size = read(fd.get(), buf, 1);
+ if (size == 1) {
+ if (buf[0] == (status ? '1' : '0')) {
+ ret = 0;
+ } else {
+ ALOGE("%s status %d expected %d after notified", __func__, buf[0], status);
+ ret = EINVAL;
+ }
+ } else {
+ ret = EIO;
+ ALOGE("%s failed to read after notified %d", __func__, errno);
+ }
+ break;
+ } else {
+ if (errno == EAGAIN || errno == EINTR) {
+ continue;
+ }
+
+ ALOGE("%s poll failed %d", __func__, errno);
+ ret = errno;
+ break;
+ }
+ };
+
+ return ret == NO_ERROR;
+}
+
bool ExynosPrimaryDisplay::getLhbmState() {
return mLhbmOn;
}
@@ -474,3 +592,115 @@ void ExynosPrimaryDisplay::setWakeupDisplay() {
writeFileNode(mWakeupDispFd, 1);
}
}
+
+int ExynosPrimaryDisplay::setMinIdleRefreshRate(const int fps) {
+ mMinIdleRefreshRate = fps;
+
+ const std::string path = getPanelSysfsPath(DisplayType::DISPLAY_PRIMARY) + "min_vrefresh";
+ std::ofstream ofs(path);
+ if (!ofs.is_open()) {
+ ALOGW("Unable to open node '%s', error = %s", path.c_str(), strerror(errno));
+ return errno;
+ } else {
+ ofs << mMinIdleRefreshRate;
+ ofs.close();
+ ALOGI("ExynosPrimaryDisplay::%s() writes min_vrefresh(%d) to the sysfs node", __func__,
+ fps);
+ }
+ return NO_ERROR;
+}
+
+int ExynosPrimaryDisplay::setRefreshRateThrottleNanos(const int64_t delayNanos) {
+ mRefreshRateDelayNanos = delayNanos;
+
+ const int32_t refreshRateDelayMs = std::chrono::duration_cast<std::chrono::milliseconds>(
+ std::chrono::nanoseconds(mRefreshRateDelayNanos))
+ .count();
+ const std::string path = getPanelSysfsPath(DisplayType::DISPLAY_PRIMARY) + "idle_delay_ms";
+ std::ofstream ofs(path);
+ if (!ofs.is_open()) {
+ ALOGW("Unable to open node '%s', error = %s", path.c_str(), strerror(errno));
+ return errno;
+ } else {
+ ofs << refreshRateDelayMs;
+ ofs.close();
+ ALOGI("ExynosPrimaryDisplay::%s() writes idle_delay_ms(%d) to the sysfs node", __func__,
+ refreshRateDelayMs);
+ }
+
+ return NO_ERROR;
+}
+
+void ExynosPrimaryDisplay::dump(String8 &result) {
+ ExynosDisplay::dump(result);
+ result.appendFormat("Min idle refresh rate: %d\n", mMinIdleRefreshRate);
+ result.appendFormat("Refresh rate delay: %" PRId64 "ns\n\n", mRefreshRateDelayNanos);
+}
+
+void ExynosPrimaryDisplay::calculateTimeline(
+ hwc2_config_t config, hwc_vsync_period_change_constraints_t *vsyncPeriodChangeConstraints,
+ hwc_vsync_period_change_timeline_t *outTimeline) {
+ int64_t desiredUpdateTime = vsyncPeriodChangeConstraints->desiredTimeNanos;
+ const int64_t origDesiredUpdateTime = desiredUpdateTime;
+ const int64_t threshold = mRefreshRateDelayNanos;
+ int64_t lastUpdateDelta = 0;
+ int64_t actualChangeTime = 0;
+ bool isDelayed = false;
+
+ /* actualChangeTime includes transient duration */
+ mDisplayInterface->getVsyncAppliedTime(config, &actualChangeTime);
+
+ outTimeline->refreshRequired = true;
+
+ /* when refresh rate is from high to low */
+ if (threshold != 0 && mLastRefreshRateAppliedNanos != 0 &&
+ mDisplayConfigs[mActiveConfig].vsyncPeriod < mDisplayConfigs[config].vsyncPeriod) {
+ lastUpdateDelta = desiredUpdateTime - mLastRefreshRateAppliedNanos;
+ if (lastUpdateDelta < threshold) {
+ /* in this case, the active config change needs to be delayed */
+ isDelayed = true;
+ desiredUpdateTime += threshold - lastUpdateDelta;
+ }
+ }
+ mVsyncPeriodChangeConstraints.desiredTimeNanos = desiredUpdateTime;
+
+ getConfigAppliedTime(mVsyncPeriodChangeConstraints.desiredTimeNanos, actualChangeTime,
+ outTimeline->newVsyncAppliedTimeNanos, outTimeline->refreshTimeNanos);
+
+ if (isDelayed) {
+ DISPLAY_LOGD(eDebugDisplayConfig,
+ "requested config : %d(%d)->%d(%d) is delayed! "
+ "delta %" PRId64 ", delay %" PRId64 ", threshold %" PRId64 ", "
+ "desired %" PRId64 "->%" PRId64 ", newVsyncAppliedTimeNanos : %" PRId64
+ ", refreshTimeNanos:%" PRId64,
+ mActiveConfig, mDisplayConfigs[mActiveConfig].vsyncPeriod, config,
+ mDisplayConfigs[config].vsyncPeriod, lastUpdateDelta,
+ threshold - lastUpdateDelta, threshold, origDesiredUpdateTime,
+ mVsyncPeriodChangeConstraints.desiredTimeNanos,
+ outTimeline->newVsyncAppliedTimeNanos, outTimeline->refreshTimeNanos);
+ } else {
+ DISPLAY_LOGD(eDebugDisplayConfig,
+ "requested config : %d(%d)->%d(%d), "
+ "lastUpdateDelta %" PRId64 ", threshold %" PRId64 ", "
+ "desired %" PRId64 ", newVsyncAppliedTimeNanos : %" PRId64 "",
+ mActiveConfig, mDisplayConfigs[mActiveConfig].vsyncPeriod, config,
+ mDisplayConfigs[config].vsyncPeriod, lastUpdateDelta, threshold,
+ mVsyncPeriodChangeConstraints.desiredTimeNanos,
+ outTimeline->newVsyncAppliedTimeNanos);
+ }
+}
+
+void ExynosPrimaryDisplay::updateAppliedActiveConfig(const hwc2_config_t newConfig,
+ const int64_t ts) {
+ if (mAppliedActiveConfig == 0 ||
+ getDisplayVsyncPeriodFromConfig(mAppliedActiveConfig) !=
+ getDisplayVsyncPeriodFromConfig(newConfig)) {
+ DISPLAY_LOGD(eDebugDisplayConfig,
+ "%s mAppliedActiveConfig(%d->%d), mLastRefreshRateAppliedNanos(%" PRIu64
+ " -> %" PRIu64 ")",
+ __func__, mAppliedActiveConfig, newConfig, mLastRefreshRateAppliedNanos, ts);
+ mLastRefreshRateAppliedNanos = ts;
+ }
+
+ mAppliedActiveConfig = newConfig;
+}
diff --git a/libhwc2.1/libmaindisplay/ExynosPrimaryDisplay.h b/libhwc2.1/libmaindisplay/ExynosPrimaryDisplay.h
index c49ae5e..e8b76ec 100644
--- a/libhwc2.1/libmaindisplay/ExynosPrimaryDisplay.h
+++ b/libhwc2.1/libmaindisplay/ExynosPrimaryDisplay.h
@@ -20,8 +20,6 @@
#include "../libdevice/ExynosDisplay.h"
-class ExynosMPPModule;
-
class ExynosPrimaryDisplay : public ExynosDisplay {
public:
/* Methods */
@@ -37,6 +35,8 @@ class ExynosPrimaryDisplay : public ExynosDisplay {
virtual bool isLhbmSupported() { return mLhbmFd ? true : false; }
virtual int32_t setLhbmState(bool enabled);
+ virtual int32_t setDisplayBrightness(float brightness) override;
+
virtual bool getLhbmState();
virtual void notifyLhbmState(bool enabled);
virtual void setWakeupDisplay();
@@ -44,6 +44,12 @@ class ExynosPrimaryDisplay : public ExynosDisplay {
virtual void initDisplayInterface(uint32_t interfaceType);
virtual int32_t doDisplayConfigInternal(hwc2_config_t config) override;
+ virtual int setMinIdleRefreshRate(const int fps) override;
+ virtual int setRefreshRateThrottleNanos(const int64_t delayNs) override;
+ virtual void dump(String8& result) override;
+ virtual void updateAppliedActiveConfig(const hwc2_config_t newConfig,
+ const int64_t ts) override;
+
protected:
/* setPowerMode(int32_t mode)
* Descriptor: HWC2_FUNCTION_SET_POWER_MODE
@@ -66,6 +72,8 @@ class ExynosPrimaryDisplay : public ExynosDisplay {
static constexpr const char* kPanelGammaCalFilePrefix = "gamma_calib_data";
enum PanelGammaSource currentPanelGammaSource = PanelGammaSource::GAMMA_DEFAULT;
+ bool checkLhbmMode(bool status, nsecs_t timoutNs);
+
hwc2_config_t mPendActiveConfig = UINT_MAX;
bool mFirstPowerOn = true;
@@ -81,6 +89,10 @@ class ExynosPrimaryDisplay : public ExynosDisplay {
FILE* mLhbmFd;
bool mLhbmOn;
bool mLhbmChanged;
+
+ std::atomic<bool> mLastRequestedLhbm;
+ std::atomic<bool> mLhbmStatusPending;
+
static constexpr const char *kLocalHbmModeFileNode =
"/sys/class/backlight/panel0-backlight/local_hbm_mode";
std::mutex lhbm_mutex_;
@@ -89,6 +101,14 @@ class ExynosPrimaryDisplay : public ExynosDisplay {
FILE* mWakeupDispFd;
static constexpr const char* kWakeupDispFilePath =
"/sys/devices/platform/1c300000.drmdecon/early_wakeup";
+
+ void calculateTimeline(hwc2_config_t config,
+ hwc_vsync_period_change_constraints_t* vsyncPeriodChangeConstraints,
+ hwc_vsync_period_change_timeline_t* outTimeline) override;
+ int mMinIdleRefreshRate;
+ int64_t mRefreshRateDelayNanos;
+ int64_t mLastRefreshRateAppliedNanos;
+ hwc2_config_t mAppliedActiveConfig;
};
#endif
diff --git a/libhwc2.1/libresource/ExynosResourceManager.cpp b/libhwc2.1/libresource/ExynosResourceManager.cpp
index fed8a3c..502baac 100644
--- a/libhwc2.1/libresource/ExynosResourceManager.cpp
+++ b/libhwc2.1/libresource/ExynosResourceManager.cpp
@@ -85,6 +85,7 @@ feature_support_t feature_table[] =
using namespace android;
using namespace vendor::graphics;
+using namespace SOC_VERSION;
ExynosMPPVector ExynosResourceManager::mOtfMPPs;
ExynosMPPVector ExynosResourceManager::mM2mMPPs;
diff --git a/libhwc2.1/libvirtualdisplay/ExynosVirtualDisplay.h b/libhwc2.1/libvirtualdisplay/ExynosVirtualDisplay.h
index af0c918..9e5daa8 100644
--- a/libhwc2.1/libvirtualdisplay/ExynosVirtualDisplay.h
+++ b/libhwc2.1/libvirtualdisplay/ExynosVirtualDisplay.h
@@ -21,8 +21,6 @@
#define VIRTUAL_DISLAY_SKIP_LAYER 0x00000100
-class ExynosMPPModule;
-
enum WFDState {
DISABLE_WFD,
GOOGLEWFD,
diff --git a/libhwc2.1/pixel-display-default.xml b/libhwc2.1/pixel-display-default.xml
index 1a08386..31c569e 100644
--- a/libhwc2.1/pixel-display-default.xml
+++ b/libhwc2.1/pixel-display-default.xml
@@ -1,7 +1,7 @@
<manifest version="1.0" type="device">
<hal format="aidl">
<name>com.google.hardware.pixel.display</name>
- <version>3</version>
+ <version>4</version>
<fqname>IDisplay/default</fqname>
</hal>
</manifest>
diff --git a/libhwc2.1/pixel-display.cpp b/libhwc2.1/pixel-display.cpp
index b6d0eb3..409cfe0 100644
--- a/libhwc2.1/pixel-display.cpp
+++ b/libhwc2.1/pixel-display.cpp
@@ -23,6 +23,8 @@
#include <sys/types.h>
#include <utils/Errors.h>
+#include "ExynosDisplay.h"
+
extern int32_t load_png_image(const char *filepath, buffer_handle_t buffer);
using ::aidl::com::google::hardware::pixel::display::Display;
@@ -137,9 +139,29 @@ ndk::ScopedAStatus Display::getLhbmState(bool *_aidl_return) {
ndk::ScopedAStatus Display::setCompensationImageHandle(const NativeHandle &native_handle,
const std::string &imageName,
int *_aidl_return) {
- *_aidl_return = readCompensationImage(native_handle, imageName);
+ if (mDevice && mDevice->isColorCalibratedByDevice()) {
+ *_aidl_return = readCompensationImage(native_handle, imageName);
+ } else {
+ *_aidl_return = -1;
+ }
return ndk::ScopedAStatus::ok();
}
+
+ndk::ScopedAStatus Display::setMinIdleRefreshRate(int fps, int *_aidl_return) {
+ if (mDevice) {
+ *_aidl_return = mDevice->setMinIdleRefreshRate(fps);
+ return ndk::ScopedAStatus::ok();
+ }
+ return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+
+ndk::ScopedAStatus Display::setRefreshRateThrottle(int delayMs, int *_aidl_return) {
+ if (mDevice) {
+ *_aidl_return = mDevice->setRefreshRateThrottle(delayMs);
+ return ndk::ScopedAStatus::ok();
+ }
+ return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
} // namespace display
} // namespace pixel
} // namespace hardware
diff --git a/libhwc2.1/pixel-display.h b/libhwc2.1/pixel-display.h
index 7e0d33b..f0fd627 100644
--- a/libhwc2.1/pixel-display.h
+++ b/libhwc2.1/pixel-display.h
@@ -47,6 +47,8 @@ public:
ndk::ScopedAStatus setCompensationImageHandle(const NativeHandle &native_handle,
const std::string &imageName,
int *_aidl_return) override;
+ ndk::ScopedAStatus setMinIdleRefreshRate(int fps, int *_aidl_return) override;
+ ndk::ScopedAStatus setRefreshRateThrottle(int delayMs, int *_aidl_return) override;
private:
ExynosDevice *mDevice = nullptr;