From 674b37e8e6c0d559db28e371b0c3df0d1432a63c Mon Sep 17 00:00:00 2001 From: Mingwei Wang Date: Tue, 21 Nov 2017 11:17:30 +0800 Subject: [PATCH] Add nested display support in hwc This display can be client to a real physical display. Jira: None. Test: Build passes on Android. Tests still work as now. Signed-off-by: Mingwei Wang --- Android.common.mk | 4 + common/Android.mk | 1 + common/core/gpudevice.cpp | 5 + common/core/logicaldisplay.h | 2 +- common/core/nesteddisplay.cpp | 210 ++++++++++++++++++++++++++++++++++++++++++ common/core/nesteddisplay.h | 119 ++++++++++++++++++++++++ os/android/iahwc2.cpp | 25 ++++- os/android/iahwc2.h | 17 +++- public/gpudevice.h | 5 + public/hwcdefs.h | 9 +- public/nativedisplay.h | 7 ++ wsi/displaymanager.h | 1 + wsi/drm/drmdisplaymanager.cpp | 14 +++ wsi/drm/drmdisplaymanager.h | 3 + 14 files changed, 417 insertions(+), 5 deletions(-) create mode 100644 common/core/nesteddisplay.cpp create mode 100644 common/core/nesteddisplay.h diff --git a/Android.common.mk b/Android.common.mk index 994131f..b4831bb 100644 --- a/Android.common.mk +++ b/Android.common.mk @@ -69,6 +69,10 @@ LOCAL_SHARED_LIBRARIES += \ LOCAL_CPPFLAGS += -DENABLE_DOUBLE_BUFFERING endif +ifeq ($(strip $(ENABLE_NESTED_DISPLAY_SUPPORT)), true) +LOCAL_CPPFLAGS += -DNESTED_DISPLAY_SUPPORT +endif + LOCAL_SRC_FILES += os/android/gralloc1bufferhandler.cpp LOCAL_CPPFLAGS += \ diff --git a/common/Android.mk b/common/Android.mk index 704ba8d..accc682 100644 --- a/common/Android.mk +++ b/common/Android.mk @@ -76,6 +76,7 @@ LOCAL_SRC_FILES := \ core/logicaldisplaymanager.cpp \ core/mosaicdisplay.cpp \ core/overlaylayer.cpp \ + core/nesteddisplay.cpp \ display/displayplanemanager.cpp \ display/displayqueue.cpp \ display/vblankeventhandler.cpp \ diff --git a/common/core/gpudevice.cpp b/common/core/gpudevice.cpp index f06fa88..be240a5 100644 --- a/common/core/gpudevice.cpp +++ b/common/core/gpudevice.cpp @@ -457,6 +457,11 @@ NativeDisplay *GpuDevice::GetVirtualDisplay() { return display_manager_->GetVirtualDisplay(); } +//It's for nested display +NativeDisplay *GpuDevice::GetNestedDisplay() { + return display_manager_->GetNestedDisplay(); +} + void GpuDevice::GetConnectedPhysicalDisplays( std::vector &displays) { size_t size = total_displays_.size(); diff --git a/common/core/logicaldisplay.h b/common/core/logicaldisplay.h index 1686677..ea0953b 100644 --- a/common/core/logicaldisplay.h +++ b/common/core/logicaldisplay.h @@ -109,7 +109,7 @@ class LogicalDisplay : public NativeDisplay { void RefreshUpdate(); - void HotPlugUpdate(bool connected); + void HotPlugUpdate(bool connected) override; private: LogicalDisplayManager *logical_display_manager_; diff --git a/common/core/nesteddisplay.cpp b/common/core/nesteddisplay.cpp new file mode 100644 index 0000000..461381a --- /dev/null +++ b/common/core/nesteddisplay.cpp @@ -0,0 +1,210 @@ +/* +// Copyright (c) 2017 Intel Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +*/ + +#include "nesteddisplay.h" + +#include + +#include +#include + +#include + +namespace hwcomposer { + +NestedDisplay::NestedDisplay() { +} + +NestedDisplay::~NestedDisplay() { +} + +void NestedDisplay::InitNestedDisplay() { +} + +bool NestedDisplay::Initialize(NativeBufferHandler * /*buffer_handler*/) { + return true; +} + +bool NestedDisplay::IsConnected() const { + return true; +} + +uint32_t NestedDisplay::PowerMode() const { + return power_mode_; +} + +int NestedDisplay::GetDisplayPipe() { + return -1; +} + +bool NestedDisplay::SetActiveConfig(uint32_t config) { + config_ = config; + return true; +} + +bool NestedDisplay::GetActiveConfig(uint32_t *config) { + if (!config) + return false; + + config[0] = 0; + return true; +} + +bool NestedDisplay::SetPowerMode(uint32_t /*power_mode*/) { + return true; +} + +bool NestedDisplay::Present(std::vector & /*source_layers*/, + int32_t * /*retire_fence*/, + bool /*handle_constraints*/) { + // TODO implement Present + return true; +} + +bool NestedDisplay::PresentClone(std::vector & /*source_layers*/, + int32_t * /*retire_fence*/, + bool /*idle_frame*/) { + return false; +} + +int NestedDisplay::RegisterVsyncCallback( + std::shared_ptr callback, uint32_t display_id) { + display_id_ = display_id; + vsync_callback_ = callback; + return 0; +} + +void NestedDisplay::RegisterRefreshCallback( + std::shared_ptr callback, uint32_t display_id) { + display_id_ = display_id; + refresh_callback_ = callback; +} + +void NestedDisplay::RegisterHotPlugCallback( + std::shared_ptr callback, uint32_t display_id) { + display_id_ = display_id; + hotplug_callback_ = callback; +} + +void NestedDisplay::VSyncControl(bool enabled) { + enable_vsync_ = enabled; +} + +void NestedDisplay::VSyncUpdate(int64_t timestamp) { + if (vsync_callback_ && enable_vsync_) { + vsync_callback_->Callback(display_id_, timestamp); + } +} + +void NestedDisplay::RefreshUpdate() { + if (refresh_callback_ && power_mode_ == kOn) { + refresh_callback_->Callback(display_id_); + } +} + +void NestedDisplay::HotPlugUpdate(bool /*connected*/) { + if (hotplug_callback_) { + IHOTPLUGEVENTTRACE( + "NestedDisplay RegisterHotPlugCallback: id: %d display: %p", + display_id_, this); + hotplug_callback_->Callback(display_id_, true); + } +} + +bool NestedDisplay::CheckPlaneFormat(uint32_t /*format*/) { + // assuming that virtual display supports the format + return true; +} + +void NestedDisplay::SetGamma(float /*red*/, float /*green*/, float /*blue*/) { +} + +void NestedDisplay::SetContrast(uint32_t /*red*/, uint32_t /*green*/, + uint32_t /*blue*/) { +} + +void NestedDisplay::SetBrightness(uint32_t /*red*/, uint32_t /*green*/, + uint32_t /*blue*/) { +} + +void NestedDisplay::SetExplicitSyncSupport(bool /*disable_explicit_sync*/) { +} + +void NestedDisplay::UpdateScalingRatio(uint32_t /*primary_width*/, + uint32_t /*primary_height*/, + uint32_t /*display_width*/, + uint32_t /*display_height*/) { +} + +void NestedDisplay::CloneDisplay(NativeDisplay * /*source_display*/) { +} + +bool NestedDisplay::GetDisplayAttribute(uint32_t /*config*/, + HWCDisplayAttribute attribute, + int32_t *value) { + // We always get the values from preferred mode config. + switch (attribute) { + case HWCDisplayAttribute::kWidth: + *value = 1920; + break; + case HWCDisplayAttribute::kHeight: + *value = 1080; + break; + case HWCDisplayAttribute::kRefreshRate: + // in nanoseconds + *value = 60; + break; + case HWCDisplayAttribute::kDpiX: + // Dots per 1000 inches + *value = 1; + break; + case HWCDisplayAttribute::kDpiY: + // Dots per 1000 inches + *value = 1; + break; + default: + *value = -1; + return false; + } + + return true; +} + +bool NestedDisplay::GetDisplayConfigs(uint32_t *num_configs, + uint32_t *configs) { + *num_configs = 1; + if (configs) + configs[0] = 0; + + return true; +} + +bool NestedDisplay::GetDisplayName(uint32_t *size, char *name) { + std::ostringstream stream; + stream << "Nested"; + std::string string = stream.str(); + size_t length = string.length(); + if (!name) { + *size = length; + return true; + } + + *size = std::min(static_cast(length - 1), *size); + strncpy(name, string.c_str(), *size); + return true; +} + +} // namespace hwcomposer diff --git a/common/core/nesteddisplay.h b/common/core/nesteddisplay.h new file mode 100644 index 0000000..ac1212d --- /dev/null +++ b/common/core/nesteddisplay.h @@ -0,0 +1,119 @@ +/* +// Copyright (c) 2017 Intel Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +*/ + +#ifndef COMMON_CORE_NESTEDDISPLAY_H_ +#define COMMON_CORE_NESTEDDISPLAY_H_ + +#include +#include + +#include + +#include + +namespace hwcomposer { + +class NestedDisplayManager; + +class NestedDisplay : public NativeDisplay { + public: + NestedDisplay(); + ~NestedDisplay() override; + + void InitNestedDisplay() override; + + bool Initialize(NativeBufferHandler *buffer_handler) override; + + DisplayType Type() const override { + return DisplayType::kNested; + } + + uint32_t Width() const override { + return width_; + } + + uint32_t Height() const override { + return height_; + } + + uint32_t PowerMode() const override; + + int GetDisplayPipe() override; + bool SetActiveConfig(uint32_t config) override; + bool GetActiveConfig(uint32_t *config) override; + + bool SetPowerMode(uint32_t power_mode) override; + + bool Present(std::vector &source_layers, int32_t *retire_fence, + bool handle_constraints = false) override; + + int RegisterVsyncCallback(std::shared_ptr callback, + uint32_t display_id) override; + + void RegisterRefreshCallback(std::shared_ptr callback, + uint32_t display_id) override; + + void RegisterHotPlugCallback(std::shared_ptr callback, + uint32_t display_id) override; + + void VSyncControl(bool enabled) override; + bool CheckPlaneFormat(uint32_t format) override; + void SetGamma(float red, float green, float blue) override; + void SetContrast(uint32_t red, uint32_t green, uint32_t blue) override; + void SetBrightness(uint32_t red, uint32_t green, uint32_t blue) override; + void SetExplicitSyncSupport(bool disable_explicit_sync) override; + + bool IsConnected() const override; + + void UpdateScalingRatio(uint32_t primary_width, uint32_t primary_height, + uint32_t display_width, + uint32_t display_height) override; + + void CloneDisplay(NativeDisplay *source_display) override; + + bool PresentClone(std::vector &source_layers, + int32_t *retire_fence, bool idle_frame) override; + + bool GetDisplayAttribute(uint32_t /*config*/, HWCDisplayAttribute attribute, + int32_t *value) override; + + bool GetDisplayConfigs(uint32_t *num_configs, uint32_t *configs) override; + bool GetDisplayName(uint32_t *size, char *name) override; + + bool EnableVSync() const { + return enable_vsync_; + } + + void VSyncUpdate(int64_t timestamp); + + void RefreshUpdate(); + + void HotPlugUpdate(bool connected); + + private: + std::shared_ptr refresh_callback_ = NULL; + std::shared_ptr vsync_callback_ = NULL; + std::shared_ptr hotplug_callback_ = NULL; + uint32_t power_mode_ = kOff; + uint32_t display_id_; + uint32_t width_ = 0; + uint32_t height_ = 0; + bool enable_vsync_ = false; + uint32_t config_ = 1; +}; + +} // namespace hwcomposer +#endif // COMMON_CORE_NESTEDDISPLAY_H_ diff --git a/os/android/iahwc2.cpp b/os/android/iahwc2.cpp index 8414238..26e9cfe 100644 --- a/os/android/iahwc2.cpp +++ b/os/android/iahwc2.cpp @@ -151,6 +151,12 @@ HWC2::Error IAHWC2::Init() { primary_display_.Init(primary_display, 0, disable_explicit_sync_); size_t size = displays.size(); + // Add nested display which is expected to use the output of this display and + // show it himself. Nested display can be implemented with real HW display. + // It's different from virtual display. + nested_display_.InitNestedDisplay(device_.GetNestedDisplay(), + disable_explicit_sync_); + for (size_t i = 0; i < size; ++i) { hwcomposer::NativeDisplay *display = displays.at(i); if (display == primary_display) @@ -160,7 +166,8 @@ HWC2::Error IAHWC2::Init() { temp->Init(display, external_display_id, disable_explicit_sync_); extended_displays_.emplace_back(std::move(temp)); external_display_id++; -// Let's not confuse things with Virtual Display. + + // Let's not confuse things with Virtual Display. if (external_display_id == HWC_DISPLAY_VIRTUAL) external_display_id = HWC_DISPLAY_VIRTUAL + 1; } @@ -223,6 +230,7 @@ HWC2::Error IAHWC2::RegisterCallback(int32_t descriptor, switch (callback) { case HWC2::Callback::Hotplug: { primary_display_.RegisterHotPlugCallback(data, function); + nested_display_.RegisterHotPlugCallback(data, function); for (size_t i = 0; i < size; ++i) { IAHWC2::HwcDisplay *display = extended_displays_.at(i).get(); display->RegisterHotPlugCallback(data, function); @@ -272,6 +280,21 @@ HWC2::Error IAHWC2::HwcDisplay::InitVirtualDisplay( return HWC2::Error::None; } +// This function will be called only for Nested Display Init +HWC2::Error IAHWC2::HwcDisplay::InitNestedDisplay( + hwcomposer::NativeDisplay *display, bool disable_explicit_sync) { + supported(__func__); + display_ = display; +#ifdef NESTED_DISPLAY_SUPPORT + type_ = HWC2::DisplayType::Nested; + handle_ = HWC_DISPLAY_NESTED; +#endif + display_->InitNestedDisplay(); + disable_explicit_sync_ = disable_explicit_sync; + display_->SetExplicitSyncSupport(disable_explicit_sync_); + return HWC2::Error::None; +} + HWC2::Error IAHWC2::HwcDisplay::Init(hwcomposer::NativeDisplay *display, int display_index, bool disable_explicit_sync) { diff --git a/os/android/iahwc2.h b/os/android/iahwc2.h index 44a26d3..c040b07 100644 --- a/os/android/iahwc2.h +++ b/os/android/iahwc2.h @@ -128,6 +128,8 @@ class IAHWC2 : public hwc2_device_t { HWC2::Error InitVirtualDisplay(hwcomposer::NativeDisplay *display, uint32_t width, uint32_t height, bool disable_explicit_sync); + HWC2::Error InitNestedDisplay(hwcomposer::NativeDisplay *display, + bool disable_explicit_sync); HWC2::Error RegisterVsyncCallback(hwc2_callback_data_t data, hwc2_function_pointer_t func); @@ -225,7 +227,12 @@ class IAHWC2 : public hwc2_device_t { return static_cast( (hwc->virtual_display_.*func)(std::forward(args)...)); } - +#ifdef NESTED_DISPLAY_SUPPORT + if (display_handle == HWC_DISPLAY_NESTED) { + return static_cast( + (hwc->nested_display_.*func)(std::forward(args)...)); + } +#endif if (display_handle == HWC_DISPLAY_EXTERNAL) { HwcDisplay *display = hwc->extended_displays_.at(0).get(); return static_cast( @@ -250,7 +257,12 @@ class IAHWC2 : public hwc2_device_t { Hwc2Layer &layer = hwc->virtual_display_.get_layer(layer_handle); return static_cast((layer.*func)(std::forward(args)...)); } - +#ifdef NESTED_DISPLAY_SUPPORT + if (display_handle == HWC_DISPLAY_NESTED) { + Hwc2Layer &layer = hwc->nested_display_.get_layer(layer_handle); + return static_cast((layer.*func)(std::forward(args)...)); + } +#endif if (display_handle == HWC_DISPLAY_EXTERNAL) { HwcDisplay *display = hwc->extended_displays_.at(0).get(); Hwc2Layer &layer = display->get_layer(layer_handle); @@ -282,6 +294,7 @@ class IAHWC2 : public hwc2_device_t { std::vector> extended_displays_; HwcDisplay primary_display_; HwcDisplay virtual_display_; + HwcDisplay nested_display_; bool disable_explicit_sync_ = false; android::HwcService hwcService_; diff --git a/public/gpudevice.h b/public/gpudevice.h index ec1101d..7a3640e 100644 --- a/public/gpudevice.h +++ b/public/gpudevice.h @@ -43,6 +43,11 @@ class GpuDevice { NativeDisplay* GetVirtualDisplay(); + // This display can be a client preparing + // content which will eventually shown by + // another parent display. + NativeDisplay* GetNestedDisplay(); + void GetConnectedPhysicalDisplays(std::vector& displays); std::vector GetAllDisplays(); diff --git a/public/hwcdefs.h b/public/hwcdefs.h index c683455..9f2475f 100644 --- a/public/hwcdefs.h +++ b/public/hwcdefs.h @@ -71,7 +71,14 @@ enum class HWCDisplayAttribute : int32_t { kDpiY = 5 }; -enum class DisplayType : int32_t { kInternal = 0, kExternal = 1, kVirtual = 2, kLogical = 3, kMosaic = 4 }; +enum class DisplayType : int32_t { + kInternal = 0, + kExternal = 1, + kVirtual = 2, + kLogical = 3, + kMosaic = 4, + kNested = 5 +}; enum DisplayPowerMode { kOff = 0, // Display is off diff --git a/public/nativedisplay.h b/public/nativedisplay.h index 051a3dc..b627f11 100644 --- a/public/nativedisplay.h +++ b/public/nativedisplay.h @@ -198,6 +198,10 @@ class NativeDisplay { virtual void InitVirtualDisplay(uint32_t /*width*/, uint32_t /*height*/) { } + // Nested display related. + virtual void InitNestedDisplay() { + } + /** * API for setting output buffer for virtual display. * @param buffer ownership is taken by display. @@ -258,6 +262,9 @@ class NativeDisplay { return 0; } + virtual void HotPlugUpdate(bool /*connected*/) { + } + protected: friend class PhysicalDisplay; friend class GpuDevice; diff --git a/wsi/displaymanager.h b/wsi/displaymanager.h index 117d764..6d6af9b 100644 --- a/wsi/displaymanager.h +++ b/wsi/displaymanager.h @@ -33,6 +33,7 @@ class DisplayManager { virtual bool Initialize() = 0; virtual NativeDisplay *GetVirtualDisplay() = 0; + virtual NativeDisplay *GetNestedDisplay() = 0; virtual std::vector GetAllDisplays() = 0; diff --git a/wsi/drm/drmdisplaymanager.cpp b/wsi/drm/drmdisplaymanager.cpp index dda1c2e..aff97c6 100644 --- a/wsi/drm/drmdisplaymanager.cpp +++ b/wsi/drm/drmdisplaymanager.cpp @@ -98,6 +98,7 @@ bool DrmDisplayManager::Initialize() { } virtual_display_.reset(new VirtualDisplay(fd_, buffer_handler_.get(), 0, 0)); + nested_display_.reset(new NestedDisplay()); hwc_lock_.reset(new HWCLock()); if (!hwc_lock_->RegisterCallBack(this)) { @@ -345,6 +346,12 @@ bool DrmDisplayManager::UpdateDisplayState() { NotifyClientsOfDisplayChangeStatus(); } + static bool nested_display_registered = false; + if (notify_client_ && !nested_display_registered) { + nested_display_->HotPlugUpdate(true); + nested_display_registered = true; + } + return true; } @@ -371,6 +378,13 @@ NativeDisplay *DrmDisplayManager::GetVirtualDisplay() { return display; } +NativeDisplay *DrmDisplayManager::GetNestedDisplay() { + spin_lock_.lock(); + NativeDisplay *display = nested_display_.get(); + spin_lock_.unlock(); + return display; +} + std::vector DrmDisplayManager::GetAllDisplays() { spin_lock_.lock(); std::vector all_displays; diff --git a/wsi/drm/drmdisplaymanager.h b/wsi/drm/drmdisplaymanager.h index 1bd0c64..0fdf61e 100644 --- a/wsi/drm/drmdisplaymanager.h +++ b/wsi/drm/drmdisplaymanager.h @@ -33,6 +33,7 @@ #include "hwclock.h" #include "vblankeventhandler.h" #include "virtualdisplay.h" +#include "nesteddisplay.h" namespace hwcomposer { @@ -48,6 +49,7 @@ class DrmDisplayManager : public HWCThread, public DisplayManager { bool Initialize() override; NativeDisplay *GetVirtualDisplay() override; + NativeDisplay *GetNestedDisplay() override; std::vector GetAllDisplays() override; @@ -68,6 +70,7 @@ class DrmDisplayManager : public HWCThread, public DisplayManager { void HotPlugEventHandler(); bool UpdateDisplayState(); std::unique_ptr virtual_display_; + std::unique_ptr nested_display_; std::unique_ptr hwc_lock_; std::vector> displays_; std::shared_ptr callback_ = NULL; -- 2.11.0