diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2022-06-11 15:44:16 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2022-06-11 15:44:16 +0000 |
commit | 2cb11755c39eb3911e2b0394eaba620db9e2dec4 (patch) | |
tree | 75d231fc860f9ee34ff424d512110267547df67c | |
parent | c8f94098b6bcf8b2cbb0f7b779714e1cacf35d8b (diff) | |
parent | 7324e6459d55ca5714a0e31ae2b85d508387db93 (diff) | |
download | common-android13-frc-art-release.tar.gz |
Snap for 8712302 from 7324e6459d55ca5714a0e31ae2b85d508387db93 to tm-frc-art-releaset_frc_art_330443060android13-frc-art-release
Change-Id: I4981c727462b3bbfd1e0c6bd099704112f2092a9
22 files changed, 445 insertions, 518 deletions
diff --git a/hwc3/Android.mk b/hwc3/Android.mk index a942355..f233aab 100644 --- a/hwc3/Android.mk +++ b/hwc3/Android.mk @@ -35,7 +35,7 @@ LOCAL_SHARED_LIBRARIES := android.hardware.graphics.composer3-V1-ndk \ android.hardware.graphics.composer@2.1-resources \ android.hardware.graphics.composer@2.2-resources \ android.hardware.graphics.composer@2.4 \ - com.google.hardware.pixel.display-V4-ndk \ + com.google.hardware.pixel.display-V6-ndk \ libbase \ libbinder \ libbinder_ndk \ diff --git a/include/displaycolor/displaycolor.h b/include/displaycolor/displaycolor.h index eb96ce0..d9141ff 100644 --- a/include/displaycolor/displaycolor.h +++ b/include/displaycolor/displaycolor.h @@ -34,6 +34,7 @@ using android::hardware::graphics::common::V1_2::PixelFormat; /** * hwc/displaycolor interface history * + * 6.1.0.2022-05-18 Get calibrated serial number. * 6.0.0.2022-02-22 Get whether dimming in linear. * 5.0.0.2022-02-17 Add layer dim ratio. * 4.0.0.2021-12-20 Get pixel format and dataspace of blending stage. @@ -60,7 +61,7 @@ constexpr struct DisplayColorIntfVer { } kInterfaceVersion { 6, - 0, + 1, 0, }; @@ -382,6 +383,13 @@ class IDisplayColorGeneric { hwc::PixelFormat &pixel_format, hwc::Dataspace &dataspace, bool &dimming_linear) const = 0; + + /** + * @brief Get the serial number for the panel used during calibration. + * @param display to get the calibrated serial number. + * @return The calibrated serial number. + */ + virtual const std::string& GetCalibratedSerialNumber(DisplayType display) const = 0; }; extern "C" { diff --git a/libhwc2.1/Android.mk b/libhwc2.1/Android.mk index 7a5e885..1918890 100644 --- a/libhwc2.1/Android.mk +++ b/libhwc2.1/Android.mk @@ -68,7 +68,7 @@ LOCAL_SHARED_LIBRARIES := liblog libcutils libhardware \ android.hardware.power-V2-ndk pixel-power-ext-V1-ndk LOCAL_SHARED_LIBRARIES += android.hardware.graphics.composer3-V1-ndk \ - com.google.hardware.pixel.display-V4-ndk \ + com.google.hardware.pixel.display-V6-ndk \ libbinder_ndk \ libbase \ libpng \ @@ -155,7 +155,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-V4-ndk \ +LOCAL_SHARED_LIBRARIES += com.google.hardware.pixel.display-V6-ndk \ libbinder_ndk \ libbase @@ -216,7 +216,7 @@ LOCAL_SHARED_LIBRARIES := liblog libcutils libutils libexynosdisplay libacryl \ libui LOCAL_SHARED_LIBRARIES += android.hardware.graphics.composer3-V1-ndk \ - com.google.hardware.pixel.display-V4-ndk \ + com.google.hardware.pixel.display-V6-ndk \ libbinder_ndk \ libbase diff --git a/libhwc2.1/ExynosHWCDebug.cpp b/libhwc2.1/ExynosHWCDebug.cpp index 982a54d..bbf676c 100644 --- a/libhwc2.1/ExynosHWCDebug.cpp +++ b/libhwc2.1/ExynosHWCDebug.cpp @@ -50,23 +50,14 @@ int32_t saveErrorLog(const String8 &errString, ExynosDisplay *display) String8 saveString; struct timeval tv; - struct tm* localTime; gettimeofday(&tv, NULL); - localTime = (struct tm*)localtime((time_t*)&tv.tv_sec); if (display != NULL) { - saveString.appendFormat("%02d-%02d %02d:%02d:%02d.%03lu(%lu) %s %" PRIu64 ": %s\n", - localTime->tm_mon+1, localTime->tm_mday, - localTime->tm_hour, localTime->tm_min, - localTime->tm_sec, tv.tv_usec/1000, ((tv.tv_sec * 1000) + (tv.tv_usec / 1000)), - display->mDisplayName.string(), display->mErrorFrameCount, - errString.string()); + saveString.appendFormat("%s %s %" PRIu64 ": %s\n", getLocalTimeStr(tv).string(), + display->mDisplayName.string(), display->mErrorFrameCount, + errString.string()); } else { - saveString.appendFormat("%02d-%02d %02d:%02d:%02d.%03lu(%lu) : %s\n", - localTime->tm_mon+1, localTime->tm_mday, - localTime->tm_hour, localTime->tm_min, - localTime->tm_sec, tv.tv_usec/1000, ((tv.tv_sec * 1000) + (tv.tv_usec / 1000)), - errString.string()); + saveString.appendFormat("%s : %s\n", getLocalTimeStr(tv).string(), errString.string()); } if (pFile != NULL) { @@ -105,80 +96,24 @@ int32_t saveFenceTrace(ExynosDisplay *display) { return -1; } + ExynosDevice *device = display->mDevice; + String8 saveString; - struct timeval tv; - ExynosDevice *device = display->mDevice; + struct timeval tv; + gettimeofday(&tv, NULL); + saveString.appendFormat("\n====== Fences at time:%s ======\n", getLocalTimeStr(tv).string()); if (device != NULL) { - for (const auto &[i, info] : device->mFenceInfos) { -#if 0 - bool sysFdOpen = false; - - // FIXME: sync_fence_info and sync_pt_info are deprecated - // HWC guys should fix this - struct sync_pt_info* pt_info = NULL; - info.sync_data = sync_fence_info(i); - if (info.sync_data != NULL) { - pt_info = sync_pt_info(info.sync_data, pt_info); - if (pt_info !=NULL) { - saveString.appendFormat("\n-- FD sys : %d\n", i); - saveString.appendFormat("real name : %s, status : %s, pt_obj : %s, pt_drv : %s, time : %llu", - info.sync_data->name, info.sync_data->status==1 ? "Active":"Signaled", - pt_info->obj_name, pt_info->driver_name, static_cast<unsigned long long>(pt_info->timestamp_ns)); - } else { - saveString.appendFormat("\n-- FD sys : %d\n", i); - saveString.appendFormat("real name : %s, status : %d, pt_info : %p", - info.sync_data->name, info.sync_data->status, pt_info); - } - sysFdOpen = true; - sync_fence_info_free(info.sync_data); - } - - if ((info.usage == 0) && !sysFdOpen) continue; -#endif - - saveString.appendFormat("\n-- FD hwc : %d, usage %d\n", i, info.usage); - - switch(info.last_dir) { - case FENCE_FROM: - saveString.appendFormat("Last state : from %d, %d\n", - info.from.type, info.from.ip); - tv = info.from.time; - break; - case FENCE_TO: - saveString.appendFormat("Last state : to %d, %d\n", - info.to.type, info.to.ip); - tv = info.to.time; - break; - case FENCE_DUP: - saveString.appendFormat("Last state : dup %d, %d\n", - info.dup.type, info.dup.ip); - tv = info.dup.time; - break; - case FENCE_CLOSE: - saveString.appendFormat("Last state : Close %d, %d\n", - info.close.type, info.close.ip); - tv = info.close.time; - break; - break; - default: - saveString.appendFormat("Fence trace : Undefined direction!\n"); - break; + for (const auto &[fd, info] : device->mFenceInfos) { + saveString.appendFormat("---- Fence FD : %d, Display(%d) ----\n", fd, info.displayId); + saveString.appendFormat("usage: %d, dupFrom: %d, pendingAllowed: %d, leaking: %d\n", + info.usage, info.dupFrom, info.pendingAllowed, info.leaking); + + for (const auto &trace : info.traces) { + saveString.appendFormat("> dir: %d, type: %d, ip: %d, time:%s\n", trace.direction, + trace.type, trace.ip, getLocalTimeStr(trace.time).string()); } - - struct tm* localTime = (struct tm*)localtime((time_t*)&tv.tv_sec); - - saveString.appendFormat("from : %d, %d (cur : %d), to : %d, %d (cur : %d), hwc_dup : %d, %d (cur : %d), hwc_close : %d, %d (cur : %d)\n", - info.from.type, info.from.ip, info.from.curFlag, - info.to.type, info.to.ip, info.to.curFlag, - info.dup.type, info.dup.ip, info.dup.curFlag, - info.close.type, info.close.ip, info.close.curFlag); - saveString.appendFormat("usage : %d, time:%02d-%02d %02d:%02d:%02d.%03lu(%lu)", info.usage, - localTime->tm_mon+1, localTime->tm_mday, - localTime->tm_hour, localTime->tm_min, - localTime->tm_sec, tv.tv_usec/1000, - ((tv.tv_sec * 1000) + (tv.tv_usec / 1000))); } } diff --git a/libhwc2.1/libdevice/ExynosDevice.cpp b/libhwc2.1/libdevice/ExynosDevice.cpp index fbc92f0..99f9438 100644 --- a/libhwc2.1/libdevice/ExynosDevice.cpp +++ b/libhwc2.1/libdevice/ExynosDevice.cpp @@ -311,8 +311,7 @@ void *ExynosDevice::dynamicRecompositionThreadLoop(void *data) } } } - if (result) - dev->invalidate(); + if (result) dev->onRefresh(); } android_atomic_dec(&(dev->mDRThreadStatus)); @@ -439,14 +438,15 @@ int32_t ExynosDevice::registerCallback ( if (descriptor < 0 || descriptor > HWC2_CALLBACK_SEAMLESS_POSSIBLE) return HWC2_ERROR_BAD_PARAMETER; + Mutex::Autolock lock(mDeviceCallbackMutex); mCallbackInfos[descriptor].callbackData = callbackData; mCallbackInfos[descriptor].funcPointer = point; /* Call hotplug callback for primary display*/ if (descriptor == HWC2_CALLBACK_HOTPLUG) { HWC2_PFN_HOTPLUG callbackFunc = - (HWC2_PFN_HOTPLUG)mCallbackInfos[descriptor].funcPointer; - if (callbackFunc != NULL) { + reinterpret_cast<HWC2_PFN_HOTPLUG>(mCallbackInfos[descriptor].funcPointer); + if (callbackFunc != nullptr) { for (auto it : mDisplays) { if (it->mPlugState) callbackFunc(callbackData, getDisplayId(it->mType, it->mIndex), @@ -466,16 +466,90 @@ int32_t ExynosDevice::registerCallback ( return HWC2_ERROR_NONE; } -void ExynosDevice::invalidate() -{ +bool ExynosDevice::isCallbackRegisteredLocked(int32_t descriptor) { + if (descriptor < 0 || descriptor > HWC2_CALLBACK_SEAMLESS_POSSIBLE) { + ALOGE("%s:: %d callback is unknown", __func__, descriptor); + return false; + } + + if (mCallbackInfos[descriptor].callbackData == nullptr || + mCallbackInfos[descriptor].funcPointer == nullptr) { + ALOGE("%s:: %d callback is not registered", __func__, descriptor); + return false; + } + + return true; +} + +bool ExynosDevice::isCallbackAvailable(int32_t descriptor) { + Mutex::Autolock lock(mDeviceCallbackMutex); + return isCallbackRegisteredLocked(descriptor); +} + +void ExynosDevice::onHotPlug(uint32_t displayId, bool status) { + Mutex::Autolock lock(mDeviceCallbackMutex); + + if (!isCallbackRegisteredLocked(HWC2_CALLBACK_HOTPLUG)) return; + + hwc2_callback_data_t callbackData = mCallbackInfos[HWC2_CALLBACK_HOTPLUG].callbackData; + HWC2_PFN_HOTPLUG callbackFunc = + reinterpret_cast<HWC2_PFN_HOTPLUG>(mCallbackInfos[HWC2_CALLBACK_HOTPLUG].funcPointer); + callbackFunc(callbackData, displayId, + status ? HWC2_CONNECTION_CONNECTED : HWC2_CONNECTION_DISCONNECTED); +} + +void ExynosDevice::onRefresh() { + Mutex::Autolock lock(mDeviceCallbackMutex); + + if (!isCallbackRegisteredLocked(HWC2_CALLBACK_REFRESH)) return; + + hwc2_callback_data_t callbackData = mCallbackInfos[HWC2_CALLBACK_REFRESH].callbackData; HWC2_PFN_REFRESH callbackFunc = - (HWC2_PFN_REFRESH)mCallbackInfos[HWC2_CALLBACK_REFRESH].funcPointer; - if (callbackFunc != NULL) - callbackFunc(mCallbackInfos[HWC2_CALLBACK_REFRESH].callbackData, - getDisplayId(HWC_DISPLAY_PRIMARY, 0)); - else - ALOGE("%s:: refresh callback is not registered", __func__); + reinterpret_cast<HWC2_PFN_REFRESH>(mCallbackInfos[HWC2_CALLBACK_REFRESH].funcPointer); + callbackFunc(callbackData, getDisplayId(HWC_DISPLAY_PRIMARY, 0)); +} + +void ExynosDevice::onVsync(uint32_t displayId, int64_t timestamp) { + Mutex::Autolock lock(mDeviceCallbackMutex); + + if (!isCallbackRegisteredLocked(HWC2_CALLBACK_VSYNC)) return; + + hwc2_callback_data_t callbackData = mCallbackInfos[HWC2_CALLBACK_VSYNC].callbackData; + HWC2_PFN_VSYNC callbackFunc = + reinterpret_cast<HWC2_PFN_VSYNC>(mCallbackInfos[HWC2_CALLBACK_VSYNC].funcPointer); + callbackFunc(callbackData, displayId, timestamp); +} + +bool ExynosDevice::onVsync_2_4(uint32_t displayId, int64_t timestamp, uint32_t vsyncPeriod) { + Mutex::Autolock lock(mDeviceCallbackMutex); + + if (!isCallbackRegisteredLocked(HWC2_CALLBACK_VSYNC_2_4)) return false; + + hwc2_callback_data_t callbackData = mCallbackInfos[HWC2_CALLBACK_VSYNC_2_4].callbackData; + HWC2_PFN_VSYNC_2_4 callbackFunc = reinterpret_cast<HWC2_PFN_VSYNC_2_4>( + mCallbackInfos[HWC2_CALLBACK_VSYNC_2_4].funcPointer); + callbackFunc(callbackData, displayId, timestamp, vsyncPeriod); + + return true; +} + +void ExynosDevice::onVsyncPeriodTimingChanged(uint32_t displayId, + hwc_vsync_period_change_timeline_t *timeline) { + Mutex::Autolock lock(mDeviceCallbackMutex); + if (!timeline) { + ALOGE("vsync period change timeline is null"); + return; + } + + if (!isCallbackRegisteredLocked(HWC2_CALLBACK_VSYNC_PERIOD_TIMING_CHANGED)) return; + + hwc2_callback_data_t callbackData = + mCallbackInfos[HWC2_CALLBACK_VSYNC_PERIOD_TIMING_CHANGED].callbackData; + HWC2_PFN_VSYNC_PERIOD_TIMING_CHANGED callbackFunc = + reinterpret_cast<HWC2_PFN_VSYNC_PERIOD_TIMING_CHANGED>( + mCallbackInfos[HWC2_CALLBACK_VSYNC_PERIOD_TIMING_CHANGED].funcPointer); + callbackFunc(callbackData, displayId, timeline); } void ExynosDevice::setHWCDebug(unsigned int debug) @@ -533,13 +607,13 @@ void ExynosDevice::setHWCControl(uint32_t display, uint32_t ctrl, int32_t val) ALOGI("%s::HWC_CTL_FORCE_GPU on/off=%d", __func__, val); exynosHWCControl.forceGpu = (unsigned int)val; setGeometryChanged(GEOMETRY_DEVICE_CONFIG_CHANGED); - invalidate(); + onRefresh(); break; case HWC_CTL_WINDOW_UPDATE: ALOGI("%s::HWC_CTL_WINDOW_UPDATE on/off=%d", __func__, val); exynosHWCControl.windowUpdate = (unsigned int)val; setGeometryChanged(GEOMETRY_DEVICE_CONFIG_CHANGED); - invalidate(); + onRefresh(); break; case HWC_CTL_FORCE_PANIC: ALOGI("%s::HWC_CTL_FORCE_PANIC on/off=%d", __func__, val); @@ -560,19 +634,19 @@ void ExynosDevice::setHWCControl(uint32_t display, uint32_t ctrl, int32_t val) ALOGI("%s::HWC_CTL_SKIP_RESOURCE_ASSIGN on/off=%d", __func__, val); exynosHWCControl.skipResourceAssign = (unsigned int)val; setGeometryChanged(GEOMETRY_DEVICE_CONFIG_CHANGED); - invalidate(); + onRefresh(); break; case HWC_CTL_SKIP_VALIDATE: ALOGI("%s::HWC_CTL_SKIP_VALIDATE on/off=%d", __func__, val); exynosHWCControl.skipValidate = (unsigned int)val; setGeometryChanged(GEOMETRY_DEVICE_CONFIG_CHANGED); - invalidate(); + onRefresh(); break; case HWC_CTL_DUMP_MID_BUF: ALOGI("%s::HWC_CTL_DUMP_MID_BUF on/off=%d", __func__, val); exynosHWCControl.dumpMidBuf = (unsigned int)val; setGeometryChanged(GEOMETRY_DEVICE_CONFIG_CHANGED); - invalidate(); + onRefresh(); break; case HWC_CTL_CAPTURE_READBACK: captureScreenWithReadback(HWC_DISPLAY_PRIMARY); @@ -581,7 +655,7 @@ void ExynosDevice::setHWCControl(uint32_t display, uint32_t ctrl, int32_t val) ALOGI("%s::HWC_CTL_DISPLAY_MODE mode=%d", __func__, val); setDisplayMode((uint32_t)val); setGeometryChanged(GEOMETRY_DEVICE_CONFIG_CHANGED); - invalidate(); + onRefresh(); break; // Support DDI scalser { case HWC_CTL_DDI_RESOLUTION_CHANGE: @@ -607,7 +681,7 @@ void ExynosDevice::setHWCControl(uint32_t display, uint32_t ctrl, int32_t val) exynosDisplay->setDDIScalerEnable(width, height); } setGeometryChanged(GEOMETRY_DISPLAY_RESOLUTION_CHANGED); - invalidate(); + onRefresh(); break; // } Support DDI scaler case HWC_CTL_ENABLE_COMPOSITION_CROP: @@ -625,7 +699,7 @@ void ExynosDevice::setHWCControl(uint32_t display, uint32_t ctrl, int32_t val) exynosDisplay->setHWCControl(ctrl, val); } setGeometryChanged(GEOMETRY_DEVICE_CONFIG_CHANGED); - invalidate(); + onRefresh(); break; case HWC_CTL_DYNAMIC_RECOMP: ALOGI("%s::HWC_CTL_DYNAMIC_RECOMP on/off = %d", __func__, val); @@ -772,16 +846,14 @@ bool ExynosDevice::validateFences(ExynosDisplay *display) { } if (fenceWarn(display, MAX_FENCE_THRESHOLD)) { - ALOGE("Fence leak! --"); printLeakFds(display); saveFenceTrace(display); return false; } if (exynosHWCControl.doFenceFileDump) { - ALOGE("Fence file dump !"); - if (mFenceLogSize != 0) - ALOGE("Fence file not empty!"); + ALOGD("Fence file dump !"); + if (mFenceLogSize != 0) ALOGD("Fence file not empty!"); saveFenceTrace(display); exynosHWCControl.doFenceFileDump = false; } @@ -921,7 +993,7 @@ void ExynosDevice::captureScreenWithReadback(uint32_t displayType) } /* Update screen */ - invalidate(); + onRefresh(); /* Wait for handling readback */ uint32_t waitPeriod = display->mVsyncPeriod * 3; @@ -969,7 +1041,7 @@ int32_t ExynosDevice::setDisplayDeviceMode(int32_t display_id, int32_t mode) mode == static_cast<int32_t>(ext_hwc2_power_mode_t::RESUME)) { ret = mDisplays[display_id]->setPowerMode(mode); if (mode == static_cast<int32_t>(ext_hwc2_power_mode_t::RESUME) && ret == HWC2_ERROR_NONE) { - invalidate(); + onRefresh(); } return ret; } else { @@ -1067,6 +1139,11 @@ bool ExynosDevice::getLhbmState() { return false; } +PanelCalibrationStatus ExynosDevice::getPanelCalibrationStatus() { + auto display = getDisplay(getDisplayId(HWC_DISPLAY_PRIMARY, 0)); + return display->getPanelCalibrationStatus(); +} + uint32_t ExynosDevice::getWindowPlaneNum() { /* @@ -1129,6 +1206,7 @@ int ExynosDevice::setRefreshRateThrottle(const int delayMs) { int32_t ExynosDevice::registerHwc3Callback(uint32_t descriptor, hwc2_callback_data_t callbackData, hwc2_function_pointer_t point) { + Mutex::Autolock lock(mDeviceCallbackMutex); mHwc3CallbackInfos[descriptor].callbackData = callbackData; mHwc3CallbackInfos[descriptor].funcPointer = point; @@ -1136,6 +1214,7 @@ int32_t ExynosDevice::registerHwc3Callback(uint32_t descriptor, hwc2_callback_da } void ExynosDevice::onVsyncIdle(hwc2_display_t displayId) { + Mutex::Autolock lock(mDeviceCallbackMutex); const auto &idleCallback = mHwc3CallbackInfos.find(IComposerCallback::TRANSACTION_onVsyncIdle); if (idleCallback == mHwc3CallbackInfos.end()) return; diff --git a/libhwc2.1/libdevice/ExynosDevice.h b/libhwc2.1/libdevice/ExynosDevice.h index d5a02fe..1dd1145 100644 --- a/libhwc2.1/libdevice/ExynosDevice.h +++ b/libhwc2.1/libdevice/ExynosDevice.h @@ -59,6 +59,7 @@ using HbmState = ::aidl::com::google::hardware::pixel::display::HbmState; using LbeState = ::aidl::com::google::hardware::pixel::display::LbeState; +using PanelCalibrationStatus = ::aidl::com::google::hardware::pixel::display::PanelCalibrationStatus; using namespace android; @@ -185,6 +186,7 @@ class ExynosDevice { exynos_callback_info_t mCallbackInfos[HWC2_CALLBACK_SEAMLESS_POSSIBLE + 1]; std::map<uint32_t, exynos_callback_info_t> mHwc3CallbackInfos; + Mutex mDeviceCallbackMutex; /** * Thread variables @@ -202,7 +204,7 @@ class ExynosDevice { uint32_t mDisplayMode; // Variable for fence tracer - std::map<int, hwc_fence_info_t> mFenceInfos; + std::map<int, HwcFenceInfo> mFenceInfos; /** * This will be initialized with differnt class @@ -274,8 +276,13 @@ class ExynosDevice { */ int32_t registerCallback ( int32_t descriptor, hwc2_callback_data_t callbackData, hwc2_function_pointer_t point); - - void invalidate(); + bool isCallbackAvailable(int32_t descriptor); + void onHotPlug(uint32_t displayId, bool status); + void onRefresh(); + void onVsync(uint32_t displayId, int64_t timestamp); + bool onVsync_2_4(uint32_t displayId, int64_t timestamp, uint32_t vsyncPeriod); + void onVsyncPeriodTimingChanged(uint32_t displayId, + hwc_vsync_period_change_timeline_t *timeline); void setHWCDebug(unsigned int debug); uint32_t getHWCDebug(); @@ -335,6 +342,7 @@ class ExynosDevice { Condition mCaptureCondition; std::atomic<bool> mIsWaitingReadbackReqDone = false; void setVBlankOffDelay(int vblankOffDelay); + bool isCallbackRegisteredLocked(int32_t descriptor); public: bool isLbeSupported(); @@ -350,6 +358,8 @@ class ExynosDevice { bool isColorCalibratedByDevice(); + PanelCalibrationStatus getPanelCalibrationStatus(); + public: void enterToTUI() { mIsInTUI = true; }; void exitFromTUI() { mIsInTUI = false; }; diff --git a/libhwc2.1/libdevice/ExynosDisplay.cpp b/libhwc2.1/libdevice/ExynosDisplay.cpp index 98256dc..78f65f2 100644 --- a/libhwc2.1/libdevice/ExynosDisplay.cpp +++ b/libhwc2.1/libdevice/ExynosDisplay.cpp @@ -1581,7 +1581,7 @@ bool ExynosDisplay::skipStaticLayerChanged(ExynosCompositionInfo& compositionInf } void ExynosDisplay::requestLhbm(bool on) { - mDevice->invalidate(); + mDevice->onRefresh(); if (mBrightnessController) { mBrightnessController->processLocalHbm(on); } @@ -1800,9 +1800,7 @@ int ExynosDisplay::doExynosComposition() { mExynosCompositionInfo.setExynosImage(src_img, dst_img); DISPLAY_LOGD(eDebugFence, "mExynosCompositionInfo acquireFencefd(%d)", - mExynosCompositionInfo.mAcquireFence); - // Test.. - // setFenceInfo(mExynosCompositionInfo.mAcquireFence, this, "G2D_DST_ACQ", FENCE_FROM); + mExynosCompositionInfo.mAcquireFence); if ((ret = mExynosCompositionInfo.mM2mMPP->resetDstReleaseFence()) != NO_ERROR) { @@ -2384,15 +2382,9 @@ void ExynosDisplay::printDebugInfos(String8 &reason) { FILE *pFile = NULL; struct timeval tv; - struct tm* localTime; gettimeofday(&tv, NULL); - localTime = (struct tm*)localtime((time_t*)&tv.tv_sec); - reason.appendFormat("errFrameNumber: %" PRId64 " time:%02d-%02d %02d:%02d:%02d.%03lu(%lu)\n", - mErrorFrameCount, - localTime->tm_mon+1, localTime->tm_mday, - localTime->tm_hour, localTime->tm_min, - localTime->tm_sec, tv.tv_usec/1000, - ((tv.tv_sec * 1000) + (tv.tv_usec / 1000))); + reason.appendFormat("errFrameNumber: %" PRId64 " time:%s\n", mErrorFrameCount, + getLocalTimeStr(tv).string()); ALOGD("%s", reason.string()); if (mErrorFrameCount < HWC_PRINT_FRAME_NUM) { @@ -2710,8 +2702,8 @@ int ExynosDisplay::deliverWinConfigData() { mRetireFenceAcquireTime = systemTime(); } for (size_t i = 0; i < mDpuData.configs.size(); i++) { - setFenceInfo(mDpuData.configs[i].acq_fence, this, - FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_DPP, FENCE_TO); + setFenceInfo(mDpuData.configs[i].acq_fence, this, FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_DPP, + HwcFenceDirection::TO); } if ((ret = mDisplayInterface->deliverWinConfigData()) < 0) { @@ -2722,11 +2714,11 @@ int ExynosDisplay::deliverWinConfigData() { } for (size_t i = 0; i < mDpuData.configs.size(); i++) { - setFenceInfo(mDpuData.configs[i].rel_fence, this, - FENCE_TYPE_SRC_RELEASE, FENCE_IP_DPP, FENCE_FROM); + setFenceInfo(mDpuData.configs[i].rel_fence, this, FENCE_TYPE_SRC_RELEASE, FENCE_IP_DPP, + HwcFenceDirection::FROM); } - setFenceInfo(mDpuData.retire_fence, this, - FENCE_TYPE_RETIRE, FENCE_IP_DPP, FENCE_FROM); + setFenceInfo(mDpuData.retire_fence, this, FENCE_TYPE_RETIRE, FENCE_IP_DPP, + HwcFenceDirection::FROM); } return ret; @@ -2829,8 +2821,8 @@ int ExynosDisplay::setReleaseFences() { if (config.rel_fence > 0) { release_fd = config.rel_fence; if (release_fd >= 0) { - setFenceName(release_fd, - this, FENCE_TYPE_DST_ACQUIRE, FENCE_IP_DPP, FENCE_FROM, true); + setFenceInfo(release_fd, this, FENCE_TYPE_DST_ACQUIRE, FENCE_IP_DPP, + HwcFenceDirection::UPDATE, true); mLayers[i]->mM2mMPP->setDstAcquireFence(release_fd); } else { DISPLAY_LOGE("fail to dup, ret(%d, %s)", errno, strerror(errno)); @@ -2907,8 +2899,8 @@ int ExynosDisplay::setReleaseFences() { mExynosCompositionInfo.mM2mMPP->setDstAcquireFence(-1); #else if (config.rel_fence > 0) { - setFenceName(config.rel_fence, - this, FENCE_TYPE_DST_ACQUIRE, FENCE_IP_DPP, FENCE_FROM, true); + setFenceInfo(config.rel_fence, this, FENCE_TYPE_DST_ACQUIRE, FENCE_IP_DPP, + HwcFenceDirection::UPDATE, true); mExynosCompositionInfo.mM2mMPP->setDstAcquireFence(config.rel_fence); } else { mExynosCompositionInfo.mM2mMPP->setDstAcquireFence(-1); @@ -3460,7 +3452,7 @@ int32_t ExynosDisplay::presentDisplay(int32_t* outRetireFence) { ret = HWC2_ERROR_NOT_VALIDATED; } mRenderingState = RENDERING_STATE_PRESENTED; - mDevice->invalidate(); + mDevice->onRefresh(); return ret; } @@ -3626,15 +3618,14 @@ int32_t ExynosDisplay::presentDisplay(int32_t* outRetireFence) { *outRetireFence = hwcCheckFenceDebug(this, FENCE_TYPE_RETIRE, FENCE_IP_DPP, mDpuData.retire_fence); #endif - setFenceInfo(mDpuData.retire_fence, this, - FENCE_TYPE_RETIRE, FENCE_IP_LAYER, FENCE_TO); + setFenceInfo(mDpuData.retire_fence, this, FENCE_TYPE_RETIRE, FENCE_IP_LAYER, + HwcFenceDirection::TO); } else *outRetireFence = -1; /* Update last retire fence */ mLastRetireFence = fence_close(mLastRetireFence, this, FENCE_TYPE_RETIRE, FENCE_IP_DPP); - mLastRetireFence = hwc_dup((*outRetireFence), this, FENCE_TYPE_RETIRE, FENCE_IP_DPP); - setFenceName(mLastRetireFence, this, FENCE_TYPE_RETIRE, FENCE_IP_DPP, FENCE_DUP, true); + mLastRetireFence = hwc_dup((*outRetireFence), this, FENCE_TYPE_RETIRE, FENCE_IP_DPP, true); setFenceName(mLastRetireFence, FENCE_RETIRE); increaseMPPDstBufIndex(); @@ -3668,16 +3659,14 @@ int32_t ExynosDisplay::presentDisplay(int32_t* outRetireFence) { /* All of release fences are tranferred */ for (size_t i=0; i < mLayers.size(); i++) { - setFenceInfo(mLayers[i]->mReleaseFence, this, - FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_LAYER, FENCE_TO); + setFenceInfo(mLayers[i]->mReleaseFence, this, FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_LAYER, + HwcFenceDirection::TO); } doPostProcessing(); - if (!mDevice->validateFences(this)){ - String8 errString; - errString.appendFormat("%s:: validate fence failed. \n", __func__); - printDebugInfos(errString); + if (!mDevice->validateFences(this)) { + ALOGE("%s:: validate fence failed.", __func__); } mDpuData.reset(); @@ -3721,9 +3710,8 @@ err: mDpuData.reset(); - if (!mDevice->validateFences(this)){ - errString.appendFormat("%s:: validate fence failed. \n", __func__); - printDebugInfos(errString); + if (!mDevice->validateFences(this)) { + ALOGE("%s:: validate fence failed.", __func__); } mDisplayInterface->setForcePanic(); @@ -3841,8 +3829,7 @@ int32_t ExynosDisplay::setClientTarget( } } mClientCompositionInfo.setTargetBuffer(this, handle, acquireFence, (android_dataspace)dataspace); - setFenceInfo(acquireFence, this, - FENCE_TYPE_SRC_RELEASE, FENCE_IP_FB, FENCE_FROM); + setFenceInfo(acquireFence, this, FENCE_TYPE_SRC_RELEASE, FENCE_IP_FB, HwcFenceDirection::FROM); if (handle) { mClientCompositionInfo.mCompressed = isAFBCCompressed(handle); @@ -4094,7 +4081,8 @@ int32_t ExynosDisplay::setActiveConfigWithConstraints(hwc2_config_t config, mXres, mYres, mVsyncPeriod, mXdpi, mYdpi); if (mConfigRequestState == hwc_request_state_t::SET_CONFIG_STATE_REQUESTED) { - DISPLAY_LOGI("%s, previous request config is processing", __func__); + DISPLAY_LOGI("%s, previous request config is processing (mDesiredConfig: %d)", __func__, + mDesiredConfig); } /* Config would be requested on present time */ mConfigRequestState = hwc_request_state_t::SET_CONFIG_STATE_PENDING; @@ -4201,8 +4189,7 @@ int32_t ExynosDisplay::updateInternalDisplayConfigVariables( getDisplayAttribute(mActiveConfig, HWC2_ATTRIBUTE_DPI_Y, (int32_t*)&mYdpi); mHdrFullScrenAreaThreshold = mXres * mYres * kHdrFullScreen; if (updateVsync) { - mVsyncPeriod = getDisplayVsyncPeriodFromConfig(mActiveConfig); - updateBtsVsyncPeriod(mVsyncPeriod, true); + resetConfigRequestStateLocked(config); } return NO_ERROR; @@ -4226,11 +4213,12 @@ void ExynosDisplay::updateRefreshRateHint() { } /* This function must be called within a mDisplayMutex protection */ -int32_t ExynosDisplay::resetConfigRequestStateLocked() { - mVsyncPeriod = getDisplayVsyncPeriodFromConfig(mActiveConfig); +int32_t ExynosDisplay::resetConfigRequestStateLocked(hwc2_config_t config) { + ATRACE_CALL(); + + mVsyncPeriod = getDisplayVsyncPeriodFromConfig(config); updateBtsVsyncPeriod(mVsyncPeriod, true); - DISPLAY_LOGD(eDebugDisplayConfig, "Update mVsyncPeriod %d by mActiveConfig(%d)", mVsyncPeriod, - mActiveConfig); + DISPLAY_LOGD(eDebugDisplayConfig, "Update mVsyncPeriod %d by config(%d)", mVsyncPeriod, config); updateRefreshRateHint(); @@ -4248,8 +4236,11 @@ int32_t ExynosDisplay::resetConfigRequestStateLocked() { int32_t ExynosDisplay::updateConfigRequestAppliedTime() { - if (mConfigRequestState != hwc_request_state_t::SET_CONFIG_STATE_REQUESTED) + if (mConfigRequestState != hwc_request_state_t::SET_CONFIG_STATE_REQUESTED) { + DISPLAY_LOGI("%s: mConfigRequestState (%d) is not REQUESTED", __func__, + mConfigRequestState); return NO_ERROR; + } /* * config change was requested but @@ -4264,14 +4255,6 @@ int32_t ExynosDisplay::updateConfigRequestAppliedTime() int32_t ExynosDisplay::updateVsyncAppliedTimeLine(int64_t actualChangeTime) { ExynosDevice *dev = mDevice; - hwc2_callback_data_t vsync_callbackData = nullptr; - HWC2_PFN_VSYNC_PERIOD_TIMING_CHANGED vsync_callbackFunc = nullptr; - if (dev->mCallbackInfos[HWC2_CALLBACK_VSYNC_PERIOD_TIMING_CHANGED].funcPointer != NULL) { - vsync_callbackData = - dev->mCallbackInfos[HWC2_CALLBACK_VSYNC_PERIOD_TIMING_CHANGED].callbackData; - vsync_callbackFunc = - (HWC2_PFN_VSYNC_PERIOD_TIMING_CHANGED)dev->mCallbackInfos[HWC2_CALLBACK_VSYNC_PERIOD_TIMING_CHANGED].funcPointer; - } DISPLAY_LOGD(eDebugDisplayConfig,"Vsync applied time is changed (%" PRId64 "-> %" PRId64 ")", mVsyncAppliedTimeLine.newVsyncAppliedTimeNanos, @@ -4291,12 +4274,7 @@ int32_t ExynosDisplay::updateVsyncAppliedTimeLine(int64_t actualChangeTime) mVsyncAppliedTimeLine.refreshRequired, mVsyncAppliedTimeLine.newVsyncAppliedTimeNanos); - if (vsync_callbackFunc != nullptr) - vsync_callbackFunc(vsync_callbackData, getId(), - &mVsyncAppliedTimeLine); - else { - ALOGD("callback function is null"); - } + dev->onVsyncPeriodTimingChanged(getId(), &mVsyncAppliedTimeLine); return NO_ERROR; } @@ -4337,7 +4315,8 @@ int32_t ExynosDisplay::doDisplayConfigPostProcess(ExynosDevice *dev) needSetActiveConfig = true; ATRACE_INT("Pending ActiveConfig", 0); } else { - DISPLAY_LOGD(eDebugDisplayConfig, "setActiveConfig still pending"); + DISPLAY_LOGD(eDebugDisplayConfig, "setActiveConfig still pending (mDesiredConfig %d)", + mDesiredConfig); ATRACE_INT("Pending ActiveConfig", mDesiredConfig); } @@ -5766,8 +5745,8 @@ void ExynosDisplay::setReadbackBufferInternal(buffer_handle_t buffer, DISPLAY_LOGE("previous readback release fence is not delivered to display device"); } if (releaseFence >= 0) { - setFenceInfo(releaseFence, this, FENCE_TYPE_READBACK_RELEASE, - FENCE_IP_FB, FENCE_FROM); + setFenceInfo(releaseFence, this, FENCE_TYPE_READBACK_RELEASE, FENCE_IP_FB, + HwcFenceDirection::FROM); } mDpuData.readback_info.rel_fence = releaseFence; @@ -5808,8 +5787,8 @@ int32_t ExynosDisplay::setReadbackBufferAcqFence(int32_t acqFence) { * so validateFences should not check this fence * in presentDisplay so this function sets pendingAllowed parameter. */ - setFenceInfo(acqFence, this, FENCE_TYPE_READBACK_ACQUIRE, - FENCE_IP_DPP, FENCE_FROM, true); + setFenceInfo(acqFence, this, FENCE_TYPE_READBACK_ACQUIRE, FENCE_IP_DPP, + HwcFenceDirection::FROM, true); } return NO_ERROR; diff --git a/libhwc2.1/libdevice/ExynosDisplay.h b/libhwc2.1/libdevice/ExynosDisplay.h index 028798e..e31a692 100644 --- a/libhwc2.1/libdevice/ExynosDisplay.h +++ b/libhwc2.1/libdevice/ExynosDisplay.h @@ -1101,7 +1101,7 @@ class ExynosDisplay { bool needNotChangeConfig(hwc2_config_t config); int32_t updateInternalDisplayConfigVariables( hwc2_config_t config, bool updateVsync = true); - int32_t resetConfigRequestStateLocked(); + int32_t resetConfigRequestStateLocked(hwc2_config_t config); int32_t updateConfigRequestAppliedTime(); int32_t updateVsyncAppliedTimeLine(int64_t actualChangeTime); int32_t getDisplayVsyncPeriodInternal( @@ -1199,6 +1199,10 @@ class ExynosDisplay { } virtual void handleDisplayIdleEnter(const uint32_t __unused idleTeRefreshRate) {} + virtual PanelCalibrationStatus getPanelCalibrationStatus() { + return PanelCalibrationStatus::UNCALIBRATED; + } + /* getDisplayPreAssignBit support mIndex up to 1. It supports only dual LCD and 2 external displays */ inline uint32_t getDisplayPreAssignBit() { @@ -1239,6 +1243,13 @@ class ExynosDisplay { // is the hint session both enabled and supported bool usePowerHintSession(); + void setMinDisplayVsyncPeriod(uint32_t period) { mMinDisplayVsyncPeriod = period; } + + bool isCurrentPeakRefreshRate(void) { + return ((mConfigRequestState == hwc_request_state_t::SET_CONFIG_STATE_NONE) && + (mVsyncPeriod == mMinDisplayVsyncPeriod)); + } + private: bool skipStaticLayerChanged(ExynosCompositionInfo& compositionInfo); @@ -1253,6 +1264,9 @@ class ExynosDisplay { static constexpr float kHdrFullScreen = 0.5; uint32_t mHdrFullScrenAreaThreshold; + // vsync period of peak refresh rate + uint32_t mMinDisplayVsyncPeriod; + /* Display hint to notify power hal */ class PowerHalHintWorker : public Worker { public: diff --git a/libhwc2.1/libdevice/ExynosLayer.cpp b/libhwc2.1/libdevice/ExynosLayer.cpp index b06b093..105437e 100644 --- a/libhwc2.1/libdevice/ExynosLayer.cpp +++ b/libhwc2.1/libdevice/ExynosLayer.cpp @@ -967,7 +967,8 @@ void ExynosLayer::setSrcAcquireFence() { hwc_dup(mPrevAcquireFence, mDisplay, FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_LAYER)); } else if (mAcquireFence != -1) { - setFenceInfo(mAcquireFence, mDisplay, FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_LAYER, FENCE_FROM); + setFenceInfo(mAcquireFence, mDisplay, FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_LAYER, + HwcFenceDirection::FROM); } } diff --git a/libhwc2.1/libdisplayinterface/ExynosDeviceDrmInterface.cpp b/libhwc2.1/libdisplayinterface/ExynosDeviceDrmInterface.cpp index 1836c11..1df6fe9 100644 --- a/libhwc2.1/libdisplayinterface/ExynosDeviceDrmInterface.cpp +++ b/libhwc2.1/libdisplayinterface/ExynosDeviceDrmInterface.cpp @@ -217,24 +217,16 @@ void ExynosDeviceDrmInterface::ExynosDrmEventHandler::init(ExynosDevice *exynosD } void ExynosDeviceDrmInterface::ExynosDrmEventHandler::handleEvent(uint64_t timestamp_us) { - hwc2_callback_data_t callbackData = - mExynosDevice->mCallbackInfos[HWC2_CALLBACK_HOTPLUG].callbackData; - HWC2_PFN_HOTPLUG callbackFunc = - (HWC2_PFN_HOTPLUG)mExynosDevice->mCallbackInfos[HWC2_CALLBACK_HOTPLUG].funcPointer; - - if (callbackData == NULL || callbackFunc == NULL) - { - ALOGE("%s:: callback info is NULL", __func__); + if (!mExynosDevice->isCallbackAvailable(HWC2_CALLBACK_HOTPLUG)) { return; } for (auto it : mExynosDevice->mDisplays) { /* Call UpdateModes to get plug status */ uint32_t numConfigs; - it->getDisplayConfigs(&numConfigs, NULL); - callbackFunc(callbackData, getDisplayId(it->mType, it->mIndex), - it->mPlugState ? HWC2_CONNECTION_CONNECTED : HWC2_CONNECTION_DISCONNECTED); + it->getDisplayConfigs(&numConfigs, NULL); + mExynosDevice->onHotPlug(getDisplayId(it->mType, it->mIndex), it->mPlugState); } /* TODO: Check plug status hear or ExynosExternalDisplay::handleHotplugEvent() */ @@ -263,7 +255,7 @@ void ExynosDeviceDrmInterface::ExynosDrmEventHandler::handleTUIEvent() { } else { /* Received TUI Exit event */ if (mExynosDevice->isInTUI()) { - mExynosDevice->invalidate(); + mExynosDevice->onRefresh(); mExynosDevice->exitFromTUI(); ALOGV("%s:: DRM device out TUI", __func__); } diff --git a/libhwc2.1/libdisplayinterface/ExynosDisplayDrmInterface.cpp b/libhwc2.1/libdisplayinterface/ExynosDisplayDrmInterface.cpp index 1ac22e8..82286a1 100644 --- a/libhwc2.1/libdisplayinterface/ExynosDisplayDrmInterface.cpp +++ b/libhwc2.1/libdisplayinterface/ExynosDisplayDrmInterface.cpp @@ -690,47 +690,42 @@ int32_t ExynosDisplayDrmInterface::initDrmDevice(DrmDevice *drmDevice) void ExynosDisplayDrmInterface::Callback( int display, int64_t timestamp) { - Mutex::Autolock lock(mExynosDisplay->getDisplayMutex()); - bool configApplied = mVsyncCallback.Callback(display, timestamp); - - if (configApplied) { - if (mVsyncCallback.getDesiredVsyncPeriod()) { - mExynosDisplay->resetConfigRequestStateLocked(); - mDrmConnector->set_active_mode(mActiveModeState.mode); - mVsyncCallback.resetDesiredVsyncPeriod(); - } + { + Mutex::Autolock lock(mExynosDisplay->getDisplayMutex()); + bool configApplied = mVsyncCallback.Callback(display, timestamp); + + if (configApplied) { + if (mVsyncCallback.getDesiredVsyncPeriod()) { + mExynosDisplay->resetConfigRequestStateLocked(mActiveModeState.mode.id()); + mDrmConnector->set_active_mode(mActiveModeState.mode); + mVsyncCallback.resetDesiredVsyncPeriod(); + } - /* - * Disable vsync if vsync config change is done - */ - if (!mVsyncCallback.getVSyncEnabled()) { - mDrmVSyncWorker.VSyncControl(false); - mVsyncCallback.resetVsyncTimeStamp(); + /* + * Disable vsync if vsync config change is done + */ + if (!mVsyncCallback.getVSyncEnabled()) { + mDrmVSyncWorker.VSyncControl(false); + mVsyncCallback.resetVsyncTimeStamp(); + } + } else { + mExynosDisplay->updateConfigRequestAppliedTime(); } - } else { - mExynosDisplay->updateConfigRequestAppliedTime(); - } - if (!mExynosDisplay->mPlugState || !mVsyncCallback.getVSyncEnabled()) { - return; + if (!mExynosDisplay->mPlugState || !mVsyncCallback.getVSyncEnabled()) { + return; + } } ExynosDevice *exynosDevice = mExynosDisplay->mDevice; - 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); + + if (exynosDevice->onVsync_2_4(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); + exynosDevice->onVsync(mExynosDisplay->mDisplayId, timestamp); } bool ExynosDisplayDrmInterface::ExynosVsyncCallback::Callback( @@ -826,8 +821,7 @@ int32_t ExynosDisplayDrmInterface::setVsyncEnabled(uint32_t enabled) mVsyncCallback.enableVSync(HWC2_VSYNC_ENABLE == enabled); ExynosDevice *exynosDevice = mExynosDisplay->mDevice; - auto vsync_2_4CallbackInfo = exynosDevice->mCallbackInfos[HWC2_CALLBACK_VSYNC_2_4]; - if (vsync_2_4CallbackInfo.funcPointer && vsync_2_4CallbackInfo.callbackData) { + if (exynosDevice->isCallbackAvailable(HWC2_CALLBACK_VSYNC_2_4)) { ATRACE_INT(vsyncPeriodTag, 0); } @@ -885,6 +879,7 @@ int32_t ExynosDisplayDrmInterface::getDisplayConfigs( /* key: (width<<32 | height) */ std::map<uint64_t, uint32_t> groupIds; uint32_t groupId = 0; + uint32_t min_vsync_period = UINT_MAX; for (const DrmMode &mode : mDrmConnector->modes()) { displayConfigs_t configs; @@ -905,11 +900,14 @@ int32_t ExynosDisplayDrmInterface::getDisplayConfigs( configs.Xdpi = mm_width ? (mode.h_display() * kUmPerInch) / mm_width : -1; // Dots per 1000 inches configs.Ydpi = mm_height ? (mode.v_display() * kUmPerInch) / mm_height : -1; + // find min vsync period + if (configs.vsyncPeriod <= min_vsync_period) min_vsync_period = configs.vsyncPeriod; mExynosDisplay->mDisplayConfigs.insert(std::make_pair(mode.id(), configs)); ALOGD("config group(%d), w(%d), h(%d), vsync(%d), xdpi(%d), ydpi(%d)", configs.groupId, configs.width, configs.height, configs.vsyncPeriod, configs.Xdpi, configs.Ydpi); } + mExynosDisplay->setMinDisplayVsyncPeriod(min_vsync_period); } uint32_t num_modes = static_cast<uint32_t>(mDrmConnector->modes().size()); @@ -1070,6 +1068,9 @@ int32_t ExynosDisplayDrmInterface::setActiveConfigWithConstraints( if ((mActiveModeState.blob_id != 0) && (mActiveModeState.mode.id() == config)) { ALOGD("%s:: same mode %d", __func__, config); + /* trigger resetConfigRequestStateLocked() */ + mVsyncCallback.setDesiredVsyncPeriod(nsecsPerSec / mActiveModeState.mode.v_refresh()); + mDrmVSyncWorker.VSyncControl(true); return HWC2_ERROR_NONE; } diff --git a/libhwc2.1/libexternaldisplay/ExynosExternalDisplay.cpp b/libhwc2.1/libexternaldisplay/ExynosExternalDisplay.cpp index 8ba3020..39c2e79 100644 --- a/libhwc2.1/libexternaldisplay/ExynosExternalDisplay.cpp +++ b/libhwc2.1/libexternaldisplay/ExynosExternalDisplay.cpp @@ -149,12 +149,7 @@ int32_t ExynosExternalDisplay::getActiveConfig(hwc2_config_t* outConfig) { void ExynosExternalDisplay::hotplug(){ DISPLAY_LOGD(eDebugExternalDisplay, ""); - hwc2_callback_data_t callbackData = - mDevice->mCallbackInfos[HWC2_CALLBACK_HOTPLUG].callbackData; - HWC2_PFN_HOTPLUG callbackFunc = - (HWC2_PFN_HOTPLUG)mDevice->mCallbackInfos[HWC2_CALLBACK_HOTPLUG].funcPointer; - if (callbackData != NULL && callbackFunc != NULL) - callbackFunc(callbackData, mDisplayId, mHpdStatus ? HWC2_CONNECTION_CONNECTED : HWC2_CONNECTION_DISCONNECTED); + mDevice->onHotPlug(mDisplayId, mHpdStatus); } bool ExynosExternalDisplay::handleRotate() @@ -314,7 +309,7 @@ int32_t ExynosExternalDisplay::presentDisplay( ret = HWC2_ERROR_NOT_VALIDATED; } mRenderingState = RENDERING_STATE_PRESENTED; - mDevice->invalidate(); + mDevice->onRefresh(); return ret; } @@ -353,7 +348,7 @@ int32_t ExynosExternalDisplay::presentDisplay( */ setGeometryChanged(GEOMETRY_DISPLAY_FORCE_VALIDATE); - mDevice->invalidate(); + mDevice->onRefresh(); return HWC2_ERROR_NONE; } @@ -513,8 +508,7 @@ void ExynosExternalDisplay::handleHotplugEvent() { bool hpd_temp = 0; - if (mDevice->mCallbackInfos[HWC2_CALLBACK_HOTPLUG].callbackData == NULL) - return; + if (!mDevice->isCallbackAvailable(HWC2_CALLBACK_HOTPLUG)) return; char cablestate_name[MAX_DEV_NAME + 1]; cablestate_name[MAX_DEV_NAME] = '\0'; @@ -550,7 +544,7 @@ void ExynosExternalDisplay::handleHotplugEvent() closeExternalDisplay(); } hotplug(); - mDevice->invalidate(); + mDevice->onRefresh(); } } diff --git a/libhwc2.1/libhwcService/ExynosHWCService.cpp b/libhwc2.1/libhwcService/ExynosHWCService.cpp index 9c09ecb..7974fee 100644 --- a/libhwc2.1/libhwcService/ExynosHWCService.cpp +++ b/libhwc2.1/libhwcService/ExynosHWCService.cpp @@ -252,7 +252,7 @@ void ExynosHWCService::enableMPP(uint32_t physicalType, uint32_t physicalIndex, __func__, physicalType, physicalIndex, logicalIndex, enable); ExynosResourceManager::enableMPP(physicalType, physicalIndex, logicalIndex, enable); mHWCCtx->device->setGeometryChanged(GEOMETRY_DEVICE_CONFIG_CHANGED); - mHWCCtx->device->invalidate(); + mHWCCtx->device->onRefresh(); } void ExynosHWCService::setScaleDownRatio(uint32_t physicalType, @@ -262,7 +262,7 @@ void ExynosHWCService::setScaleDownRatio(uint32_t physicalType, __func__, physicalType, physicalIndex, logicalIndex, scaleDownRatio); ExynosResourceManager::setScaleDownRatio(physicalType, physicalIndex, logicalIndex, scaleDownRatio); mHWCCtx->device->setGeometryChanged(GEOMETRY_DEVICE_CONFIG_CHANGED); - mHWCCtx->device->invalidate(); + mHWCCtx->device->onRefresh(); } void ExynosHWCService::setLbeCtrl(uint32_t display_id, uint32_t state, uint32_t lux) { @@ -482,7 +482,7 @@ int32_t ExynosHWCService::setDisplayRCDLayerEnabled(uint32_t displayIndex, bool auto ret = primaryDisplay->setDebugRCDLayerEnabled(enable); mHWCCtx->device->setGeometryChanged(GEOMETRY_DEVICE_CONFIG_CHANGED); - mHWCCtx->device->invalidate(); + mHWCCtx->device->onRefresh(); return ret; } diff --git a/libhwc2.1/libhwchelper/ExynosHWCHelper.cpp b/libhwc2.1/libhwchelper/ExynosHWCHelper.cpp index 75762fc..60593c8 100644 --- a/libhwc2.1/libhwchelper/ExynosHWCHelper.cpp +++ b/libhwc2.1/libhwchelper/ExynosHWCHelper.cpp @@ -15,6 +15,7 @@ */ #include "ExynosHWCHelper.h" +#include <android-base/properties.h> #include <linux/videodev2.h> #include <linux/videodev2_exynos_media.h> #include <png.h> @@ -30,7 +31,6 @@ #include "ExynosLayer.h" #include "ExynosResourceRestriction.h" #include "VendorVideoAPI.h" -#include "android-base/properties.h" #include "exynos_sync.h" using vendor::graphics::BufferUsage; @@ -613,8 +613,7 @@ uint32_t getBytePerPixelOfPrimaryPlane(int format) { return 0; } -void setFenceName(int fenceFd, hwc_fence_type fenceType) -{ +void setFenceName(int fenceFd, HwcFenceType fenceType) { if (fenceFd >= 3) ioctl(fenceFd, SYNC_IOC_FENCE_NAME, fence_names[fenceType]); else if (fenceFd == -1) { @@ -753,10 +752,8 @@ int getBufLength(buffer_handle_t handle, uint32_t planerNum, size_t *length, int return NO_ERROR; } -int fence_close(int fence, ExynosDisplay* display, - hwc_fdebug_fence_type type, hwc_fdebug_ip_type ip) { - if (display != NULL) - setFenceInfo(fence, display, type, ip, FENCE_CLOSE); +int fence_close(int fence, ExynosDisplay* display, HwcFdebugFenceType type, HwcFdebugIpType ip) { + if (display != NULL) setFenceInfo(fence, display, type, ip, HwcFenceDirection::CLOSE); return hwcFdClose(fence); } @@ -784,7 +781,7 @@ int hwcFdClose(int fd) { return -1; } -int hwc_dup(int fd, ExynosDisplay* display, hwc_fdebug_fence_type type, hwc_fdebug_ip_type ip, +int hwc_dup(int fd, ExynosDisplay* display, HwcFdebugFenceType type, HwcFdebugIpType ip, bool pendingAllowed) { int dup_fd = -1; @@ -802,7 +799,7 @@ int hwc_dup(int fd, ExynosDisplay* display, hwc_fdebug_fence_type type, hwc_fdeb hwc_print_stack(); } - setFenceInfo(dup_fd, display, type, ip, FENCE_FROM, pendingAllowed); + setFenceInfo(dup_fd, display, type, ip, HwcFenceDirection::DUP, pendingAllowed, fd); FT_LOGD("duplicated %d from %d", dup_fd, fd); return dup_fd; @@ -815,157 +812,95 @@ int hwc_print_stack() { return 0; } -struct tm* getLocalTime(struct timeval tv) { - return (struct tm*)localtime((time_t*)&tv.tv_sec); +String8 getLocalTimeStr(struct timeval tv) { + struct tm* localTime = (struct tm*)localtime((time_t*)&tv.tv_sec); + return String8::format("%02d-%02d %02d:%02d:%02d.%03lu(%lu)", localTime->tm_mon + 1, + localTime->tm_mday, localTime->tm_hour, localTime->tm_min, + localTime->tm_sec, tv.tv_usec / 1000, + ((tv.tv_sec * 1000) + (tv.tv_usec / 1000))); } -void setFenceInfo(uint32_t fd, ExynosDisplay* display, hwc_fdebug_fence_type type, - hwc_fdebug_ip_type ip, uint32_t direction, bool pendingAllowed) { +void setFenceInfo(uint32_t fd, ExynosDisplay* display, HwcFdebugFenceType type, HwcFdebugIpType ip, + HwcFenceDirection direction, bool pendingAllowed, int32_t dupFrom) { if (!fence_valid(fd) || display == NULL) return; ExynosDevice* device = display->mDevice; - hwc_fence_info_t& info = device->mFenceInfos[fd]; + HwcFenceInfo& info = device->mFenceInfos[fd]; info.displayId = display->mDisplayId; - struct timeval tv; - - // FIXME: sync_fence_info, sync_pt_info are deprecated - // HWC guys should fix this. -#if 0 - if (exynosHWCControl.sysFenceLogging) { - struct sync_pt_info* pt_info = NULL; - info.sync_data = NULL; - if (info.sync_data != NULL) { - pt_info = sync_pt_info(info.sync_data, pt_info); - if (pt_info !=NULL) { - FT_LOGD("real name : %s status : %s pt_obj : %s pt_drv : %s", - info.sync_data->name, info.sync_data->status==1 ? "Active":"Signaled", - pt_info->obj_name, pt_info->driver_name); - } else { - FT_LOGD("real name : %s status : %d pt_info : %p", - info.sync_data->name, info.sync_data->status, pt_info); - } - sync_fence_info_free(info.sync_data); - } - } -#endif - - fenceTrace_t *trace = NULL; - switch(direction) { - case FENCE_FROM: - trace = &info.from; - info.to.type = FENCE_TYPE_UNDEFINED; - info.to.ip = FENCE_IP_UNDEFINED; - info.usage++; - break; - case FENCE_TO: - trace = &info.to; - info.usage--; - break; - case FENCE_DUP: - trace = &info.dup; - info.usage++; - break; - case FENCE_CLOSE: - trace = &info.close; - info.usage--; - if (info.usage < 0) info.usage = 0; - break; - default: - ALOGE("Fence trace : Undefined direction!"); - break; + if (info.leaking) { + return; } - if (trace != NULL) { - trace->type = type; - trace->ip = ip; - gettimeofday(&trace->time, NULL); - tv = trace->time; - trace->curFlag = 1; - FT_LOGW("FD : %d, direction : %d, type : %d, ip : %d", fd, direction, trace->type, trace->ip); - // device->fenceTracing.appendFormat("FD : %d, From : %s\n", fd, info.trace.fromName); + switch (direction) { + case HwcFenceDirection::FROM: + info.usage++; + break; + case HwcFenceDirection::TO: + info.usage--; + break; + case HwcFenceDirection::DUP: + info.usage++; + info.dupFrom = dupFrom; + break; + case HwcFenceDirection::CLOSE: + info.usage--; + if (info.usage < 0) info.usage = 0; + break; + case HwcFenceDirection::UPDATE: + break; + default: + ALOGE("Fence trace : Undefined direction!"); + break; } -#if 0 // To be used ? - struct tm* localTime = getLocalTime(tv); - device->fenceTracing.appendFormat("usage : %d, time:%02d-%02d %02d:%02d:%02d.%03lu(%lu)\n", info.usage, - localTime->tm_mon+1, localTime->tm_mday, - localTime->tm_hour, localTime->tm_min, - localTime->tm_sec, tv.tv_usec/1000, - ((tv.tv_sec * 1000) + (tv.tv_usec / 1000))); -#endif - - // Fence's usage count shuld be zero at end of frame(present done). - // This flag means usage count of the fence can be pended over frame. - info.pendingAllowed = pendingAllowed; - - info.last_dir = direction; - if (info.usage == 0) { device->mFenceInfos.erase(fd); + return; } else if (info.usage < 0) { ALOGE("%s : Invalid negative usage (%d) for Fence FD:%d", __func__, info.usage, fd); printLastFenceInfo(fd, display); } -} -void printLastFenceInfo(uint32_t fd, ExynosDisplay* display) { + HwcFenceTrace trace = {.direction = direction, .type = type, .ip = ip, .time = {0, 0}}; + + gettimeofday(&trace.time, NULL); - struct timeval tv; + info.traces.push_back(trace); + FT_LOGW("FD : %d, direction : %d, type : %d, ip : %d", fd, direction, type, ip); + + // Fence's usage count shuld be zero at end of frame(present done). + // This flag means usage count of the fence can be pended over frame. + info.pendingAllowed = pendingAllowed; +} + +void printLastFenceInfo(uint32_t fd, ExynosDisplay* display) { if (!fence_valid(fd)) return; ExynosDevice* device = display->mDevice; auto it = device->mFenceInfos.find(fd); if (it == device->mFenceInfos.end()) return; - hwc_fence_info_t& info = it->second; + HwcFenceInfo& info = it->second; FT_LOGD("---- Fence FD : %d, Display(%d) ----", fd, info.displayId); + FT_LOGD("usage: %d, dupFrom: %d, pendingAllowed: %d, leaking: %d", info.usage, info.dupFrom, + info.pendingAllowed, info.leaking); - fenceTrace_t *trace = NULL; - - switch (info.last_dir) { - case FENCE_FROM: - trace = &info.from; - break; - case FENCE_TO: - trace = &info.to; - break; - case FENCE_DUP: - trace = &info.dup; - break; - case FENCE_CLOSE: - trace = &info.close; - break; - default: - ALOGE("Fence trace : Undefined direction!"); - break; - } - - if (trace != NULL) { - FT_LOGD("Last state : %d, type(%d), ip(%d)", info.last_dir, trace->type, trace->ip); - tv = info.from.time; + for (const auto& trace : info.traces) { + FT_LOGD("> dir: %d, type: %d, ip: %d, time:%s", trace.direction, trace.type, trace.ip, + getLocalTimeStr(trace.time).string()); } - - FT_LOGD("from : %d, %d (cur : %d), to : %d, %d (cur : %d), hwc_dup : %d, %d (cur : " - "%d),hwc_close : %d, %d (cur : %d)", - info.from.type, info.from.ip, info.from.curFlag, info.to.type, info.to.ip, - info.to.curFlag, info.dup.type, info.dup.ip, info.dup.curFlag, info.close.type, - info.close.ip, info.close.curFlag); - - struct tm* localTime = getLocalTime(tv); - - FT_LOGD("usage : %d, time:%02d-%02d %02d:%02d:%02d.%03lu(%lu)", info.usage, - localTime->tm_mon + 1, localTime->tm_mday, localTime->tm_hour, localTime->tm_min, - localTime->tm_sec, tv.tv_usec / 1000, ((tv.tv_sec * 1000) + (tv.tv_usec / 1000))); } -void dumpFenceInfo(ExynosDisplay* display, int32_t __unused depth) { +void dumpFenceInfo(ExynosDisplay* display, int32_t count) { ExynosDevice* device = display->mDevice; - FT_LOGD("Dump fence ++"); + FT_LOGD("Dump fence (up to %d fences) ++", count); for (const auto& [fd, info] : device->mFenceInfos) { - if (!info.pendingAllowed) printLastFenceInfo(fd, display); + if (info.pendingAllowed) continue; + if (count-- <= 0) break; + printLastFenceInfo(fd, display); } FT_LOGD("Dump fence --"); } @@ -979,6 +914,7 @@ void printLeakFds(ExynosDisplay* display) { int cnt = 0; for (const auto& [fd, info] : fenceInfos) { + if (!info.leaking) continue; if (info.usage * sign > 0) { errString.appendFormat("%d,", fd); if ((++cnt % 10) == 0) { @@ -1018,32 +954,17 @@ void dumpNCheckLeak(ExynosDisplay* display, int32_t __unused depth) { bool fenceWarn(ExynosDisplay* display, uint32_t threshold) { ExynosDevice* device = display->mDevice; - uint32_t cnt = device->mFenceInfos.size(), r_cnt = 0; - - // FIXME: sync_fence_info() is deprecated - // HWC guys should fix this. -#if 0 - if (exynosHWCControl.sysFenceLogging) { - for (int i=3; i < MAX_FD_NUM; i++){ - struct sync_fence_info_data* data = nullptr; - data = NULL; //sync_fence_info(i); - if (data != NULL) { - r_cnt++; - sync_fence_info_free(data); - } - } - } -#endif - - if ((cnt>threshold) || (exynosHWCControl.fenceTracer > 0)) - dumpFenceInfo(display, 0); - - if (r_cnt>threshold) - ALOGE("Fence leak somewhare!!"); + uint32_t cnt = device->mFenceInfos.size(); - FT_LOGD("fence hwc : %d, real : %d", cnt, r_cnt); + if (cnt > threshold) { + ALOGE("Fence leak! -- the number of fences(%d) exceeds threshold(%d)", cnt, threshold); + int priv = exynosHWCControl.fenceTracer; + exynosHWCControl.fenceTracer = 3; + dumpFenceInfo(display, 10); + exynosHWCControl.fenceTracer = priv; + } - return (cnt>threshold) ? true : false; + return (cnt > threshold); } bool validateFencePerFrame(ExynosDisplay* display) { @@ -1068,47 +989,6 @@ bool validateFencePerFrame(ExynosDisplay* display) { return ret; } -void setFenceName(uint32_t fd, ExynosDisplay *display, - hwc_fdebug_fence_type type, hwc_fdebug_ip_type ip, - uint32_t direction, bool pendingAllowed) { - - ExynosDevice* device = display->mDevice; - if (!fence_valid(fd) || device == NULL) return; - - auto it = device->mFenceInfos.find(fd); - if (it == device->mFenceInfos.end()) return; - - hwc_fence_info_t& info = it->second; - info.displayId = display->mDisplayId; - fenceTrace_t *trace = NULL; - - switch(direction) { - case FENCE_FROM: - trace = &info.from; - break; - case FENCE_TO: - trace = &info.to; - break; - case FENCE_DUP: - trace = &info.dup; - break; - case FENCE_CLOSE: - trace = &info.close; - break; - default: - ALOGE("Fence trace : Undefined direction!"); - break; - } - - if (trace != NULL) { - trace->type = type; - trace->ip = ip; - FT_LOGD("FD : %d, direction : %d, type(%d), ip(%d) (changed)", fd, direction, type, ip); - } - - info.pendingAllowed = pendingAllowed; -} - String8 getMPPStr(int typeId) { if (typeId < MPP_DPP_NUM){ int cnt = sizeof(AVAILABLE_OTF_MPP_UNITS)/sizeof(exynos_mpp_t); diff --git a/libhwc2.1/libhwchelper/ExynosHWCHelper.h b/libhwc2.1/libhwchelper/ExynosHWCHelper.h index 69d9fe1..6fb9ea5 100644 --- a/libhwc2.1/libhwchelper/ExynosHWCHelper.h +++ b/libhwc2.1/libhwchelper/ExynosHWCHelper.h @@ -21,6 +21,7 @@ #include <utils/String8.h> #include <fstream> +#include <list> #include <optional> #include <sstream> #include <string> @@ -258,7 +259,7 @@ const format_description_t exynos_format_desc[] = { constexpr size_t FORMAT_MAX_CNT = sizeof(exynos_format_desc) / sizeof(format_description); -typedef enum hwc_fdebug_fence_type_t { +enum HwcFdebugFenceType { FENCE_TYPE_SRC_RELEASE = 1, FENCE_TYPE_SRC_ACQUIRE = 2, FENCE_TYPE_DST_RELEASE = 3, @@ -271,9 +272,9 @@ typedef enum hwc_fdebug_fence_type_t { FENCE_TYPE_READBACK_RELEASE = 10, FENCE_TYPE_ALL = 11, FENCE_TYPE_UNDEFINED = 100 -} hwc_fdebug_fence_type; +}; -typedef enum hwc_fdebug_ip_type_t { +enum HwcFdebugIpType { FENCE_IP_DPP = 0, FENCE_IP_MSC = 1, FENCE_IP_G2D = 2, @@ -281,30 +282,30 @@ typedef enum hwc_fdebug_ip_type_t { FENCE_IP_LAYER = 4, FENCE_IP_ALL = 5, FENCE_IP_UNDEFINED = 100 -} hwc_fdebug_ip_type; - -typedef enum hwc_fence_type_t { - FENCE_LAYER_RELEASE_DPP = 0, - FENCE_LAYER_RELEASE_MPP = 1, - FENCE_LAYER_RELEASE_MSC = 2, - FENCE_LAYER_RELEASE_G2D = 3, - FENCE_DPP_HW_STATE = 4, - FENCE_MSC_HW_STATE = 5, - FENCE_G2D_HW_STATE = 6, - FENCE_MSC_SRC_LAYER = 7, - FENCE_G2D_SRC_LAYER = 8, - FENCE_MPP_DST_DPP = 9, - FENCE_MSC_DST_DPP = 10, - FENCE_G2D_DST_DPP = 11, - FENCE_DPP_SRC_MPP = 12, - FENCE_DPP_SRC_MSC = 13, - FENCE_DPP_SRC_G2D = 14, - FENCE_DPP_SRC_LAYER = 15, - FENCE_MPP_FREE_BUF_ACQUIRE = 16, - FENCE_MPP_FREE_BUF_RELEASE = 17, - FENCE_RETIRE = 18, +}; + +enum HwcFenceType { + FENCE_LAYER_RELEASE_DPP = 0, + FENCE_LAYER_RELEASE_MPP = 1, + FENCE_LAYER_RELEASE_MSC = 2, + FENCE_LAYER_RELEASE_G2D = 3, + FENCE_DPP_HW_STATE = 4, + FENCE_MSC_HW_STATE = 5, + FENCE_G2D_HW_STATE = 6, + FENCE_MSC_SRC_LAYER = 7, + FENCE_G2D_SRC_LAYER = 8, + FENCE_MPP_DST_DPP = 9, + FENCE_MSC_DST_DPP = 10, + FENCE_G2D_DST_DPP = 11, + FENCE_DPP_SRC_MPP = 12, + FENCE_DPP_SRC_MSC = 13, + FENCE_DPP_SRC_G2D = 14, + FENCE_DPP_SRC_LAYER = 15, + FENCE_MPP_FREE_BUF_ACQUIRE = 16, + FENCE_MPP_FREE_BUF_RELEASE = 17, + FENCE_RETIRE = 18, FENCE_MAX -} hwc_fence_type; +}; enum { EXYNOS_ERROR_NONE = 0, @@ -446,12 +447,11 @@ uint32_t getBufferNumOfFormat(int format, uint32_t compressType); uint32_t getPlaneNumOfFormat(int format, uint32_t compressType); uint32_t getBytePerPixelOfPrimaryPlane(int format); -int fence_close(int fence, ExynosDisplay* display, - hwc_fdebug_fence_type type, hwc_fdebug_ip_type ip); +int fence_close(int fence, ExynosDisplay *display, HwcFdebugFenceType type, HwcFdebugIpType ip); bool fence_valid(int fence); int hwcFdClose(int fd); -int hwc_dup(int fd, ExynosDisplay *display, hwc_fdebug_fence_type type, hwc_fdebug_ip_type ip, +int hwc_dup(int fd, ExynosDisplay *display, HwcFdebugFenceType type, HwcFdebugIpType ip, bool pendingAllowed = false); int hwc_print_stack(); @@ -482,37 +482,29 @@ inline T pixel_align(const T x, const uint32_t a) { uint32_t getExynosBufferYLength(uint32_t width, uint32_t height, int format); int getBufLength(buffer_handle_t handle, uint32_t planer_num, size_t *length, int format, uint32_t width, uint32_t height); -//class hwc_fence_info(sync_fence_info_data* data, sync_pt_info* info) { -struct tm* getHwcFenceTime(); - -enum { - FENCE_FROM = 0, - FENCE_TO, - FENCE_DUP, - FENCE_CLOSE, +enum class HwcFenceDirection { + FROM = 0, + TO, + DUP, + CLOSE, + UPDATE, }; -typedef struct fenceTrace { - hwc_fdebug_fence_type type = FENCE_TYPE_UNDEFINED; - hwc_fdebug_ip_type ip = FENCE_IP_UNDEFINED; +struct HwcFenceTrace { + HwcFenceDirection direction = HwcFenceDirection::FROM; + HwcFdebugFenceType type = FENCE_TYPE_UNDEFINED; + HwcFdebugIpType ip = FENCE_IP_UNDEFINED; struct timeval time = {0, 0}; - int32_t curFlag = 0; -} fenceTrace_t; +}; -typedef struct hwc_fence_info { +struct HwcFenceInfo { uint32_t displayId = HWC_DISPLAY_PRIMARY; - struct sync_fence_info_data *sync_data = nullptr; - struct sync_pt_info *pt_info = nullptr; - fenceTrace_t from = {}; - fenceTrace_t to = {}; - fenceTrace_t dup = {}; - fenceTrace_t close = {}; int32_t usage = 0; - int32_t curFlag = 0; - uint32_t last_dir = 0; + int32_t dupFrom = -1; bool pendingAllowed = false; bool leaking = false; -} hwc_fence_info_t; + std::list<HwcFenceTrace> traces = {}; +}; class funcReturnCallback { public: @@ -522,15 +514,13 @@ class funcReturnCallback { const std::function<void(void)> mCb; }; -void setFenceName(int fenceFd, hwc_fence_type fenceType); -void setFenceName(uint32_t fd, ExynosDisplay *display, - hwc_fdebug_fence_type type, hwc_fdebug_ip_type ip, - uint32_t direction, bool pendingAllowed = false); -void setFenceInfo(uint32_t fd, ExynosDisplay *display, - hwc_fdebug_fence_type type, hwc_fdebug_ip_type ip, - uint32_t direction, bool pendingAllowed = false); +String8 getLocalTimeStr(struct timeval tv); + +void setFenceName(int fenceFd, HwcFenceType fenceType); +void setFenceInfo(uint32_t fd, ExynosDisplay *display, HwcFdebugFenceType type, HwcFdebugIpType ip, + HwcFenceDirection direction, bool pendingAllowed = false, int32_t dupFrom = -1); void printLastFenceInfo(uint32_t fd, ExynosDisplay *display); -void dumpFenceInfo(ExynosDisplay *display, int32_t __unused depth); +void dumpFenceInfo(ExynosDisplay *display, int32_t count); bool fenceWarn(ExynosDisplay *display, uint32_t threshold); void printLeakFds(ExynosDisplay *display); bool validateFencePerFrame(ExynosDisplay *display); diff --git a/libhwc2.1/libmaindisplay/ExynosPrimaryDisplay.cpp b/libhwc2.1/libmaindisplay/ExynosPrimaryDisplay.cpp index 35253a9..633b1d7 100644 --- a/libhwc2.1/libmaindisplay/ExynosPrimaryDisplay.cpp +++ b/libhwc2.1/libmaindisplay/ExynosPrimaryDisplay.cpp @@ -116,10 +116,9 @@ ExynosPrimaryDisplay::ExynosPrimaryDisplay(uint32_t index, ExynosDevice *device) mEarlyWakeupDispFd = fopen(EARLY_WAKUP_NODE_0_BASE, "w"); if (mEarlyWakeupDispFd == nullptr) ALOGE("open %s failed! %s", EARLY_WAKUP_NODE_0_BASE, strerror(errno)); - mBrightnessController = - std::make_unique<BrightnessController>(mIndex, - [this]() { mDevice->invalidate(); }, - [this]() { updatePresentColorConversionInfo(); }); + mBrightnessController = std::make_unique<BrightnessController>( + mIndex, [this]() { mDevice->onRefresh(); }, + [this]() { updatePresentColorConversionInfo(); }); } ExynosPrimaryDisplay::~ExynosPrimaryDisplay() @@ -496,6 +495,22 @@ int32_t ExynosPrimaryDisplay::SetCurrentPanelGammaSource(const DisplayType type, int32_t ExynosPrimaryDisplay::setLhbmState(bool enabled) { ATRACE_CALL(); + if (enabled) { + ATRACE_NAME("wait for peak refresh rate"); + for (int32_t i = 0; i <= kLhbmWaitForPeakRefreshRate; i++) { + if (!isCurrentPeakRefreshRate()) { + if (i == kLhbmWaitForPeakRefreshRate) { + ALOGW("setLhbmState(on) wait for peak refresh rate timeout !"); + return TIMED_OUT; + } + usleep(mVsyncPeriod / 1000 + 1); + } else { + ALOGI_IF(i, "waited %d vsync to reach peak refresh rate", i); + break; + } + } + } + requestLhbm(enabled); ALOGI("setLhbmState =%d", enabled); @@ -511,7 +526,7 @@ int32_t ExynosPrimaryDisplay::setLhbmState(bool enabled) { mDisplayInterface->waitVBlank(); ATRACE_NAME("frames to reach LHBM peak brightness"); for (int32_t i = mFramesToReachLhbmPeakBrightness; i > 0; i--) { - mDevice->invalidate(); + mDevice->onRefresh(); mDisplayInterface->waitVBlank(); } } diff --git a/libhwc2.1/libmaindisplay/ExynosPrimaryDisplay.h b/libhwc2.1/libmaindisplay/ExynosPrimaryDisplay.h index e544749..c4d79ea 100644 --- a/libhwc2.1/libmaindisplay/ExynosPrimaryDisplay.h +++ b/libhwc2.1/libmaindisplay/ExynosPrimaryDisplay.h @@ -103,6 +103,8 @@ class ExynosPrimaryDisplay : public ExynosDisplay { bool mLhbmOn; bool mLhbmChanged; int32_t mFramesToReachLhbmPeakBrightness; + // wait num of vsync periods for peak refresh rate + static constexpr uint32_t kLhbmWaitForPeakRefreshRate = 10; std::mutex lhbm_mutex_; std::condition_variable lhbm_cond_; diff --git a/libhwc2.1/libresource/ExynosMPP.cpp b/libhwc2.1/libresource/ExynosMPP.cpp index 09c937d..740cec7 100644 --- a/libhwc2.1/libresource/ExynosMPP.cpp +++ b/libhwc2.1/libresource/ExynosMPP.cpp @@ -1239,12 +1239,12 @@ int32_t ExynosMPP::setupLayer(exynos_mpp_img_info *srcImgInfo, struct exynos_ima if (mPhysicalType == MPP_G2D) { setFenceName(srcImgInfo->acrylicAcquireFenceFd, FENCE_G2D_SRC_LAYER); - setFenceInfo(srcImgInfo->acrylicAcquireFenceFd, mAssignedDisplay, - FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_G2D, FENCE_TO); + setFenceInfo(srcImgInfo->acrylicAcquireFenceFd, mAssignedDisplay, FENCE_TYPE_SRC_ACQUIRE, + FENCE_IP_G2D, HwcFenceDirection::TO); } else if (mPhysicalType == MPP_MSC) { setFenceName(srcImgInfo->acrylicAcquireFenceFd, FENCE_MSC_SRC_LAYER); - setFenceInfo(srcImgInfo->acrylicAcquireFenceFd, mAssignedDisplay, - FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_MSC, FENCE_TO); + setFenceInfo(srcImgInfo->acrylicAcquireFenceFd, mAssignedDisplay, FENCE_TYPE_SRC_ACQUIRE, + FENCE_IP_MSC, HwcFenceDirection::TO); } else { MPP_LOGE("%s:: invalid mPhysicalType(%d)", __func__, mPhysicalType); } @@ -1367,13 +1367,13 @@ int32_t ExynosMPP::setupDst(exynos_mpp_img_info *dstImgInfo) if (mPhysicalType == MPP_G2D) { setFenceName(dstImgInfo->acrylicAcquireFenceFd, FENCE_G2D_DST_DPP); /* Might be closed next frame */ - setFenceInfo(dstImgInfo->acrylicAcquireFenceFd, mAssignedDisplay, - FENCE_TYPE_DST_ACQUIRE, FENCE_IP_G2D, FENCE_TO); + setFenceInfo(dstImgInfo->acrylicAcquireFenceFd, mAssignedDisplay, FENCE_TYPE_DST_ACQUIRE, + FENCE_IP_G2D, HwcFenceDirection::TO); } else if (mPhysicalType == MPP_MSC) { setFenceName(dstImgInfo->acrylicAcquireFenceFd, FENCE_MSC_DST_DPP); /* Might be closed next frame */ - setFenceInfo(dstImgInfo->acrylicAcquireFenceFd, mAssignedDisplay, - FENCE_TYPE_DST_ACQUIRE, FENCE_IP_MSC, FENCE_TO); + setFenceInfo(dstImgInfo->acrylicAcquireFenceFd, mAssignedDisplay, FENCE_TYPE_DST_ACQUIRE, + FENCE_IP_MSC, HwcFenceDirection::TO); } else { MPP_LOGE("%s:: invalid mPhysicalType(%d)", __func__, mPhysicalType); } @@ -1512,23 +1512,23 @@ int32_t ExynosMPP::doPostProcessingInternal() // set fence informations from acryl if (mPhysicalType == MPP_G2D) { - setFenceInfo(releaseFences[dstBufIdx], mAssignedDisplay, - FENCE_TYPE_DST_ACQUIRE, FENCE_IP_G2D, FENCE_FROM); + setFenceInfo(releaseFences[dstBufIdx], mAssignedDisplay, FENCE_TYPE_DST_ACQUIRE, + FENCE_IP_G2D, HwcFenceDirection::FROM); if (usingFenceCnt > 1) { for(size_t i = 0; i < sourceNum; i++) { // TODO DPU release fence is tranferred to m2mMPP's source layer fence - setFenceInfo(releaseFences[i], mAssignedDisplay, - FENCE_TYPE_SRC_RELEASE, FENCE_IP_G2D, FENCE_FROM); + setFenceInfo(releaseFences[i], mAssignedDisplay, FENCE_TYPE_SRC_RELEASE, + FENCE_IP_G2D, HwcFenceDirection::FROM); } } } else if (mPhysicalType == MPP_MSC) { - setFenceInfo(releaseFences[dstBufIdx], mAssignedDisplay, - FENCE_TYPE_DST_ACQUIRE, FENCE_IP_MSC, FENCE_FROM); + setFenceInfo(releaseFences[dstBufIdx], mAssignedDisplay, FENCE_TYPE_DST_ACQUIRE, + FENCE_IP_MSC, HwcFenceDirection::FROM); if (usingFenceCnt > 1) { for(size_t i = 0; i < sourceNum; i++) { // TODO DPU release fence is tranferred to m2mMPP's source layer fence - setFenceInfo(releaseFences[i], mAssignedDisplay, - FENCE_TYPE_SRC_RELEASE, FENCE_IP_MSC, FENCE_FROM); + setFenceInfo(releaseFences[i], mAssignedDisplay, FENCE_TYPE_SRC_RELEASE, + FENCE_IP_MSC, HwcFenceDirection::FROM); } } } else { diff --git a/libhwc2.1/libvirtualdisplay/ExynosVirtualDisplay.cpp b/libhwc2.1/libvirtualdisplay/ExynosVirtualDisplay.cpp index a9cadc3..d6ce85f 100644 --- a/libhwc2.1/libvirtualdisplay/ExynosVirtualDisplay.cpp +++ b/libhwc2.1/libvirtualdisplay/ExynosVirtualDisplay.cpp @@ -348,7 +348,8 @@ int ExynosVirtualDisplay::setReleaseFences() ret = ExynosDisplay::setReleaseFences(); mOutputBufferReleaseFenceFd = hwcCheckFenceDebug(this, FENCE_TYPE_RETIRE, FENCE_IP_G2D, mExynosCompositionInfo.mAcquireFence); - setFenceInfo(mExynosCompositionInfo.mAcquireFence, this, FENCE_TYPE_RETIRE, FENCE_IP_G2D, FENCE_TO); + setFenceInfo(mExynosCompositionInfo.mAcquireFence, this, FENCE_TYPE_RETIRE, FENCE_IP_G2D, + HwcFenceDirection::TO); mExynosCompositionInfo.mAcquireFence = -1; /* mClientCompositionInfo.mAcquireFence is delivered to G2D */ mClientCompositionInfo.mAcquireFence = -1; @@ -505,12 +506,14 @@ void ExynosVirtualDisplay::handleAcquireFence() if (layer->mValidateCompositionType == HWC2_COMPOSITION_DEVICE || layer->mValidateCompositionType == HWC2_COMPOSITION_EXYNOS) { layer->mReleaseFence = layer->mAcquireFence; - setFenceInfo(layer->mAcquireFence, this, FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_LAYER, FENCE_TO); + setFenceInfo(layer->mAcquireFence, this, FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_LAYER, + HwcFenceDirection::TO); layer->mAcquireFence = -1; } } mClientCompositionInfo.mReleaseFence = mClientCompositionInfo.mAcquireFence; - setFenceInfo(mClientCompositionInfo.mAcquireFence, this, FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_FB, FENCE_TO); + setFenceInfo(mClientCompositionInfo.mAcquireFence, this, FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_FB, + HwcFenceDirection::TO); mClientCompositionInfo.mAcquireFence = -1; mOutputBufferReleaseFenceFd = mOutputBufferAcquireFenceFd; diff --git a/libhwc2.1/pixel-display-default.xml b/libhwc2.1/pixel-display-default.xml index 31c569e..fc10d6a 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>4</version> + <version>6</version> <fqname>IDisplay/default</fqname> </hal> </manifest> diff --git a/libhwc2.1/pixel-display.cpp b/libhwc2.1/pixel-display.cpp index 409cfe0..629a137 100644 --- a/libhwc2.1/pixel-display.cpp +++ b/libhwc2.1/pixel-display.cpp @@ -162,6 +162,21 @@ ndk::ScopedAStatus Display::setRefreshRateThrottle(int delayMs, int *_aidl_retur } return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); } + +ndk::ScopedAStatus Display::histogramSample(const RoiRect &roi, const Weight &weight, + HistogramPos pos, Priority pri, + std::vector<char16_t> *histogrambuffer, + HistogramErrorCode *_aidl_return) { + return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); +} + +ndk::ScopedAStatus Display::getPanelCalibrationStatus(PanelCalibrationStatus *_aidl_return){ + if (mDevice) { + *_aidl_return = mDevice->getPanelCalibrationStatus(); + 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 f0fd627..4ca69d7 100644 --- a/libhwc2.1/pixel-display.h +++ b/libhwc2.1/pixel-display.h @@ -28,6 +28,11 @@ namespace pixel { namespace display { using aidl::android::hardware::common::NativeHandle; +using RoiRect = ::aidl::android::hardware::graphics::common::Rect; +using Weight = ::aidl::com::google::hardware::pixel::display::Weight; +using HistogramPos = ::aidl::com::google::hardware::pixel::display::HistogramPos; +using Priority = ::aidl::com::google::hardware::pixel::display::Priority; +using HistogramErrorCode = ::aidl::com::google::hardware::pixel::display::HistogramErrorCode; // Default implementation class Display : public BnDisplay { @@ -49,6 +54,10 @@ public: int *_aidl_return) override; ndk::ScopedAStatus setMinIdleRefreshRate(int fps, int *_aidl_return) override; ndk::ScopedAStatus setRefreshRateThrottle(int delayMs, int *_aidl_return) override; + ndk::ScopedAStatus histogramSample(const RoiRect &roi, const Weight &weight, HistogramPos pos, + Priority pri, std::vector<char16_t> *histogrambuffer, + HistogramErrorCode *_aidl_return) override; + ndk::ScopedAStatus getPanelCalibrationStatus(PanelCalibrationStatus *_aidl_return) override; private: ExynosDevice *mDevice = nullptr; |