diff --git a/common/display/vblankeventhandler.cpp b/common/display/vblankeventhandler.cpp index 28d75c309..79be495ca 100644 --- a/common/display/vblankeventhandler.cpp +++ b/common/display/vblankeventhandler.cpp @@ -94,8 +94,20 @@ void VblankEventHandler::HandlePageFlipEvent(unsigned int sec, spin_lock_.lock(); if (enabled_ && callback_) { callback_->Callback(display_, timestamp); + callbacked_vsync_++; + } else { + IPAGEFLIPEVENTTRACE("1 VSYNC is skipped at %d because VSYNC is disabled by SF.", timestamp); + missed_vsync_++; } spin_lock_.unlock(); + + if (timestamp - sec_start_ >= 1000000000) { + IPAGEFLIPEVENTTRACE("Missed VSYNC: %d, Frame rate: %d", + missed_vsync_, callbacked_vsync_); + sec_start_ = timestamp; + callbacked_vsync_ = 0; + missed_vsync_ = 0; + } } void VblankEventHandler::HandleWait() { diff --git a/common/display/vblankeventhandler.h b/common/display/vblankeventhandler.h index 9b89806ff..d0c89b1af 100644 --- a/common/display/vblankeventhandler.h +++ b/common/display/vblankeventhandler.h @@ -62,6 +62,9 @@ class VblankEventHandler : public HWCThread { int fd_; int64_t last_timestamp_; + int64_t sec_start_ = 0; + size_t callbacked_vsync_ = 0; + size_t missed_vsync_ = 0; drmVBlankSeqType type_; DisplayQueue* queue_; }; diff --git a/common/utils/hwctrace.h b/common/utils/hwctrace.h index 93d060b48..4efcfc227 100644 --- a/common/utils/hwctrace.h +++ b/common/utils/hwctrace.h @@ -34,7 +34,7 @@ extern "C" { // #define ENABLE_DISPLAY_DUMP 1 // #define ENABLE_DISPLAY_MANAGER_TRACING 1 -// #define ENABLE_PAGE_FLIP_EVENT_TRACING 1 +#define ENABLE_PAGE_FLIP_EVENT_TRACING 1 // #define ENABLE_HOT_PLUG_EVENT_TRACING 1 // #define ENABLE_MOSAIC_DISPLAY_TRACING 1 // #define FUNCTION_CALL_TRACING 1 diff --git a/wsi/drm/drmdisplay.cpp b/wsi/drm/drmdisplay.cpp index 59c7feb11..921119962 100644 --- a/wsi/drm/drmdisplay.cpp +++ b/wsi/drm/drmdisplay.cpp @@ -345,6 +345,64 @@ bool DrmDisplay::GetDisplayAttribute(uint32_t config /*config*/, return status; } +uint32_t DrmDisplay::FindPreferedDisplayMode(size_t modes_size) { + uint32_t prefer_display_mode = 0; + if (modes_size > 1) { + SPIN_LOCK(display_lock_); + for (size_t i = 0; i < modes_size; i++) { + // There is only one preferred mode per connector. + if (modes_[i].type & DRM_MODE_TYPE_PREFERRED) { + prefer_display_mode = i; + IHOTPLUGEVENTTRACE("Preferred display config is found. index: %d", i); + break; + } + } + SPIN_UNLOCK(display_lock_); + } + if (prefer_display_mode_ != prefer_display_mode) + prefer_display_mode_ = prefer_display_mode; + return prefer_display_mode; +} + +uint32_t DrmDisplay::FindPerformaceDisplayMode(size_t modes_size) { + uint32_t perf_display_mode; + perf_display_mode = prefer_display_mode_; + if (modes_size >= prefer_display_mode_) { + int32_t prefer_width = 0, prefer_height = 0, prefer_interval = 0; + int32_t perf_width = 0, perf_height = 0, perf_interval = 0, + previous_perf_interval = 0; + GetDisplayAttribute(prefer_display_mode_, HWCDisplayAttribute::kWidth, + &prefer_width); + GetDisplayAttribute(prefer_display_mode_, HWCDisplayAttribute::kHeight, + &prefer_height); + GetDisplayAttribute(prefer_display_mode_, HWCDisplayAttribute::kRefreshRate, + &prefer_interval); + previous_perf_interval = prefer_interval; + IHOTPLUGEVENTTRACE("Preferred width:%d, height:%d, interval:%d", + prefer_width, prefer_height, prefer_interval); + for (size_t i = 0; i < modes_size; i++) { + if (i != prefer_display_mode_) { + GetDisplayAttribute(i, HWCDisplayAttribute::kWidth, &perf_width); + GetDisplayAttribute(i, HWCDisplayAttribute::kHeight, &perf_height); + GetDisplayAttribute(i, HWCDisplayAttribute::kRefreshRate, + &perf_interval); + IHOTPLUGEVENTTRACE("EDIP item width:%d, height:%d, rate:%d", perf_width, + perf_height, perf_interval); + if (prefer_width == perf_width && prefer_height == perf_height && + prefer_interval > perf_interval && + previous_perf_interval > perf_interval) { + perf_display_mode = i; + previous_perf_interval = perf_interval; + } + } + } + } + if (perf_display_mode_ != perf_display_mode) + perf_display_mode_ = perf_display_mode; + IHOTPLUGEVENTTRACE("PerformaceDisplayMode: %d", perf_display_mode_); + return perf_display_mode; +} + bool DrmDisplay::GetDisplayConfigs(uint32_t *num_configs, uint32_t *configs) { if (!num_configs) return false; @@ -353,12 +411,20 @@ bool DrmDisplay::GetDisplayConfigs(uint32_t *num_configs, uint32_t *configs) { size_t modes_size = modes_.size(); SPIN_UNLOCK(display_lock_); - if (modes_size == 0) { + //if (modes_size == 0) { return PhysicalDisplay::GetDisplayConfigs(num_configs, configs); - } + //} + + uint32_t prefer_display_mode = prefer_display_mode_; + uint32_t perf_display_mode = perf_display_mode_; if (!configs) { - *num_configs = modes_size; + prefer_display_mode = FindPreferedDisplayMode(modes_size); + perf_display_mode = FindPerformaceDisplayMode(modes_size); + if (prefer_display_mode == perf_display_mode) + *num_configs = 1; + else + *num_configs = 2; IHOTPLUGEVENTTRACE( "GetDisplayConfigs: Total Configs: %d pipe: %d display: %p", *num_configs, pipe_, this); @@ -369,9 +435,9 @@ bool DrmDisplay::GetDisplayConfigs(uint32_t *num_configs, uint32_t *configs) { "GetDisplayConfigs: Populating Configs: %d pipe: %d display: %p", *num_configs, pipe_, this); - uint32_t size = *num_configs > modes_size ? modes_size : *num_configs; - for (uint32_t i = 0; i < size; i++) - configs[i] = i; + configs[0] = prefer_display_mode; + if (prefer_display_mode != perf_display_mode) + configs[1] = perf_display_mode; return true; } diff --git a/wsi/drm/drmdisplay.h b/wsi/drm/drmdisplay.h index e21a0f5dd..3dffe9cd0 100644 --- a/wsi/drm/drmdisplay.h +++ b/wsi/drm/drmdisplay.h @@ -173,6 +173,9 @@ class DrmDisplay : public PhysicalDisplay { void TraceFirstCommit(); + uint32_t FindPreferedDisplayMode(size_t modes_size); + uint32_t FindPerformaceDisplayMode(size_t modes_size); + uint32_t crtc_id_ = 0; uint32_t mmWidth_ = 0; uint32_t mmHeight_ = 0; @@ -200,6 +203,8 @@ class DrmDisplay : public PhysicalDisplay { uint32_t flags_ = DRM_MODE_ATOMIC_ALLOW_MODESET; bool planes_updated_ = false; bool first_commit_ = false; + uint32_t prefer_display_mode_ = 0; + uint32_t perf_display_mode_ = 0; std::string display_name_ = ""; HWCContentProtection current_protection_support_ = HWCContentProtection::kUnSupported; diff --git a/wsi/physicaldisplay.cpp b/wsi/physicaldisplay.cpp index 07e94b035..3a14eca7a 100644 --- a/wsi/physicaldisplay.cpp +++ b/wsi/physicaldisplay.cpp @@ -17,6 +17,8 @@ #include "physicaldisplay.h" #include +#include +#include #include #include @@ -293,6 +295,19 @@ bool PhysicalDisplay::Present(std::vector &source_layers, CTRACE(); SPIN_LOCK(modeset_lock_); + struct timeval te; + gettimeofday(&te, NULL); // get current time + long long milliseconds = + te.tv_sec * 1000LL + te.tv_usec / 1000; // calculate milliseconds + frame_rate_++; + IPAGEFLIPEVENTTRACE("Present at %lld", milliseconds); + if (milliseconds - last_timestamp_ - 1000ll >=0) { + IPAGEFLIPEVENTTRACE("Frame rate: %d, frame duration: %f", frame_rate_, + static_cast(milliseconds - last_timestamp_)); + last_timestamp_ = milliseconds; + frame_rate_ = 0; + } + bool handle_hotplug_notifications = false; if (display_state_ & kHandlePendingHotPlugNotifications) { display_state_ &= ~kHandlePendingHotPlugNotifications; diff --git a/wsi/physicaldisplay.h b/wsi/physicaldisplay.h index a9c44b184..3f7dd1e7a 100644 --- a/wsi/physicaldisplay.h +++ b/wsi/physicaldisplay.h @@ -310,6 +310,8 @@ class PhysicalDisplay : public NativeDisplay, public DisplayPlaneHandler { std::vector clones_; uint32_t config_ = DEFAULT_CONFIG_ID; bool bypassClientCTM_ = false; + long long last_timestamp_ = 0; + size_t frame_rate_ = 0; }; } // namespace hwcomposer