diff --git a/common/display/displayqueue.cpp b/common/display/displayqueue.cpp index b87095054..e7d9095c5 100644 --- a/common/display/displayqueue.cpp +++ b/common/display/displayqueue.cpp @@ -957,6 +957,11 @@ int DisplayQueue::RegisterVsyncCallback(std::shared_ptr callback, return vblank_handler_->RegisterCallback(callback, display_id); } +int DisplayQueue::RegisterVsyncPeriodCallback(std::shared_ptr callback, + uint32_t display_id) { + return vblank_handler_->RegisterCallback(callback, display_id); +} + void DisplayQueue::RegisterRefreshCallback( std::shared_ptr callback, uint32_t display_id) { idle_tracker_.idle_lock_.lock(); diff --git a/common/display/displayqueue.h b/common/display/displayqueue.h index fe30507cd..7e86fd64a 100644 --- a/common/display/displayqueue.h +++ b/common/display/displayqueue.h @@ -85,7 +85,8 @@ class DisplayQueue { void RestoreVideoDefaultDeinterlace(); int RegisterVsyncCallback(std::shared_ptr callback, uint32_t display_id); - + int RegisterVsyncPeriodCallback(std::shared_ptr callback, + uint32_t display_id); void RegisterRefreshCallback(std::shared_ptr callback, uint32_t display_id); diff --git a/common/display/vblankeventhandler.cpp b/common/display/vblankeventhandler.cpp index 28d75c309..65a0a06dc 100644 --- a/common/display/vblankeventhandler.cpp +++ b/common/display/vblankeventhandler.cpp @@ -32,6 +32,7 @@ VblankEventHandler::VblankEventHandler(DisplayQueue* queue) enabled_(false), fd_(-1), last_timestamp_(-1), + previous_timestamp_(-1), queue_(queue) { memset(&type_, 0, sizeof(type_)); } @@ -69,6 +70,16 @@ int VblankEventHandler::RegisterCallback( return 0; } +int VblankEventHandler::RegisterCallback( + std::shared_ptr callback, uint32_t display) { + spin_lock_.lock(); + callback_2_4_ = callback; + display_ = display; + last_timestamp_ = -1; + spin_lock_.unlock(); + return 0; +} + int VblankEventHandler::VSyncControl(bool enabled) { IPAGEFLIPEVENTTRACE("VblankEventHandler VSyncControl enabled %d", enabled); if (enabled_ == enabled) @@ -87,14 +98,20 @@ void VblankEventHandler::HandlePageFlipEvent(unsigned int sec, int64_t timestamp = ((int64_t)sec * kOneSecondNs) + ((int64_t)usec * 1000); IPAGEFLIPEVENTTRACE("HandleVblankCallBack Frame Time %f", static_cast(timestamp - last_timestamp_) / (1000)); + int64_t vperiod = timestamp - previous_timestamp_; last_timestamp_ = timestamp; IPAGEFLIPEVENTTRACE("Callback called from HandlePageFlipEvent. %lu", timestamp); spin_lock_.lock(); if (enabled_ && callback_) { - callback_->Callback(display_, timestamp); + if(abs(vperiod - vperiod_) > (13333333 - 11111111) && previous_timestamp_ != -1) + callback_2_4_->Callback(display_, timestamp, vperiod); + else + callback_->Callback(display_, timestamp); } + vperiod_ = vperiod; + previous_timestamp_ = timestamp; spin_lock_.unlock(); } diff --git a/common/display/vblankeventhandler.h b/common/display/vblankeventhandler.h index 9b89806ff..7834cfa26 100644 --- a/common/display/vblankeventhandler.h +++ b/common/display/vblankeventhandler.h @@ -45,6 +45,9 @@ class VblankEventHandler : public HWCThread { int RegisterCallback(std::shared_ptr callback, uint32_t display_id); + int RegisterCallback(std::shared_ptr callback, + uint32_t display_id); + int VSyncControl(bool enabled); protected: @@ -56,12 +59,15 @@ class VblankEventHandler : public HWCThread { // actually call the hook) and we don't want the memory freed until we're // done std::shared_ptr callback_ = NULL; + std::shared_ptr callback_2_4_ = NULL; SpinLock spin_lock_; uint32_t display_; + int64_t vperiod_; bool enabled_ = false; int fd_; int64_t last_timestamp_; + int64_t previous_timestamp_; drmVBlankSeqType type_; DisplayQueue* queue_; }; diff --git a/os/android/iahwc2.cpp b/os/android/iahwc2.cpp index 92b973954..6318da669 100644 --- a/os/android/iahwc2.cpp +++ b/os/android/iahwc2.cpp @@ -57,6 +57,24 @@ class IAVsyncCallback : public hwcomposer::VsyncCallback { hwc2_function_pointer_t hook_; }; +class IAVsyncPeriodCallback : public hwcomposer::VsyncPeriodCallback { + public: + IAVsyncPeriodCallback(hwc2_callback_data_t data, hwc2_function_pointer_t hook) + : data_(data), hook_(hook) { + } + + void Callback(uint32_t display, int64_t timestamp, uint32_t vsyncPeriodNanos) { + if (hook_ != NULL) { + auto hook = reinterpret_cast(hook_); + hook(data_, display, timestamp, vsyncPeriodNanos); + } + } + + private: + hwc2_callback_data_t data_; + hwc2_function_pointer_t hook_; +}; + class IARefreshCallback : public hwcomposer::RefreshCallback { public: IARefreshCallback(hwc2_callback_data_t data, hwc2_function_pointer_t hook) @@ -335,6 +353,15 @@ HWC2::Error IAHWC2::RegisterCallback(int32_t descriptor, break; } + case HWC2::Callback::Vsync_2_4: { + primary_display_.RegisterVsyncPeriodCallback(data, function); + for (size_t i = 0; i < size; ++i) { + IAHWC2::HwcDisplay *display = extended_displays_.at(i).get(); + display->RegisterVsyncPeriodCallback(data, function); + } + + break; + } case HWC2::Callback::Refresh: { primary_display_.RegisterRefreshCallback(data, function); for (size_t i = 0; i < size; ++i) { @@ -425,6 +452,19 @@ HWC2::Error IAHWC2::HwcDisplay::RegisterVsyncCallback( return HWC2::Error::None; } +HWC2::Error IAHWC2::HwcDisplay::RegisterVsyncPeriodCallback( + hwc2_callback_data_t data, hwc2_function_pointer_t func) { + supported(__func__); + auto callback = std::make_shared(data, func); + int ret = display_->RegisterVsyncPeriodCallback(std::move(callback), + static_cast(handle_)); + if (ret) { + ALOGE("Failed to register callback d=%" PRIu64 " ret=%d", handle_, ret); + return HWC2::Error::BadDisplay; + } + return HWC2::Error::None; +} + HWC2::Error IAHWC2::HwcDisplay::RegisterRefreshCallback( hwc2_callback_data_t data, hwc2_function_pointer_t func) { supported(__func__); @@ -815,6 +855,25 @@ HWC2::Error IAHWC2::HwcDisplay::SetActiveConfig(hwc2_config_t config) { return HWC2::Error::None; } +HWC2::Error IAHWC2::HwcDisplay::SetActiveConfigWithConstraints( + hwc2_config_t config, + hwc_vsync_period_change_constraints_t* vsyncPeriodChangeConstraints, + hwc_vsync_period_change_timeline_t* outTimeline + ) { + supported(__func__); + return SetActiveConfig(config); +} + +HWC2::Error IAHWC2::HwcDisplay::GetDisplayVsyncPeriod(hwc2_vsync_period_t* outVsyncPeriod) { + supported(__func__); + //*outVsyncPeriod = 16666667; + //return HWC2::Error::None; + if(display_->GetDisplayVsyncPeriod(outVsyncPeriod)) + return HWC2::Error::None; + else + return HWC2::Error::BadConfig; +} + HWC2::Error IAHWC2::HwcDisplay::SetClientTarget(buffer_handle_t target, int32_t acquire_fence, int32_t dataspace, @@ -951,6 +1010,11 @@ HWC2::Error IAHWC2::HwcDisplay::SetVsyncEnabled(int32_t enabled) { return HWC2::Error::None; } +HWC2::Error IAHWC2::HwcDisplay::SetDisplayBrightness(float brightness) { + supported(__func__); + return HWC2::Error::None; +} + HWC2::Error IAHWC2::HwcDisplay::ValidateDisplay(uint32_t *num_types, uint32_t *num_requests) { std::map z_map; @@ -1439,6 +1503,16 @@ hwc2_function_pointer_t IAHWC2::HookDevGetFunction(struct hwc2_device * /*dev*/, return ToHook( DisplayHook); + case HWC2::FunctionDescriptor::SetActiveConfigWithConstraints: + return ToHook( + DisplayHook); + case HWC2::FunctionDescriptor::GetDisplayVsyncPeriod: + return ToHook( + DisplayHook); case HWC2::FunctionDescriptor::SetClientTarget: return ToHook(DisplayHook< decltype(&HwcDisplay::SetClientTarget), &HwcDisplay::SetClientTarget, @@ -1473,6 +1547,10 @@ hwc2_function_pointer_t IAHWC2::HookDevGetFunction(struct hwc2_device * /*dev*/, return ToHook( DisplayHook); + case HWC2::FunctionDescriptor::SetDisplayBrightness: + return ToHook( + DisplayHook); case HWC2::FunctionDescriptor::ValidateDisplay: return ToHook( DisplayHook #include "overlaylayer.h" -#define ALL_EDID_FLAG_PROPERTY "vendor.hwcomposer.edid.all" +#define ALL_EDID_FLAG_PROPERTY "1" namespace hwcomposer { diff --git a/public/nativedisplay.h b/public/nativedisplay.h index 4f17b1dbc..fe181086c 100644 --- a/public/nativedisplay.h +++ b/public/nativedisplay.h @@ -41,6 +41,13 @@ class VsyncCallback { virtual void Callback(uint32_t display, int64_t timestamp) = 0; }; +class VsyncPeriodCallback { + public: + virtual ~VsyncPeriodCallback() { + } + virtual void Callback(uint32_t display, int64_t timestamp, uint32_t vsyncPeriodNanos) = 0; +}; + class RefreshCallback { public: virtual ~RefreshCallback() { @@ -95,6 +102,9 @@ class NativeDisplay { virtual void GetDisplayCapabilities(uint32_t *outNumCapabilities, uint32_t *outCapabilities) = 0; + virtual bool GetDisplayVsyncPeriod(uint32_t *outVsyncPeriod) { + return false; + }; /** * API for getting connected display's pipe id. @@ -132,6 +142,12 @@ class NativeDisplay { virtual int RegisterVsyncCallback(std::shared_ptr callback, uint32_t display_id) = 0; + + virtual int RegisterVsyncPeriodCallback(std::shared_ptr callback, + uint32_t display_id) { + return false; + }; + virtual void VSyncControl(bool enabled) = 0; /** diff --git a/wsi/drm/drmdisplay.cpp b/wsi/drm/drmdisplay.cpp index 5b48c1b46..cb2dd9f51 100644 --- a/wsi/drm/drmdisplay.cpp +++ b/wsi/drm/drmdisplay.cpp @@ -575,9 +575,15 @@ void DrmDisplay::UpdateDisplayConfig() { } flags_ |= DRM_MODE_ATOMIC_ALLOW_MODESET; SetDisplayAttribute(modes_[config_]); + vsync_period_ = modes_[config_].vrefresh; SPIN_UNLOCK(display_lock_); } +bool DrmDisplay::GetDisplayVsyncPeriod(uint32_t* outVsyncPeriod) { + return GetDisplayAttribute(config_, HWCDisplayAttribute::kRefreshRate, + reinterpret_cast(outVsyncPeriod)); +} + void DrmDisplay::PowerOn() { flags_ = 0; flags_ |= DRM_MODE_ATOMIC_ALLOW_MODESET; diff --git a/wsi/drm/drmdisplay.h b/wsi/drm/drmdisplay.h index 3dffe9cd0..4cea5e30d 100644 --- a/wsi/drm/drmdisplay.h +++ b/wsi/drm/drmdisplay.h @@ -78,6 +78,8 @@ class DrmDisplay : public PhysicalDisplay { bool InitializeDisplay() override; void PowerOn() override; void UpdateDisplayConfig() override; + bool GetDisplayVsyncPeriod(uint32_t* outVsyncPeriod) override; + void SetColorCorrection(struct gamma_colors gamma, uint32_t contrast, uint32_t brightness) const override; void SetPipeCanvasColor(uint16_t bpc, uint16_t red, uint16_t green, @@ -215,6 +217,7 @@ class DrmDisplay : public PhysicalDisplay { std::vector modes_; SpinLock display_lock_; DrmDisplayManager *manager_; + uint32_t vsync_period_ = 0; }; } // namespace hwcomposer diff --git a/wsi/physicaldisplay.cpp b/wsi/physicaldisplay.cpp index 07e94b035..cab4d97c2 100644 --- a/wsi/physicaldisplay.cpp +++ b/wsi/physicaldisplay.cpp @@ -379,6 +379,11 @@ int PhysicalDisplay::RegisterVsyncCallback( return display_queue_->RegisterVsyncCallback(callback, display_id); } +int PhysicalDisplay::RegisterVsyncPeriodCallback( + std::shared_ptr callback, uint32_t display_id) { + return display_queue_->RegisterVsyncPeriodCallback(callback, display_id); +} + void PhysicalDisplay::RegisterRefreshCallback( std::shared_ptr callback, uint32_t display_id) { display_queue_->RegisterRefreshCallback(callback, display_id); diff --git a/wsi/physicaldisplay.h b/wsi/physicaldisplay.h index a9c44b184..d6473b3ad 100644 --- a/wsi/physicaldisplay.h +++ b/wsi/physicaldisplay.h @@ -78,6 +78,9 @@ class PhysicalDisplay : public NativeDisplay, public DisplayPlaneHandler { int RegisterVsyncCallback(std::shared_ptr callback, uint32_t display_id) override; + int RegisterVsyncPeriodCallback(std::shared_ptr callback, + uint32_t display_id) override; + void RegisterRefreshCallback(std::shared_ptr callback, uint32_t display_id) override; @@ -201,6 +204,9 @@ class PhysicalDisplay : public NativeDisplay, public DisplayPlaneHandler { */ virtual void UpdateDisplayConfig() = 0; + + virtual bool GetDisplayVsyncPeriod(uint32_t* outVsyncPeriod) = 0; + /** * API for powering on the display */