diff options
21 files changed, 844 insertions, 1016 deletions
diff --git a/libs/vr/libvrflinger/display_service.cpp b/libs/vr/libvrflinger/display_service.cpp index 733edc659c..f350762e79 100644 --- a/libs/vr/libvrflinger/display_service.cpp +++ b/libs/vr/libvrflinger/display_service.cpp @@ -40,10 +40,8 @@ namespace dvr { DisplayService::DisplayService(Hwc2::Composer* hidl, RequestDisplayCallback request_display_callback) : BASE("DisplayService", - Endpoint::Create(display::DisplayProtocol::kClientPath)), - hardware_composer_(hidl, request_display_callback), - request_display_callback_(request_display_callback) { - hardware_composer_.Initialize(); + Endpoint::Create(display::DisplayProtocol::kClientPath)) { + hardware_composer_.Initialize(hidl, request_display_callback); } bool DisplayService::IsInitialized() const { @@ -398,10 +396,6 @@ pdx::Status<void> DisplayService::DeleteGlobalBuffer(DvrGlobalBufferKey key) { return {0}; } -void DisplayService::OnHardwareComposerRefresh() { - hardware_composer_.OnHardwareComposerRefresh(); -} - void DisplayService::SetDisplayConfigurationUpdateNotifier( DisplayConfigurationUpdateNotifier update_notifier) { update_notifier_ = update_notifier; diff --git a/libs/vr/libvrflinger/display_service.h b/libs/vr/libvrflinger/display_service.h index 6efe264b09..55e33ab852 100644 --- a/libs/vr/libvrflinger/display_service.h +++ b/libs/vr/libvrflinger/display_service.h @@ -72,8 +72,6 @@ class DisplayService : public pdx::ServiceBase<DisplayService> { void GrantDisplayOwnership() { hardware_composer_.Enable(); } void SeizeDisplayOwnership() { hardware_composer_.Disable(); } - void OnHardwareComposerRefresh(); - private: friend BASE; friend DisplaySurface; @@ -119,7 +117,6 @@ class DisplayService : public pdx::ServiceBase<DisplayService> { pdx::Status<void> HandleSurfaceMessage(pdx::Message& message); HardwareComposer hardware_composer_; - RequestDisplayCallback request_display_callback_; EpollEventDispatcher dispatcher_; DisplayConfigurationUpdateNotifier update_notifier_; diff --git a/libs/vr/libvrflinger/hardware_composer.cpp b/libs/vr/libvrflinger/hardware_composer.cpp index 11c137063e..f9a5dcd987 100644 --- a/libs/vr/libvrflinger/hardware_composer.cpp +++ b/libs/vr/libvrflinger/hardware_composer.cpp @@ -28,6 +28,8 @@ #include <private/dvr/clock_ns.h> #include <private/dvr/ion_buffer.h> +using android::hardware::Return; +using android::hardware::Void; using android::pdx::LocalHandle; using android::pdx::rpc::EmptyVariant; using android::pdx::rpc::IfAnyOf; @@ -42,9 +44,6 @@ namespace { const char kBacklightBrightnessSysFile[] = "/sys/class/leds/lcd-backlight/brightness"; -const char kPrimaryDisplayVSyncEventFile[] = - "/sys/class/graphics/fb0/vsync_event"; - const char kPrimaryDisplayWaitPPEventFile[] = "/sys/class/graphics/fb0/wait_pp"; const char kDvrPerformanceProperty[] = "sys.dvr.performance"; @@ -86,22 +85,11 @@ bool SetThreadPolicy(const std::string& scheduler_class, } // anonymous namespace -// Layer static data. -Hwc2::Composer* Layer::hwc2_hidl_; -const HWCDisplayMetrics* Layer::display_metrics_; - // HardwareComposer static data; constexpr size_t HardwareComposer::kMaxHardwareLayers; HardwareComposer::HardwareComposer() - : HardwareComposer(nullptr, RequestDisplayCallback()) {} - -HardwareComposer::HardwareComposer( - Hwc2::Composer* hwc2_hidl, RequestDisplayCallback request_display_callback) - : initialized_(false), - hwc2_hidl_(hwc2_hidl), - request_display_callback_(request_display_callback), - callbacks_(new ComposerCallback) {} + : initialized_(false), request_display_callback_(nullptr) {} HardwareComposer::~HardwareComposer(void) { UpdatePostThreadState(PostThreadState::Quit, true); @@ -109,16 +97,19 @@ HardwareComposer::~HardwareComposer(void) { post_thread_.join(); } -bool HardwareComposer::Initialize() { +bool HardwareComposer::Initialize( + Hwc2::Composer* hidl, RequestDisplayCallback request_display_callback) { if (initialized_) { ALOGE("HardwareComposer::Initialize: already initialized."); return false; } + request_display_callback_ = request_display_callback; + HWC::Error error = HWC::Error::None; Hwc2::Config config; - error = hwc2_hidl_->getActiveConfig(HWC_DISPLAY_PRIMARY, &config); + error = hidl->getActiveConfig(HWC_DISPLAY_PRIMARY, &config); if (error != HWC::Error::None) { ALOGE("HardwareComposer: Failed to get current display config : %d", @@ -126,8 +117,8 @@ bool HardwareComposer::Initialize() { return false; } - error = - GetDisplayMetrics(HWC_DISPLAY_PRIMARY, config, &native_display_metrics_); + error = GetDisplayMetrics(hidl, HWC_DISPLAY_PRIMARY, config, + &native_display_metrics_); if (error != HWC::Error::None) { ALOGE( @@ -149,9 +140,6 @@ bool HardwareComposer::Initialize() { display_transform_ = HWC_TRANSFORM_NONE; display_metrics_ = native_display_metrics_; - // Pass hwc instance and metrics to setup globals for Layer. - Layer::InitializeGlobals(hwc2_hidl_, &native_display_metrics_); - post_thread_event_fd_.Reset(eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK)); LOG_ALWAYS_FATAL_IF( !post_thread_event_fd_, @@ -210,15 +198,11 @@ void HardwareComposer::UpdatePostThreadState(PostThreadStateType state, } void HardwareComposer::OnPostThreadResumed() { - hwc2_hidl_->resetCommands(); + hidl_.reset(new Hwc2::Composer("default")); + hidl_callback_ = new ComposerCallback; + hidl_->registerCallback(hidl_callback_); - // HIDL HWC seems to have an internal race condition. If we submit a frame too - // soon after turning on VSync we don't get any VSync signals. Give poor HWC - // implementations a chance to enable VSync before we continue. - EnableVsync(false); - std::this_thread::sleep_for(100ms); EnableVsync(true); - std::this_thread::sleep_for(100ms); // TODO(skiazyk): We need to do something about accessing this directly, // supposedly there is a backlight service on the way. @@ -240,9 +224,12 @@ void HardwareComposer::OnPostThreadPaused() { } active_layer_count_ = 0; - EnableVsync(false); + if (hidl_) { + EnableVsync(false); + } - hwc2_hidl_->resetCommands(); + hidl_callback_ = nullptr; + hidl_.reset(nullptr); // Trigger target-specific performance mode change. property_set(kDvrPerformanceProperty, "idle"); @@ -252,21 +239,21 @@ HWC::Error HardwareComposer::Validate(hwc2_display_t display) { uint32_t num_types; uint32_t num_requests; HWC::Error error = - hwc2_hidl_->validateDisplay(display, &num_types, &num_requests); + hidl_->validateDisplay(display, &num_types, &num_requests); if (error == HWC2_ERROR_HAS_CHANGES) { // TODO(skiazyk): We might need to inspect the requested changes first, but // so far it seems like we shouldn't ever hit a bad state. // error = hwc2_funcs_.accept_display_changes_fn_(hardware_composer_device_, // display); - error = hwc2_hidl_->acceptDisplayChanges(display); + error = hidl_->acceptDisplayChanges(display); } return error; } -int32_t HardwareComposer::EnableVsync(bool enabled) { - return (int32_t)hwc2_hidl_->setVsyncEnabled( +HWC::Error HardwareComposer::EnableVsync(bool enabled) { + return hidl_->setVsyncEnabled( HWC_DISPLAY_PRIMARY, (Hwc2::IComposerClient::Vsync)(enabled ? HWC2_VSYNC_ENABLE : HWC2_VSYNC_DISABLE)); @@ -274,7 +261,7 @@ int32_t HardwareComposer::EnableVsync(bool enabled) { HWC::Error HardwareComposer::Present(hwc2_display_t display) { int32_t present_fence; - HWC::Error error = hwc2_hidl_->presentDisplay(display, &present_fence); + HWC::Error error = hidl_->presentDisplay(display, &present_fence); // According to the documentation, this fence is signaled at the time of // vsync/DMA for physical displays. @@ -288,20 +275,21 @@ HWC::Error HardwareComposer::Present(hwc2_display_t display) { return error; } -HWC::Error HardwareComposer::GetDisplayAttribute(hwc2_display_t display, +HWC::Error HardwareComposer::GetDisplayAttribute(Hwc2::Composer* hidl, + hwc2_display_t display, hwc2_config_t config, hwc2_attribute_t attribute, int32_t* out_value) const { - return hwc2_hidl_->getDisplayAttribute( + return hidl->getDisplayAttribute( display, config, (Hwc2::IComposerClient::Attribute)attribute, out_value); } HWC::Error HardwareComposer::GetDisplayMetrics( - hwc2_display_t display, hwc2_config_t config, + Hwc2::Composer* hidl, hwc2_display_t display, hwc2_config_t config, HWCDisplayMetrics* out_metrics) const { HWC::Error error; - error = GetDisplayAttribute(display, config, HWC2_ATTRIBUTE_WIDTH, + error = GetDisplayAttribute(hidl, display, config, HWC2_ATTRIBUTE_WIDTH, &out_metrics->width); if (error != HWC::Error::None) { ALOGE( @@ -310,7 +298,7 @@ HWC::Error HardwareComposer::GetDisplayMetrics( return error; } - error = GetDisplayAttribute(display, config, HWC2_ATTRIBUTE_HEIGHT, + error = GetDisplayAttribute(hidl, display, config, HWC2_ATTRIBUTE_HEIGHT, &out_metrics->height); if (error != HWC::Error::None) { ALOGE( @@ -319,7 +307,8 @@ HWC::Error HardwareComposer::GetDisplayMetrics( return error; } - error = GetDisplayAttribute(display, config, HWC2_ATTRIBUTE_VSYNC_PERIOD, + error = GetDisplayAttribute(hidl, display, config, + HWC2_ATTRIBUTE_VSYNC_PERIOD, &out_metrics->vsync_period_ns); if (error != HWC::Error::None) { ALOGE( @@ -328,7 +317,7 @@ HWC::Error HardwareComposer::GetDisplayMetrics( return error; } - error = GetDisplayAttribute(display, config, HWC2_ATTRIBUTE_DPI_X, + error = GetDisplayAttribute(hidl, display, config, HWC2_ATTRIBUTE_DPI_X, &out_metrics->dpi.x); if (error != HWC::Error::None) { ALOGE( @@ -337,7 +326,7 @@ HWC::Error HardwareComposer::GetDisplayMetrics( return error; } - error = GetDisplayAttribute(display, config, HWC2_ATTRIBUTE_DPI_Y, + error = GetDisplayAttribute(hidl, display, config, HWC2_ATTRIBUTE_DPI_Y, &out_metrics->dpi.y); if (error != HWC::Error::None) { ALOGE( @@ -374,7 +363,7 @@ std::string HardwareComposer::Dump() { if (post_thread_resumed_) { stream << "Hardware Composer Debug Info:" << std::endl; - stream << hwc2_hidl_->dumpDebugInfo(); + stream << hidl_->dumpDebugInfo(); } return stream.str(); @@ -446,8 +435,8 @@ void HardwareComposer::PostLayers() { std::vector<Hwc2::Layer> out_layers; std::vector<int> out_fences; - error = hwc2_hidl_->getReleaseFences(HWC_DISPLAY_PRIMARY, &out_layers, - &out_fences); + error = hidl_->getReleaseFences(HWC_DISPLAY_PRIMARY, &out_layers, + &out_fences); ALOGE_IF(error != HWC::Error::None, "HardwareComposer::PostLayers: Failed to get release fences: %s", error.to_string().c_str()); @@ -546,7 +535,7 @@ void HardwareComposer::UpdateConfigBuffer() { } int HardwareComposer::PostThreadPollInterruptible( - const pdx::LocalHandle& event_fd, int requested_events) { + const pdx::LocalHandle& event_fd, int requested_events, int timeout_ms) { pollfd pfd[2] = { { .fd = event_fd.Get(), @@ -561,7 +550,7 @@ int HardwareComposer::PostThreadPollInterruptible( }; int ret, error; do { - ret = poll(pfd, 2, -1); + ret = poll(pfd, 2, timeout_ms); error = errno; ALOGW_IF(ret < 0, "HardwareComposer::PostThreadPollInterruptible: Error during " @@ -571,6 +560,8 @@ int HardwareComposer::PostThreadPollInterruptible( if (ret < 0) { return -error; + } else if (ret == 0) { + return -ETIMEDOUT; } else if (pfd[0].revents != 0) { return 0; } else if (pfd[1].revents != 0) { @@ -623,114 +614,17 @@ int HardwareComposer::ReadWaitPPState() { } } -// Reads the timestamp of the last vsync from the display driver. -// TODO(eieio): This is pretty driver specific, this should be moved to a -// separate class eventually. -int HardwareComposer::ReadVSyncTimestamp(int64_t* timestamp) { - const int event_fd = primary_display_vsync_event_fd_.Get(); - int ret, error; - - // The driver returns data in the form "VSYNC=<timestamp ns>". - std::array<char, 32> data; - data.fill('\0'); - - // Seek back to the beginning of the event file. - ret = lseek(event_fd, 0, SEEK_SET); - if (ret < 0) { - error = errno; - ALOGE( - "HardwareComposer::ReadVSyncTimestamp: Failed to seek vsync event fd: " - "%s", - strerror(error)); - return -error; - } - - // Read the vsync event timestamp. - ret = read(event_fd, data.data(), data.size()); - if (ret < 0) { - error = errno; - ALOGE_IF( - error != EAGAIN, - "HardwareComposer::ReadVSyncTimestamp: Error while reading timestamp: " - "%s", - strerror(error)); - return -error; - } - - ret = sscanf(data.data(), "VSYNC=%" PRIu64, - reinterpret_cast<uint64_t*>(timestamp)); - if (ret < 0) { - error = errno; - ALOGE( - "HardwareComposer::ReadVSyncTimestamp: Error while parsing timestamp: " - "%s", - strerror(error)); - return -error; - } - - return 0; -} - -// Blocks until the next vsync event is signaled by the display driver. -// TODO(eieio): This is pretty driver specific, this should be moved to a -// separate class eventually. -int HardwareComposer::BlockUntilVSync() { - // Vsync is signaled by POLLPRI on the fb vsync node. - return PostThreadPollInterruptible(primary_display_vsync_event_fd_, POLLPRI); -} - // Waits for the next vsync and returns the timestamp of the vsync event. If // vsync already passed since the last call, returns the latest vsync timestamp -// instead of blocking. This method updates the last_vsync_timeout_ in the -// process. -// -// TODO(eieio): This is pretty driver specific, this should be moved to a -// separate class eventually. +// instead of blocking. int HardwareComposer::WaitForVSync(int64_t* timestamp) { - int error; - - // Get the current timestamp and decide what to do. - while (true) { - int64_t current_vsync_timestamp; - error = ReadVSyncTimestamp(¤t_vsync_timestamp); - if (error < 0 && error != -EAGAIN) - return error; - - if (error == -EAGAIN) { - // Vsync was turned off, wait for the next vsync event. - error = BlockUntilVSync(); - if (error < 0 || error == kPostThreadInterrupted) - return error; - - // Try again to get the timestamp for this new vsync interval. - continue; - } - - // Check that we advanced to a later vsync interval. - if (TimestampGT(current_vsync_timestamp, last_vsync_timestamp_)) { - *timestamp = last_vsync_timestamp_ = current_vsync_timestamp; - return 0; - } - - // See how close we are to the next expected vsync. If we're within 1ms, - // sleep for 1ms and try again. - const int64_t ns_per_frame = display_metrics_.vsync_period_ns; - const int64_t threshold_ns = 1000000; // 1ms - - const int64_t next_vsync_est = last_vsync_timestamp_ + ns_per_frame; - const int64_t distance_to_vsync_est = next_vsync_est - GetSystemClockNs(); - - if (distance_to_vsync_est > threshold_ns) { - // Wait for vsync event notification. - error = BlockUntilVSync(); - if (error < 0 || error == kPostThreadInterrupted) - return error; - } else { - // Sleep for a short time (1 millisecond) before retrying. - error = SleepUntil(GetSystemClockNs() + threshold_ns); - if (error < 0 || error == kPostThreadInterrupted) - return error; - } + int error = PostThreadPollInterruptible( + hidl_callback_->GetVsyncEventFd(), POLLIN, /*timeout_ms*/ 1000); + if (error == kPostThreadInterrupted || error < 0) { + return error; + } else { + *timestamp = hidl_callback_->GetVsyncTime(); + return 0; } } @@ -749,7 +643,8 @@ int HardwareComposer::SleepUntil(int64_t wakeup_timestamp) { return -error; } - return PostThreadPollInterruptible(vsync_sleep_timer_fd_, POLLIN); + return PostThreadPollInterruptible( + vsync_sleep_timer_fd_, POLLIN, /*timeout_ms*/ -1); } void HardwareComposer::PostThread() { @@ -772,15 +667,6 @@ void HardwareComposer::PostThread() { strerror(errno)); #endif // ENABLE_BACKLIGHT_BRIGHTNESS - // Open the vsync event node for the primary display. - // TODO(eieio): Move this into a platform-specific class. - primary_display_vsync_event_fd_ = - LocalHandle(kPrimaryDisplayVSyncEventFile, O_RDONLY); - ALOGE_IF(!primary_display_vsync_event_fd_, - "HardwareComposer: Failed to open vsync event node for primary " - "display: %s", - strerror(errno)); - // Open the wait pingpong status node for the primary display. // TODO(eieio): Move this into a platform-specific class. primary_display_wait_pp_fd_ = @@ -951,7 +837,8 @@ bool HardwareComposer::UpdateLayerConfig() { // The bottom layer is opaque, other layers blend. HWC::BlendMode blending = layer_index == 0 ? HWC::BlendMode::None : HWC::BlendMode::Coverage; - layers_[layer_index].Setup(surfaces[layer_index], blending, + layers_[layer_index].Setup(surfaces[layer_index], native_display_metrics_, + hidl_.get(), blending, display_transform_, HWC::Composition::Device, layer_index); display_surfaces_.push_back(surfaces[layer_index]); @@ -979,50 +866,67 @@ void HardwareComposer::SetVSyncCallback(VSyncCallback callback) { vsync_callback_ = callback; } -void HardwareComposer::HwcRefresh(hwc2_callback_data_t /*data*/, - hwc2_display_t /*display*/) { - // TODO(eieio): implement invalidate callbacks. +void HardwareComposer::SetBacklightBrightness(int brightness) { + if (backlight_brightness_fd_) { + std::array<char, 32> text; + const int length = snprintf(text.data(), text.size(), "%d", brightness); + write(backlight_brightness_fd_.Get(), text.data(), length); + } } -void HardwareComposer::HwcVSync(hwc2_callback_data_t /*data*/, - hwc2_display_t /*display*/, - int64_t /*timestamp*/) { - ATRACE_NAME(__PRETTY_FUNCTION__); - // Intentionally empty. HWC may require a callback to be set to enable vsync - // signals. We bypass this callback thread by monitoring the vsync event - // directly, but signals still need to be enabled. +HardwareComposer::ComposerCallback::ComposerCallback() { + vsync_event_fd_.Reset(eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK)); + LOG_ALWAYS_FATAL_IF( + !vsync_event_fd_, + "Failed to create vsync event fd : %s", + strerror(errno)); } -void HardwareComposer::HwcHotplug(hwc2_callback_data_t /*callbackData*/, - hwc2_display_t /*display*/, - hwc2_connection_t /*connected*/) { - // TODO(eieio): implement display hotplug callbacks. +Return<void> HardwareComposer::ComposerCallback::onHotplug( + Hwc2::Display /*display*/, + IComposerCallback::Connection /*conn*/) { + return Void(); } -void HardwareComposer::OnHardwareComposerRefresh() { - // TODO(steventhomas): Handle refresh. +Return<void> HardwareComposer::ComposerCallback::onRefresh( + Hwc2::Display /*display*/) { + return hardware::Void(); } -void HardwareComposer::SetBacklightBrightness(int brightness) { - if (backlight_brightness_fd_) { - std::array<char, 32> text; - const int length = snprintf(text.data(), text.size(), "%d", brightness); - write(backlight_brightness_fd_.Get(), text.data(), length); +Return<void> HardwareComposer::ComposerCallback::onVsync( + Hwc2::Display display, int64_t timestamp) { + if (display == HWC_DISPLAY_PRIMARY) { + std::lock_guard<std::mutex> lock(vsync_mutex_); + vsync_time_ = timestamp; + int error = eventfd_write(vsync_event_fd_.Get(), 1); + LOG_ALWAYS_FATAL_IF(error != 0, "Failed writing to vsync event fd"); } + return Void(); +} + +const pdx::LocalHandle& +HardwareComposer::ComposerCallback::GetVsyncEventFd() const { + return vsync_event_fd_; } -void Layer::InitializeGlobals(Hwc2::Composer* hwc2_hidl, - const HWCDisplayMetrics* metrics) { - hwc2_hidl_ = hwc2_hidl; - display_metrics_ = metrics; +int64_t HardwareComposer::ComposerCallback::GetVsyncTime() { + std::lock_guard<std::mutex> lock(vsync_mutex_); + eventfd_t event; + eventfd_read(vsync_event_fd_.Get(), &event); + LOG_ALWAYS_FATAL_IF(vsync_time_ < 0, + "Attempt to read vsync time before vsync event"); + int64_t return_val = vsync_time_; + vsync_time_ = -1; + return return_val; } void Layer::Reset() { - if (hwc2_hidl_ != nullptr && hardware_composer_layer_) { - hwc2_hidl_->destroyLayer(HWC_DISPLAY_PRIMARY, hardware_composer_layer_); + if (hidl_ != nullptr && hardware_composer_layer_) { + hidl_->destroyLayer(HWC_DISPLAY_PRIMARY, hardware_composer_layer_); hardware_composer_layer_ = 0; } + hidl_ = nullptr; z_order_ = 0; blending_ = HWC::BlendMode::None; transform_ = HWC::Transform::None; @@ -1034,29 +938,35 @@ void Layer::Reset() { } void Layer::Setup(const std::shared_ptr<DirectDisplaySurface>& surface, - HWC::BlendMode blending, HWC::Transform transform, - HWC::Composition composition_type, size_t z_order) { + const HWCDisplayMetrics& display_metrics, + Hwc2::Composer* hidl, HWC::BlendMode blending, + HWC::Transform transform, HWC::Composition composition_type, + size_t z_order) { Reset(); + hidl_ = hidl; z_order_ = z_order; blending_ = blending; transform_ = transform; composition_type_ = HWC::Composition::Invalid; target_composition_type_ = composition_type; source_ = SourceSurface{surface}; - CommonLayerSetup(); + CommonLayerSetup(display_metrics); } void Layer::Setup(const std::shared_ptr<IonBuffer>& buffer, - HWC::BlendMode blending, HWC::Transform transform, - HWC::Composition composition_type, size_t z_order) { + const HWCDisplayMetrics& display_metrics, + Hwc2::Composer* hidl, HWC::BlendMode blending, + HWC::Transform transform, HWC::Composition composition_type, + size_t z_order) { Reset(); + hidl_ = hidl; z_order_ = z_order; blending_ = blending; transform_ = transform; composition_type_ = HWC::Composition::Invalid; target_composition_type_ = composition_type; source_ = SourceBuffer{buffer}; - CommonLayerSetup(); + CommonLayerSetup(display_metrics); } void Layer::UpdateBuffer(const std::shared_ptr<IonBuffer>& buffer) { @@ -1076,7 +986,7 @@ IonBuffer* Layer::GetBuffer() { return source_.Visit(Visitor{}); } -void Layer::UpdateLayerSettings() { +void Layer::UpdateLayerSettings(const HWCDisplayMetrics& display_metrics) { if (!IsLayerSetup()) { ALOGE( "HardwareComposer::Layer::UpdateLayerSettings: Attempt to update " @@ -1087,7 +997,7 @@ void Layer::UpdateLayerSettings() { HWC::Error error; hwc2_display_t display = HWC_DISPLAY_PRIMARY; - error = hwc2_hidl_->setLayerCompositionType( + error = hidl_->setLayerCompositionType( display, hardware_composer_layer_, composition_type_.cast<Hwc2::IComposerClient::Composition>()); ALOGE_IF( @@ -1095,7 +1005,7 @@ void Layer::UpdateLayerSettings() { "Layer::UpdateLayerSettings: Error setting layer composition type: %s", error.to_string().c_str()); - error = hwc2_hidl_->setLayerBlendMode( + error = hidl_->setLayerBlendMode( display, hardware_composer_layer_, blending_.cast<Hwc2::IComposerClient::BlendMode>()); ALOGE_IF(error != HWC::Error::None, @@ -1104,41 +1014,39 @@ void Layer::UpdateLayerSettings() { // TODO(eieio): Use surface attributes or some other mechanism to control // the layer display frame. - error = hwc2_hidl_->setLayerDisplayFrame( + error = hidl_->setLayerDisplayFrame( display, hardware_composer_layer_, - {0, 0, display_metrics_->width, display_metrics_->height}); + {0, 0, display_metrics.width, display_metrics.height}); ALOGE_IF(error != HWC::Error::None, "Layer::UpdateLayerSettings: Error setting layer display frame: %s", error.to_string().c_str()); - error = hwc2_hidl_->setLayerVisibleRegion( + error = hidl_->setLayerVisibleRegion( display, hardware_composer_layer_, - {{0, 0, display_metrics_->width, display_metrics_->height}}); + {{0, 0, display_metrics.width, display_metrics.height}}); ALOGE_IF(error != HWC::Error::None, "Layer::UpdateLayerSettings: Error setting layer visible region: %s", error.to_string().c_str()); - error = - hwc2_hidl_->setLayerPlaneAlpha(display, hardware_composer_layer_, 1.0f); + error = hidl_->setLayerPlaneAlpha(display, hardware_composer_layer_, 1.0f); ALOGE_IF(error != HWC::Error::None, "Layer::UpdateLayerSettings: Error setting layer plane alpha: %s", error.to_string().c_str()); - error = - hwc2_hidl_->setLayerZOrder(display, hardware_composer_layer_, z_order_); + error = hidl_->setLayerZOrder(display, hardware_composer_layer_, z_order_); ALOGE_IF(error != HWC::Error::None, "Layer::UpdateLayerSettings: Error setting z_ order: %s", error.to_string().c_str()); } -void Layer::CommonLayerSetup() { +void Layer::CommonLayerSetup(const HWCDisplayMetrics& display_metrics) { HWC::Error error = - hwc2_hidl_->createLayer(HWC_DISPLAY_PRIMARY, &hardware_composer_layer_); + hidl_->createLayer(HWC_DISPLAY_PRIMARY, &hardware_composer_layer_); ALOGE_IF( error != HWC::Error::None, "Layer::CommonLayerSetup: Failed to create layer on primary display: %s", error.to_string().c_str()); - UpdateLayerSettings(); + UpdateLayerSettings(display_metrics); } void Layer::Prepare() { @@ -1157,12 +1065,12 @@ void Layer::Prepare() { if (!handle.get()) { if (composition_type_ == HWC::Composition::Invalid) { composition_type_ = HWC::Composition::SolidColor; - hwc2_hidl_->setLayerCompositionType( + hidl_->setLayerCompositionType( HWC_DISPLAY_PRIMARY, hardware_composer_layer_, composition_type_.cast<Hwc2::IComposerClient::Composition>()); Hwc2::IComposerClient::Color layer_color = {0, 0, 0, 0}; - hwc2_hidl_->setLayerColor(HWC_DISPLAY_PRIMARY, hardware_composer_layer_, - layer_color); + hidl_->setLayerColor(HWC_DISPLAY_PRIMARY, hardware_composer_layer_, + layer_color); } else { // The composition type is already set. Nothing else to do until a // buffer arrives. @@ -1170,15 +1078,15 @@ void Layer::Prepare() { } else { if (composition_type_ != target_composition_type_) { composition_type_ = target_composition_type_; - hwc2_hidl_->setLayerCompositionType( + hidl_->setLayerCompositionType( HWC_DISPLAY_PRIMARY, hardware_composer_layer_, composition_type_.cast<Hwc2::IComposerClient::Composition>()); } HWC::Error error{HWC::Error::None}; - error = hwc2_hidl_->setLayerBuffer(HWC_DISPLAY_PRIMARY, - hardware_composer_layer_, 0, handle, - acquire_fence_.Get()); + error = hidl_->setLayerBuffer(HWC_DISPLAY_PRIMARY, + hardware_composer_layer_, 0, handle, + acquire_fence_.Get()); ALOGE_IF(error != HWC::Error::None, "Layer::Prepare: Error setting layer buffer: %s", @@ -1187,9 +1095,9 @@ void Layer::Prepare() { if (!surface_rect_functions_applied_) { const float float_right = right; const float float_bottom = bottom; - error = hwc2_hidl_->setLayerSourceCrop(HWC_DISPLAY_PRIMARY, - hardware_composer_layer_, - {0, 0, float_right, float_bottom}); + error = hidl_->setLayerSourceCrop(HWC_DISPLAY_PRIMARY, + hardware_composer_layer_, + {0, 0, float_right, float_bottom}); ALOGE_IF(error != HWC::Error::None, "Layer::Prepare: Error setting layer source crop: %s", diff --git a/libs/vr/libvrflinger/hardware_composer.h b/libs/vr/libvrflinger/hardware_composer.h index a0c50e14d8..fc0efeeeb4 100644 --- a/libs/vr/libvrflinger/hardware_composer.h +++ b/libs/vr/libvrflinger/hardware_composer.h @@ -54,11 +54,6 @@ class Layer { public: Layer() {} - // Sets up the global state used by all Layer instances. This must be called - // before using any Layer methods. - static void InitializeGlobals(Hwc2::Composer* hwc2_hidl, - const HWCDisplayMetrics* metrics); - // Releases any shared pointers and fence handles held by this instance. void Reset(); @@ -72,6 +67,7 @@ class Layer { // HWC_FRAMEBUFFER_TARGET (unless you know what you are doing). // |index| is the index of this surface in the DirectDisplaySurface array. void Setup(const std::shared_ptr<DirectDisplaySurface>& surface, + const HWCDisplayMetrics& display_metrics, Hwc2::Composer* hidl, HWC::BlendMode blending, HWC::Transform transform, HWC::Composition composition_type, size_t z_roder); @@ -83,9 +79,10 @@ class Layer { // |transform| receives HWC_TRANSFORM_* values. // |composition_type| receives either HWC_FRAMEBUFFER for most layers or // HWC_FRAMEBUFFER_TARGET (unless you know what you are doing). - void Setup(const std::shared_ptr<IonBuffer>& buffer, HWC::BlendMode blending, - HWC::Transform transform, HWC::Composition composition_type, - size_t z_order); + void Setup(const std::shared_ptr<IonBuffer>& buffer, + const HWCDisplayMetrics& display_metrics, Hwc2::Composer* hidl, + HWC::BlendMode blending, HWC::Transform transform, + HWC::Composition composition_type, size_t z_order); // Layers that use a direct IonBuffer should call this each frame to update // which buffer will be used for the next PostLayers. @@ -121,7 +118,7 @@ class Layer { bool IsLayerSetup() const { return !source_.empty(); } // Applies all of the settings to this layer using the hwc functions - void UpdateLayerSettings(); + void UpdateLayerSettings(const HWCDisplayMetrics& display_metrics); int GetSurfaceId() const { int surface_id = -1; @@ -142,10 +139,9 @@ class Layer { } private: - void CommonLayerSetup(); + void CommonLayerSetup(const HWCDisplayMetrics& display_metrics); - static Hwc2::Composer* hwc2_hidl_; - static const HWCDisplayMetrics* display_metrics_; + Hwc2::Composer* hidl_ = nullptr; // The hardware composer layer and metrics to use during the prepare cycle. hwc2_layer_t hardware_composer_layer_ = 0; @@ -263,11 +259,10 @@ class HardwareComposer { static constexpr size_t kMaxHardwareLayers = 4; HardwareComposer(); - HardwareComposer(Hwc2::Composer* hidl, - RequestDisplayCallback request_display_callback); ~HardwareComposer(); - bool Initialize(); + bool Initialize(Hwc2::Composer* hidl, + RequestDisplayCallback request_display_callback); bool IsInitialized() const { return initialized_; } @@ -281,11 +276,6 @@ class HardwareComposer { // Get the HMD display metrics for the current display. display::Metrics GetHmdDisplayMetrics() const; - HWC::Error GetDisplayAttribute(hwc2_display_t display, hwc2_config_t config, - hwc2_attribute_t attributes, - int32_t* out_value) const; - HWC::Error GetDisplayMetrics(hwc2_display_t display, hwc2_config_t config, - HWCDisplayMetrics* out_metrics) const; std::string Dump(); void SetVSyncCallback(VSyncCallback callback); @@ -308,34 +298,31 @@ class HardwareComposer { int OnNewGlobalBuffer(DvrGlobalBufferKey key, IonBuffer& ion_buffer); void OnDeletedGlobalBuffer(DvrGlobalBufferKey key); - void OnHardwareComposerRefresh(); - private: - int32_t EnableVsync(bool enabled); + HWC::Error GetDisplayAttribute(Hwc2::Composer* hidl, hwc2_display_t display, + hwc2_config_t config, + hwc2_attribute_t attributes, + int32_t* out_value) const; + HWC::Error GetDisplayMetrics(Hwc2::Composer* hidl, hwc2_display_t display, + hwc2_config_t config, + HWCDisplayMetrics* out_metrics) const; + + HWC::Error EnableVsync(bool enabled); class ComposerCallback : public Hwc2::IComposerCallback { public: - ComposerCallback() {} - - hardware::Return<void> onHotplug(Hwc2::Display /*display*/, - Connection /*connected*/) override { - // TODO(skiazyk): depending on how the server is implemented, we might - // have to set it up to synchronize with receiving this event, as it can - // potentially be a critical event for setting up state within the - // hwc2 module. That is, we (technically) should not call any other hwc - // methods until this method has been called after registering the - // callbacks. - return hardware::Void(); - } - - hardware::Return<void> onRefresh(Hwc2::Display /*display*/) override { - return hardware::Void(); - } - - hardware::Return<void> onVsync(Hwc2::Display /*display*/, - int64_t /*timestamp*/) override { - return hardware::Void(); - } + ComposerCallback(); + hardware::Return<void> onHotplug(Hwc2::Display display, + Connection conn) override; + hardware::Return<void> onRefresh(Hwc2::Display display) override; + hardware::Return<void> onVsync(Hwc2::Display display, + int64_t timestamp) override; + const pdx::LocalHandle& GetVsyncEventFd() const; + int64_t GetVsyncTime(); + private: + std::mutex vsync_mutex_; + pdx::LocalHandle vsync_event_fd_; + int64_t vsync_time_ = -1; }; HWC::Error Validate(hwc2_display_t display); @@ -364,17 +351,18 @@ class HardwareComposer { void UpdatePostThreadState(uint32_t state, bool suspend); // Blocks until either event_fd becomes readable, or we're interrupted by a - // control thread. Any errors are returned as negative errno values. If we're - // interrupted, kPostThreadInterrupted will be returned. + // control thread, or timeout_ms is reached before any events occur. Any + // errors are returned as negative errno values, with -ETIMEDOUT returned in + // the case of a timeout. If we're interrupted, kPostThreadInterrupted will be + // returned. int PostThreadPollInterruptible(const pdx::LocalHandle& event_fd, - int requested_events); + int requested_events, + int timeout_ms); - // BlockUntilVSync, WaitForVSync, and SleepUntil are all blocking calls made - // on the post thread that can be interrupted by a control thread. If - // interrupted, these calls return kPostThreadInterrupted. + // WaitForVSync and SleepUntil are blocking calls made on the post thread that + // can be interrupted by a control thread. If interrupted, these calls return + // kPostThreadInterrupted. int ReadWaitPPState(); - int BlockUntilVSync(); - int ReadVSyncTimestamp(int64_t* timestamp); int WaitForVSync(int64_t* timestamp); int SleepUntil(int64_t wakeup_timestamp); @@ -398,11 +386,9 @@ class HardwareComposer { bool initialized_; - // Hardware composer HAL device from SurfaceFlinger. VrFlinger does not own - // this pointer. - Hwc2::Composer* hwc2_hidl_; + std::unique_ptr<Hwc2::Composer> hidl_; + sp<ComposerCallback> hidl_callback_; RequestDisplayCallback request_display_callback_; - sp<ComposerCallback> callbacks_; // Display metrics of the physical display. HWCDisplayMetrics native_display_metrics_; @@ -433,7 +419,8 @@ class HardwareComposer { std::thread post_thread_; // Post thread state machine and synchronization primitives. - PostThreadStateType post_thread_state_{PostThreadState::Idle}; + PostThreadStateType post_thread_state_{ + PostThreadState::Idle | PostThreadState::Suspended}; std::atomic<bool> post_thread_quiescent_{true}; bool post_thread_resumed_{false}; pdx::LocalHandle post_thread_event_fd_; @@ -444,9 +431,6 @@ class HardwareComposer { // Backlight LED brightness sysfs node. pdx::LocalHandle backlight_brightness_fd_; - // Primary display vsync event sysfs node. - pdx::LocalHandle primary_display_vsync_event_fd_; - // Primary display wait_pingpong state sysfs node. pdx::LocalHandle primary_display_wait_pp_fd_; @@ -478,12 +462,6 @@ class HardwareComposer { static constexpr int kPostThreadInterrupted = 1; - static void HwcRefresh(hwc2_callback_data_t data, hwc2_display_t display); - static void HwcVSync(hwc2_callback_data_t data, hwc2_display_t display, - int64_t timestamp); - static void HwcHotplug(hwc2_callback_data_t callbackData, - hwc2_display_t display, hwc2_connection_t connected); - HardwareComposer(const HardwareComposer&) = delete; void operator=(const HardwareComposer&) = delete; }; diff --git a/libs/vr/libvrflinger/include/dvr/vr_flinger.h b/libs/vr/libvrflinger/include/dvr/vr_flinger.h index e7f41a7379..33cbc84d7d 100644 --- a/libs/vr/libvrflinger/include/dvr/vr_flinger.h +++ b/libs/vr/libvrflinger/include/dvr/vr_flinger.h @@ -29,9 +29,6 @@ class VrFlinger { void GrantDisplayOwnership(); void SeizeDisplayOwnership(); - // Called on a binder thread. - void OnHardwareComposerRefresh(); - // dump all vr flinger state. std::string Dump(); diff --git a/libs/vr/libvrflinger/vr_flinger.cpp b/libs/vr/libvrflinger/vr_flinger.cpp index 56405deeaa..fcf94f0865 100644 --- a/libs/vr/libvrflinger/vr_flinger.cpp +++ b/libs/vr/libvrflinger/vr_flinger.cpp @@ -133,10 +133,6 @@ void VrFlinger::SeizeDisplayOwnership() { display_service_->SeizeDisplayOwnership(); } -void VrFlinger::OnHardwareComposerRefresh() { - display_service_->OnHardwareComposerRefresh(); -} - std::string VrFlinger::Dump() { // TODO(karthikrs): Add more state information here. return display_service_->DumpState(0/*unused*/); diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index 744dd50df5..248ef53f55 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -134,9 +134,11 @@ DisplayDevice::DisplayDevice( EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); if (config == EGL_NO_CONFIG) { #ifdef USE_HWC2 - config = RenderEngine::chooseEglConfig(display, PIXEL_FORMAT_RGBA_8888); + config = RenderEngine::chooseEglConfig(display, PIXEL_FORMAT_RGBA_8888, + /*logConfig*/ false); #else - config = RenderEngine::chooseEglConfig(display, format); + config = RenderEngine::chooseEglConfig(display, format, + /*logConfig*/ false); #endif } eglSurface = eglCreateWindowSurface(display, config, window, NULL); diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp index 704b17ef43..433a224e25 100644 --- a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp +++ b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp @@ -215,6 +215,10 @@ void Composer::registerCallback(const sp<IComposerCallback>& callback) } } +bool Composer::isRemote() { + return mClient->isRemote(); +} + void Composer::resetCommands() { mWriter.reset(); } diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.h b/services/surfaceflinger/DisplayHardware/ComposerHal.h index 40d2a4c3aa..31a3c1d785 100644 --- a/services/surfaceflinger/DisplayHardware/ComposerHal.h +++ b/services/surfaceflinger/DisplayHardware/ComposerHal.h @@ -143,6 +143,11 @@ public: void registerCallback(const sp<IComposerCallback>& callback); + // Returns true if the connected composer service is running in a remote + // process, false otherwise. This will return false if the service is + // configured in passthrough mode, for example. + bool isRemote(); + // Reset all pending commands in the command buffer. Useful if you want to // skip a frame but have already queued some commands. void resetCommands(); diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp index b749ce630d..78c0c8567a 100644 --- a/services/surfaceflinger/DisplayHardware/HWC2.cpp +++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp @@ -33,45 +33,6 @@ #include <algorithm> #include <inttypes.h> -extern "C" { - static void hotplug_hook(hwc2_callback_data_t callbackData, - hwc2_display_t displayId, int32_t intConnected) { - auto device = static_cast<HWC2::Device*>(callbackData); - auto display = device->getDisplayById(displayId); - if (display) { - auto connected = static_cast<HWC2::Connection>(intConnected); - device->callHotplug(std::move(display), connected); - } else { - ALOGE("Hotplug callback called with unknown display %" PRIu64, - displayId); - } - } - - static void refresh_hook(hwc2_callback_data_t callbackData, - hwc2_display_t displayId) { - auto device = static_cast<HWC2::Device*>(callbackData); - auto display = device->getDisplayById(displayId); - if (display) { - device->callRefresh(std::move(display)); - } else { - ALOGE("Refresh callback called with unknown display %" PRIu64, - displayId); - } - } - - static void vsync_hook(hwc2_callback_data_t callbackData, - hwc2_display_t displayId, int64_t timestamp) { - auto device = static_cast<HWC2::Device*>(callbackData); - auto display = device->getDisplayById(displayId); - if (display) { - device->callVsync(std::move(display), timestamp); - } else { - ALOGE("Vsync callback called with unknown display %" PRIu64, - displayId); - } - } -} - using android::Fence; using android::FloatRect; using android::GraphicBuffer; @@ -86,51 +47,78 @@ namespace HWC2 { namespace Hwc2 = android::Hwc2; +namespace { + +class ComposerCallbackBridge : public Hwc2::IComposerCallback { +public: + ComposerCallbackBridge(ComposerCallback* callback, int32_t sequenceId) + : mCallback(callback), mSequenceId(sequenceId), + mHasPrimaryDisplay(false) {} + + Return<void> onHotplug(Hwc2::Display display, + IComposerCallback::Connection conn) override + { + HWC2::Connection connection = static_cast<HWC2::Connection>(conn); + if (!mHasPrimaryDisplay) { + LOG_ALWAYS_FATAL_IF(connection != HWC2::Connection::Connected, + "Initial onHotplug callback should be " + "primary display connected"); + mHasPrimaryDisplay = true; + mCallback->onHotplugReceived(mSequenceId, display, + connection, true); + } else { + mCallback->onHotplugReceived(mSequenceId, display, + connection, false); + } + return Void(); + } + + Return<void> onRefresh(Hwc2::Display display) override + { + mCallback->onRefreshReceived(mSequenceId, display); + return Void(); + } + + Return<void> onVsync(Hwc2::Display display, int64_t timestamp) override + { + mCallback->onVsyncReceived(mSequenceId, display, timestamp); + return Void(); + } + + bool HasPrimaryDisplay() { return mHasPrimaryDisplay; } + +private: + ComposerCallback* mCallback; + int32_t mSequenceId; + bool mHasPrimaryDisplay; +}; + +} // namespace anonymous + + // Device methods Device::Device(const std::string& serviceName) : mComposer(std::make_unique<Hwc2::Composer>(serviceName)), mCapabilities(), mDisplays(), - mHotplug(), - mPendingHotplugs(), - mRefresh(), - mPendingRefreshes(), - mVsync(), - mPendingVsyncs() + mRegisteredCallback(false) { loadCapabilities(); - registerCallbacks(); } -Device::~Device() -{ - for (auto element : mDisplays) { - auto display = element.second.lock(); - if (!display) { - ALOGE("~Device: Found a display (%" PRId64 " that has already been" - " destroyed", element.first); - continue; - } - - DisplayType displayType = HWC2::DisplayType::Invalid; - auto error = display->getType(&displayType); - if (error != Error::None) { - ALOGE("~Device: Failed to determine type of display %" PRIu64 - ": %s (%d)", display->getId(), to_string(error).c_str(), - static_cast<int32_t>(error)); - continue; - } - - if (displayType == HWC2::DisplayType::Physical) { - error = display->setVsyncEnabled(HWC2::Vsync::Disable); - if (error != Error::None) { - ALOGE("~Device: Failed to disable vsync for display %" PRIu64 - ": %s (%d)", display->getId(), to_string(error).c_str(), - static_cast<int32_t>(error)); - } - } +void Device::registerCallback(ComposerCallback* callback, int32_t sequenceId) { + if (mRegisteredCallback) { + ALOGW("Callback already registered. Ignored extra registration " + "attempt."); + return; } + mRegisteredCallback = true; + sp<ComposerCallbackBridge> callbackBridge( + new ComposerCallbackBridge(callback, sequenceId)); + mComposer->registerCallback(callbackBridge); + LOG_ALWAYS_FATAL_IF(!callbackBridge->HasPrimaryDisplay(), + "Registered composer callback but didn't get primary display"); } // Required by HWC2 device @@ -146,7 +134,7 @@ uint32_t Device::getMaxVirtualDisplayCount() const } Error Device::createVirtualDisplay(uint32_t width, uint32_t height, - android_pixel_format_t* format, std::shared_ptr<Display>* outDisplay) + android_pixel_format_t* format, Display** outDisplay) { ALOGI("Creating virtual display"); @@ -159,104 +147,66 @@ Error Device::createVirtualDisplay(uint32_t width, uint32_t height, return error; } - ALOGI("Created virtual display"); + auto display = std::make_unique<Display>( + *mComposer.get(), mCapabilities, displayId, DisplayType::Virtual); + *outDisplay = display.get(); *format = static_cast<android_pixel_format_t>(intFormat); - *outDisplay = getDisplayById(displayId); - if (!*outDisplay) { - ALOGE("Failed to get display by id"); - return Error::BadDisplay; - } - (*outDisplay)->setConnected(true); + mDisplays.emplace(displayId, std::move(display)); + ALOGI("Created virtual display"); return Error::None; } -void Device::registerHotplugCallback(HotplugCallback hotplug) +void Device::destroyDisplay(hwc2_display_t displayId) { - ALOGV("registerHotplugCallback"); - mHotplug = hotplug; - for (auto& pending : mPendingHotplugs) { - auto& display = pending.first; - auto connected = pending.second; - ALOGV("Sending pending hotplug(%" PRIu64 ", %s)", display->getId(), - to_string(connected).c_str()); - mHotplug(std::move(display), connected); - } + ALOGI("Destroying display %" PRIu64, displayId); + mDisplays.erase(displayId); } -void Device::registerRefreshCallback(RefreshCallback refresh) -{ - mRefresh = refresh; - for (auto& pending : mPendingRefreshes) { - mRefresh(std::move(pending)); - } -} - -void Device::registerVsyncCallback(VsyncCallback vsync) -{ - mVsync = vsync; - for (auto& pending : mPendingVsyncs) { - auto& display = pending.first; - auto timestamp = pending.second; - mVsync(std::move(display), timestamp); - } -} - -// For use by Device callbacks +void Device::onHotplug(hwc2_display_t displayId, Connection connection) { + if (connection == Connection::Connected) { + auto display = getDisplayById(displayId); + if (display) { + if (display->isConnected()) { + ALOGW("Attempt to hotplug connect display %" PRIu64 + " , which is already connected.", displayId); + } else { + display->setConnected(true); + } + } else { + DisplayType displayType; + auto intError = mComposer->getDisplayType(displayId, + reinterpret_cast<Hwc2::IComposerClient::DisplayType *>( + &displayType)); + auto error = static_cast<Error>(intError); + if (error != Error::None) { + ALOGE("getDisplayType(%" PRIu64 ") failed: %s (%d). " + "Aborting hotplug attempt.", + displayId, to_string(error).c_str(), intError); + return; + } -void Device::callHotplug(std::shared_ptr<Display> display, Connection connected) -{ - if (connected == Connection::Connected) { - if (!display->isConnected()) { - mComposer->setClientTargetSlotCount(display->getId()); - display->loadConfigs(); - display->setConnected(true); + auto newDisplay = std::make_unique<Display>( + *mComposer.get(), mCapabilities, displayId, displayType); + mDisplays.emplace(displayId, std::move(newDisplay)); + } + } else if (connection == Connection::Disconnected) { + // The display will later be destroyed by a call to + // destroyDisplay(). For now we just mark it disconnected. + auto display = getDisplayById(displayId); + if (display) { + display->setConnected(false); + } else { + ALOGW("Attempted to disconnect unknown display %" PRIu64, + displayId); } - } else { - display->setConnected(false); - mDisplays.erase(display->getId()); - } - - if (mHotplug) { - mHotplug(std::move(display), connected); - } else { - ALOGV("callHotplug called, but no valid callback registered, storing"); - mPendingHotplugs.emplace_back(std::move(display), connected); - } -} - -void Device::callRefresh(std::shared_ptr<Display> display) -{ - if (mRefresh) { - mRefresh(std::move(display)); - } else { - ALOGV("callRefresh called, but no valid callback registered, storing"); - mPendingRefreshes.emplace_back(std::move(display)); - } -} - -void Device::callVsync(std::shared_ptr<Display> display, nsecs_t timestamp) -{ - if (mVsync) { - mVsync(std::move(display), timestamp); - } else { - ALOGV("callVsync called, but no valid callback registered, storing"); - mPendingVsyncs.emplace_back(std::move(display), timestamp); } } // Other Device methods -std::shared_ptr<Display> Device::getDisplayById(hwc2_display_t id) { - if (mDisplays.count(id) != 0) { - auto strongDisplay = mDisplays[id].lock(); - ALOGE_IF(!strongDisplay, "Display %" PRId64 " is in mDisplays but is no" - " longer alive", id); - return strongDisplay; - } - - auto display = std::make_shared<Display>(*this, id); - mDisplays.emplace(id, display); - return display; +Display* Device::getDisplayById(hwc2_display_t id) { + auto iter = mDisplays.find(id); + return iter == mDisplays.end() ? nullptr : iter->second.get(); } // Device initialization methods @@ -271,84 +221,37 @@ void Device::loadCapabilities() } } -bool Device::hasCapability(HWC2::Capability capability) const -{ - return std::find(mCapabilities.cbegin(), mCapabilities.cend(), - capability) != mCapabilities.cend(); -} - -namespace { -class ComposerCallback : public Hwc2::IComposerCallback { -public: - ComposerCallback(Device* device) : mDevice(device) {} - - Return<void> onHotplug(Hwc2::Display display, - Connection connected) override - { - hotplug_hook(mDevice, display, static_cast<int32_t>(connected)); - return Void(); - } - - Return<void> onRefresh(Hwc2::Display display) override - { - refresh_hook(mDevice, display); - return Void(); - } - - Return<void> onVsync(Hwc2::Display display, int64_t timestamp) override - { - vsync_hook(mDevice, display, timestamp); - return Void(); - } - -private: - Device* mDevice; -}; -} // namespace anonymous - -void Device::registerCallbacks() -{ - sp<ComposerCallback> callback = new ComposerCallback(this); - mComposer->registerCallback(callback); -} - - -// For use by Display - -void Device::destroyVirtualDisplay(hwc2_display_t display) -{ - ALOGI("Destroying virtual display"); - auto intError = mComposer->destroyVirtualDisplay(display); - auto error = static_cast<Error>(intError); - ALOGE_IF(error != Error::None, "destroyVirtualDisplay(%" PRIu64 ") failed:" - " %s (%d)", display, to_string(error).c_str(), intError); - mDisplays.erase(display); -} - // Display methods -Display::Display(Device& device, hwc2_display_t id) - : mDevice(device), +Display::Display(android::Hwc2::Composer& composer, + const std::unordered_set<Capability>& capabilities, + hwc2_display_t id, DisplayType type) + : mComposer(composer), + mCapabilities(capabilities), mId(id), mIsConnected(false), - mType(DisplayType::Invalid) + mType(type) { ALOGV("Created display %" PRIu64, id); - - auto intError = mDevice.mComposer->getDisplayType(mId, - reinterpret_cast<Hwc2::IComposerClient::DisplayType *>(&mType)); - auto error = static_cast<Error>(intError); - if (error != Error::None) { - ALOGE("getDisplayType(%" PRIu64 ") failed: %s (%d)", - id, to_string(error).c_str(), intError); - } + setConnected(true); } -Display::~Display() -{ - ALOGV("Destroyed display %" PRIu64, mId); +Display::~Display() { + mLayers.clear(); + if (mType == DisplayType::Virtual) { - mDevice.destroyVirtualDisplay(mId); + ALOGV("Destroying virtual display"); + auto intError = mComposer.destroyVirtualDisplay(mId); + auto error = static_cast<Error>(intError); + ALOGE_IF(error != Error::None, "destroyVirtualDisplay(%" PRIu64 + ") failed: %s (%d)", mId, to_string(error).c_str(), intError); + } else if (mType == DisplayType::Physical) { + auto error = setVsyncEnabled(HWC2::Vsync::Disable); + if (error != Error::None) { + ALOGE("~Display: Failed to disable vsync for display %" PRIu64 + ": %s (%d)", mId, to_string(error).c_str(), + static_cast<int32_t>(error)); + } } } @@ -383,22 +286,35 @@ float Display::Config::Builder::getDefaultDensity() { Error Display::acceptChanges() { - auto intError = mDevice.mComposer->acceptDisplayChanges(mId); + auto intError = mComposer.acceptDisplayChanges(mId); return static_cast<Error>(intError); } -Error Display::createLayer(std::shared_ptr<Layer>* outLayer) +Error Display::createLayer(Layer** outLayer) { + if (!outLayer) { + return Error::BadParameter; + } hwc2_layer_t layerId = 0; - auto intError = mDevice.mComposer->createLayer(mId, &layerId); + auto intError = mComposer.createLayer(mId, &layerId); auto error = static_cast<Error>(intError); if (error != Error::None) { return error; } - auto layer = std::make_shared<Layer>(shared_from_this(), layerId); - mLayers.emplace(layerId, layer); - *outLayer = std::move(layer); + auto layer = std::make_unique<Layer>( + mComposer, mCapabilities, mId, layerId); + *outLayer = layer.get(); + mLayers.emplace(layerId, std::move(layer)); + return Error::None; +} + +Error Display::destroyLayer(Layer* layer) +{ + if (!layer) { + return Error::BadParameter; + } + mLayers.erase(layer->getId()); return Error::None; } @@ -407,7 +323,7 @@ Error Display::getActiveConfig( { ALOGV("[%" PRIu64 "] getActiveConfig", mId); hwc2_config_t configId = 0; - auto intError = mDevice.mComposer->getActiveConfig(mId, &configId); + auto intError = mComposer.getActiveConfig(mId, &configId); auto error = static_cast<Error>(intError); if (error != Error::None) { @@ -430,12 +346,12 @@ Error Display::getActiveConfig( } Error Display::getChangedCompositionTypes( - std::unordered_map<std::shared_ptr<Layer>, Composition>* outTypes) + std::unordered_map<Layer*, Composition>* outTypes) { std::vector<Hwc2::Layer> layerIds; std::vector<Hwc2::IComposerClient::Composition> types; - auto intError = mDevice.mComposer->getChangedCompositionTypes(mId, - &layerIds, &types); + auto intError = mComposer.getChangedCompositionTypes( + mId, &layerIds, &types); uint32_t numElements = layerIds.size(); auto error = static_cast<Error>(intError); error = static_cast<Error>(intError); @@ -464,7 +380,7 @@ Error Display::getChangedCompositionTypes( Error Display::getColorModes(std::vector<android_color_mode_t>* outModes) const { std::vector<Hwc2::ColorMode> modes; - auto intError = mDevice.mComposer->getColorModes(mId, &modes); + auto intError = mComposer.getColorModes(mId, &modes); uint32_t numModes = modes.size(); auto error = static_cast<Error>(intError); if (error != Error::None) { @@ -489,19 +405,18 @@ std::vector<std::shared_ptr<const Display::Config>> Display::getConfigs() const Error Display::getName(std::string* outName) const { - auto intError = mDevice.mComposer->getDisplayName(mId, outName); + auto intError = mComposer.getDisplayName(mId, outName); return static_cast<Error>(intError); } Error Display::getRequests(HWC2::DisplayRequest* outDisplayRequests, - std::unordered_map<std::shared_ptr<Layer>, LayerRequest>* - outLayerRequests) + std::unordered_map<Layer*, LayerRequest>* outLayerRequests) { uint32_t intDisplayRequests; std::vector<Hwc2::Layer> layerIds; std::vector<uint32_t> layerRequests; - auto intError = mDevice.mComposer->getDisplayRequests(mId, - &intDisplayRequests, &layerIds, &layerRequests); + auto intError = mComposer.getDisplayRequests( + mId, &intDisplayRequests, &layerIds, &layerRequests); uint32_t numElements = layerIds.size(); auto error = static_cast<Error>(intError); if (error != Error::None) { @@ -535,7 +450,7 @@ Error Display::getType(DisplayType* outType) const Error Display::supportsDoze(bool* outSupport) const { bool intSupport = false; - auto intError = mDevice.mComposer->getDozeSupport(mId, &intSupport); + auto intError = mComposer.getDozeSupport(mId, &intSupport); auto error = static_cast<Error>(intError); if (error != Error::None) { return error; @@ -552,7 +467,7 @@ Error Display::getHdrCapabilities( float maxAverageLuminance = -1.0f; float minLuminance = -1.0f; std::vector<Hwc2::Hdr> intTypes; - auto intError = mDevice.mComposer->getHdrCapabilities(mId, &intTypes, + auto intError = mComposer.getHdrCapabilities(mId, &intTypes, &maxLuminance, &maxAverageLuminance, &minLuminance); auto error = static_cast<HWC2::Error>(intError); @@ -571,25 +486,24 @@ Error Display::getHdrCapabilities( } Error Display::getReleaseFences( - std::unordered_map<std::shared_ptr<Layer>, sp<Fence>>* outFences) const + std::unordered_map<Layer*, sp<Fence>>* outFences) const { std::vector<Hwc2::Layer> layerIds; std::vector<int> fenceFds; - auto intError = mDevice.mComposer->getReleaseFences(mId, - &layerIds, &fenceFds); + auto intError = mComposer.getReleaseFences(mId, &layerIds, &fenceFds); auto error = static_cast<Error>(intError); uint32_t numElements = layerIds.size(); if (error != Error::None) { return error; } - std::unordered_map<std::shared_ptr<Layer>, sp<Fence>> releaseFences; + std::unordered_map<Layer*, sp<Fence>> releaseFences; releaseFences.reserve(numElements); for (uint32_t element = 0; element < numElements; ++element) { auto layer = getLayerById(layerIds[element]); if (layer) { sp<Fence> fence(new Fence(fenceFds[element])); - releaseFences.emplace(std::move(layer), fence); + releaseFences.emplace(layer, fence); } else { ALOGE("getReleaseFences: invalid layer %" PRIu64 " found on display %" PRIu64, layerIds[element], mId); @@ -607,7 +521,7 @@ Error Display::getReleaseFences( Error Display::present(sp<Fence>* outPresentFence) { int32_t presentFenceFd = -1; - auto intError = mDevice.mComposer->presentDisplay(mId, &presentFenceFd); + auto intError = mComposer.presentDisplay(mId, &presentFenceFd); auto error = static_cast<Error>(intError); if (error != Error::None) { return error; @@ -625,7 +539,7 @@ Error Display::setActiveConfig(const std::shared_ptr<const Config>& config) config->getDisplayId(), mId); return Error::BadConfig; } - auto intError = mDevice.mComposer->setActiveConfig(mId, config->getId()); + auto intError = mComposer.setActiveConfig(mId, config->getId()); return static_cast<Error>(intError); } @@ -634,7 +548,7 @@ Error Display::setClientTarget(uint32_t slot, const sp<GraphicBuffer>& target, { // TODO: Properly encode client target surface damage int32_t fenceFd = acquireFence->dup(); - auto intError = mDevice.mComposer->setClientTarget(mId, slot, target, + auto intError = mComposer.setClientTarget(mId, slot, target, fenceFd, static_cast<Hwc2::Dataspace>(dataspace), std::vector<Hwc2::IComposerClient::Rect>()); return static_cast<Error>(intError); @@ -642,15 +556,15 @@ Error Display::setClientTarget(uint32_t slot, const sp<GraphicBuffer>& target, Error Display::setColorMode(android_color_mode_t mode) { - auto intError = mDevice.mComposer->setColorMode(mId, - static_cast<Hwc2::ColorMode>(mode)); + auto intError = mComposer.setColorMode( + mId, static_cast<Hwc2::ColorMode>(mode)); return static_cast<Error>(intError); } Error Display::setColorTransform(const android::mat4& matrix, android_color_transform_t hint) { - auto intError = mDevice.mComposer->setColorTransform(mId, + auto intError = mComposer.setColorTransform(mId, matrix.asArray(), static_cast<Hwc2::ColorTransform>(hint)); return static_cast<Error>(intError); } @@ -660,7 +574,7 @@ Error Display::setOutputBuffer(const sp<GraphicBuffer>& buffer, { int32_t fenceFd = releaseFence->dup(); auto handle = buffer->getNativeBuffer()->handle; - auto intError = mDevice.mComposer->setOutputBuffer(mId, handle, fenceFd); + auto intError = mComposer.setOutputBuffer(mId, handle, fenceFd); close(fenceFd); return static_cast<Error>(intError); } @@ -668,14 +582,14 @@ Error Display::setOutputBuffer(const sp<GraphicBuffer>& buffer, Error Display::setPowerMode(PowerMode mode) { auto intMode = static_cast<Hwc2::IComposerClient::PowerMode>(mode); - auto intError = mDevice.mComposer->setPowerMode(mId, intMode); + auto intError = mComposer.setPowerMode(mId, intMode); return static_cast<Error>(intError); } Error Display::setVsyncEnabled(Vsync enabled) { auto intEnabled = static_cast<Hwc2::IComposerClient::Vsync>(enabled); - auto intError = mDevice.mComposer->setVsyncEnabled(mId, intEnabled); + auto intError = mComposer.setVsyncEnabled(mId, intEnabled); return static_cast<Error>(intError); } @@ -683,8 +597,7 @@ Error Display::validate(uint32_t* outNumTypes, uint32_t* outNumRequests) { uint32_t numTypes = 0; uint32_t numRequests = 0; - auto intError = mDevice.mComposer->validateDisplay(mId, - &numTypes, &numRequests); + auto intError = mComposer.validateDisplay(mId, &numTypes, &numRequests); auto error = static_cast<Error>(intError); if (error != Error::None && error != Error::HasChanges) { return error; @@ -701,7 +614,8 @@ Error Display::presentOrValidate(uint32_t* outNumTypes, uint32_t* outNumRequests uint32_t numTypes = 0; uint32_t numRequests = 0; int32_t presentFenceFd = -1; - auto intError = mDevice.mComposer->presentOrValidateDisplay(mId, &numTypes, &numRequests, &presentFenceFd, state); + auto intError = mComposer.presentOrValidateDisplay( + mId, &numTypes, &numRequests, &presentFenceFd, state); auto error = static_cast<Error>(intError); if (error != Error::None && error != Error::HasChanges) { return error; @@ -720,15 +634,23 @@ Error Display::presentOrValidate(uint32_t* outNumTypes, uint32_t* outNumRequests void Display::discardCommands() { - mDevice.mComposer->resetCommands(); + mComposer.resetCommands(); } // For use by Device +void Display::setConnected(bool connected) { + if (!mIsConnected && connected && mType == DisplayType::Physical) { + mComposer.setClientTargetSlotCount(mId); + loadConfigs(); + } + mIsConnected = connected; +} + int32_t Display::getAttribute(hwc2_config_t configId, Attribute attribute) { int32_t value = 0; - auto intError = mDevice.mComposer->getDisplayAttribute(mId, configId, + auto intError = mComposer.getDisplayAttribute(mId, configId, static_cast<Hwc2::IComposerClient::Attribute>(attribute), &value); auto error = static_cast<Error>(intError); @@ -760,7 +682,7 @@ void Display::loadConfigs() ALOGV("[%" PRIu64 "] loadConfigs", mId); std::vector<Hwc2::Config> configIds; - auto intError = mDevice.mComposer->getDisplayConfigs(mId, &configIds); + auto intError = mComposer.getDisplayConfigs(mId, &configIds); auto error = static_cast<Error>(intError); if (error != Error::None) { ALOGE("[%" PRIu64 "] getDisplayConfigs [2] failed: %s (%d)", mId, @@ -773,54 +695,51 @@ void Display::loadConfigs() } } -// For use by Layer - -void Display::destroyLayer(hwc2_layer_t layerId) -{ - auto intError =mDevice.mComposer->destroyLayer(mId, layerId); - auto error = static_cast<Error>(intError); - ALOGE_IF(error != Error::None, "destroyLayer(%" PRIu64 ", %" PRIu64 ")" - " failed: %s (%d)", mId, layerId, to_string(error).c_str(), - intError); - mLayers.erase(layerId); -} - // Other Display methods -std::shared_ptr<Layer> Display::getLayerById(hwc2_layer_t id) const +Layer* Display::getLayerById(hwc2_layer_t id) const { if (mLayers.count(id) == 0) { return nullptr; } - auto layer = mLayers.at(id).lock(); - return layer; + return mLayers.at(id).get(); } // Layer methods -Layer::Layer(const std::shared_ptr<Display>& display, hwc2_layer_t id) - : mDisplay(display), - mDisplayId(display->getId()), - mDevice(display->getDevice()), - mId(id) +Layer::Layer(android::Hwc2::Composer& composer, + const std::unordered_set<Capability>& capabilities, + hwc2_display_t displayId, hwc2_layer_t layerId) + : mComposer(composer), + mCapabilities(capabilities), + mDisplayId(displayId), + mId(layerId) { - ALOGV("Created layer %" PRIu64 " on display %" PRIu64, id, - display->getId()); + ALOGV("Created layer %" PRIu64 " on display %" PRIu64, layerId, displayId); } Layer::~Layer() { - auto display = mDisplay.lock(); - if (display) { - display->destroyLayer(mId); + auto intError = mComposer.destroyLayer(mDisplayId, mId); + auto error = static_cast<Error>(intError); + ALOGE_IF(error != Error::None, "destroyLayer(%" PRIu64 ", %" PRIu64 ")" + " failed: %s (%d)", mDisplayId, mId, to_string(error).c_str(), + intError); + if (mLayerDestroyedListener) { + mLayerDestroyedListener(this); } } +void Layer::setLayerDestroyedListener(std::function<void(Layer*)> listener) { + LOG_ALWAYS_FATAL_IF(mLayerDestroyedListener && listener, + "Attempt to set layer destroyed listener multiple times"); + mLayerDestroyedListener = listener; +} + Error Layer::setCursorPosition(int32_t x, int32_t y) { - auto intError = mDevice.mComposer->setCursorPosition(mDisplayId, - mId, x, y); + auto intError = mComposer.setCursorPosition(mDisplayId, mId, x, y); return static_cast<Error>(intError); } @@ -828,8 +747,8 @@ Error Layer::setBuffer(uint32_t slot, const sp<GraphicBuffer>& buffer, const sp<Fence>& acquireFence) { int32_t fenceFd = acquireFence->dup(); - auto intError = mDevice.mComposer->setLayerBuffer(mDisplayId, - mId, slot, buffer, fenceFd); + auto intError = mComposer.setLayerBuffer(mDisplayId, mId, slot, buffer, + fenceFd); return static_cast<Error>(intError); } @@ -839,7 +758,7 @@ Error Layer::setSurfaceDamage(const Region& damage) // rects for HWC Hwc2::Error intError = Hwc2::Error::NONE; if (damage.isRect() && damage.getBounds() == Rect::INVALID_RECT) { - intError = mDevice.mComposer->setLayerSurfaceDamage(mDisplayId, + intError = mComposer.setLayerSurfaceDamage(mDisplayId, mId, std::vector<Hwc2::IComposerClient::Rect>()); } else { size_t rectCount = 0; @@ -851,8 +770,7 @@ Error Layer::setSurfaceDamage(const Region& damage) rectArray[rect].right, rectArray[rect].bottom}); } - intError = mDevice.mComposer->setLayerSurfaceDamage(mDisplayId, - mId, hwcRects); + intError = mComposer.setLayerSurfaceDamage(mDisplayId, mId, hwcRects); } return static_cast<Error>(intError); @@ -861,24 +779,22 @@ Error Layer::setSurfaceDamage(const Region& damage) Error Layer::setBlendMode(BlendMode mode) { auto intMode = static_cast<Hwc2::IComposerClient::BlendMode>(mode); - auto intError = mDevice.mComposer->setLayerBlendMode(mDisplayId, - mId, intMode); + auto intError = mComposer.setLayerBlendMode(mDisplayId, mId, intMode); return static_cast<Error>(intError); } Error Layer::setColor(hwc_color_t color) { Hwc2::IComposerClient::Color hwcColor{color.r, color.g, color.b, color.a}; - auto intError = mDevice.mComposer->setLayerColor(mDisplayId, - mId, hwcColor); + auto intError = mComposer.setLayerColor(mDisplayId, mId, hwcColor); return static_cast<Error>(intError); } Error Layer::setCompositionType(Composition type) { auto intType = static_cast<Hwc2::IComposerClient::Composition>(type); - auto intError = mDevice.mComposer->setLayerCompositionType(mDisplayId, - mId, intType); + auto intError = mComposer.setLayerCompositionType( + mDisplayId, mId, intType); return static_cast<Error>(intError); } @@ -889,8 +805,7 @@ Error Layer::setDataspace(android_dataspace_t dataspace) } mDataSpace = dataspace; auto intDataspace = static_cast<Hwc2::Dataspace>(dataspace); - auto intError = mDevice.mComposer->setLayerDataspace(mDisplayId, - mId, intDataspace); + auto intError = mComposer.setLayerDataspace(mDisplayId, mId, intDataspace); return static_cast<Error>(intError); } @@ -898,27 +813,24 @@ Error Layer::setDisplayFrame(const Rect& frame) { Hwc2::IComposerClient::Rect hwcRect{frame.left, frame.top, frame.right, frame.bottom}; - auto intError = mDevice.mComposer->setLayerDisplayFrame(mDisplayId, - mId, hwcRect); + auto intError = mComposer.setLayerDisplayFrame(mDisplayId, mId, hwcRect); return static_cast<Error>(intError); } Error Layer::setPlaneAlpha(float alpha) { - auto intError = mDevice.mComposer->setLayerPlaneAlpha(mDisplayId, - mId, alpha); + auto intError = mComposer.setLayerPlaneAlpha(mDisplayId, mId, alpha); return static_cast<Error>(intError); } Error Layer::setSidebandStream(const native_handle_t* stream) { - if (!mDevice.hasCapability(Capability::SidebandStream)) { + if (mCapabilities.count(Capability::SidebandStream) == 0) { ALOGE("Attempted to call setSidebandStream without checking that the " "device supports sideband streams"); return Error::Unsupported; } - auto intError = mDevice.mComposer->setLayerSidebandStream(mDisplayId, - mId, stream); + auto intError = mComposer.setLayerSidebandStream(mDisplayId, mId, stream); return static_cast<Error>(intError); } @@ -926,16 +838,14 @@ Error Layer::setSourceCrop(const FloatRect& crop) { Hwc2::IComposerClient::FRect hwcRect{ crop.left, crop.top, crop.right, crop.bottom}; - auto intError = mDevice.mComposer->setLayerSourceCrop(mDisplayId, - mId, hwcRect); + auto intError = mComposer.setLayerSourceCrop(mDisplayId, mId, hwcRect); return static_cast<Error>(intError); } Error Layer::setTransform(Transform transform) { auto intTransform = static_cast<Hwc2::Transform>(transform); - auto intError = mDevice.mComposer->setLayerTransform(mDisplayId, - mId, intTransform); + auto intError = mComposer.setLayerTransform(mDisplayId, mId, intTransform); return static_cast<Error>(intError); } @@ -950,20 +860,19 @@ Error Layer::setVisibleRegion(const Region& region) rectArray[rect].right, rectArray[rect].bottom}); } - auto intError = mDevice.mComposer->setLayerVisibleRegion(mDisplayId, - mId, hwcRects); + auto intError = mComposer.setLayerVisibleRegion(mDisplayId, mId, hwcRects); return static_cast<Error>(intError); } Error Layer::setZOrder(uint32_t z) { - auto intError = mDevice.mComposer->setLayerZOrder(mDisplayId, mId, z); + auto intError = mComposer.setLayerZOrder(mDisplayId, mId, z); return static_cast<Error>(intError); } Error Layer::setInfo(uint32_t type, uint32_t appId) { - auto intError = mDevice.mComposer->setLayerInfo(mDisplayId, mId, type, appId); + auto intError = mComposer.setLayerInfo(mDisplayId, mId, type, appId); return static_cast<Error>(intError); } diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h index 9bcda1eb0a..fbe4c7ebed 100644 --- a/services/surfaceflinger/DisplayHardware/HWC2.h +++ b/services/surfaceflinger/DisplayHardware/HWC2.h @@ -53,10 +53,26 @@ namespace HWC2 { class Display; class Layer; -typedef std::function<void(std::shared_ptr<Display>, Connection)> - HotplugCallback; -typedef std::function<void(std::shared_ptr<Display>)> RefreshCallback; -typedef std::function<void(std::shared_ptr<Display>, nsecs_t)> VsyncCallback; +// Implement this interface to receive hardware composer events. +// +// These callback functions will generally be called on a hwbinder thread, but +// when first registering the callback the onHotplugReceived() function will +// immediately be called on the thread calling registerCallback(). +// +// All calls receive a sequenceId, which will be the value that was supplied to +// HWC2::Device::registerCallback(). It's used to help differentiate callbacks +// from different hardware composer instances. +class ComposerCallback { + public: + virtual void onHotplugReceived(int32_t sequenceId, hwc2_display_t display, + Connection connection, + bool primaryDisplay) = 0; + virtual void onRefreshReceived(int32_t sequenceId, + hwc2_display_t display) = 0; + virtual void onVsyncReceived(int32_t sequenceId, hwc2_display_t display, + int64_t timestamp) = 0; + virtual ~ComposerCallback() = default; +}; // C++ Wrapper around hwc2_device_t. Load all functions pointers // and handle callback registration. @@ -66,10 +82,8 @@ public: // Service name is expected to be 'default' or 'vr' for normal use. // 'vr' will slightly modify the behavior of the mComposer. Device(const std::string& serviceName); - ~Device(); - friend class HWC2::Display; - friend class HWC2::Layer; + void registerCallback(ComposerCallback* callback, int32_t sequenceId); // Required by HWC2 @@ -81,27 +95,14 @@ public: uint32_t getMaxVirtualDisplayCount() const; Error createVirtualDisplay(uint32_t width, uint32_t height, - android_pixel_format_t* format, - std::shared_ptr<Display>* outDisplay); - - void registerHotplugCallback(HotplugCallback hotplug); - void registerRefreshCallback(RefreshCallback refresh); - void registerVsyncCallback(VsyncCallback vsync); + android_pixel_format_t* format, Display** outDisplay); + void destroyDisplay(hwc2_display_t displayId); - // For use by callbacks - - void callHotplug(std::shared_ptr<Display> display, Connection connected); - void callRefresh(std::shared_ptr<Display> display); - void callVsync(std::shared_ptr<Display> display, nsecs_t timestamp); + void onHotplug(hwc2_display_t displayId, Connection connection); // Other Device methods - // This will create a Display if one is not found, but it will not be marked - // as connected. This Display may be null if the display has been torn down - // but has not been removed from the map yet. - std::shared_ptr<Display> getDisplayById(hwc2_display_t id); - - bool hasCapability(HWC2::Capability capability) const; + Display* getDisplayById(hwc2_display_t id); android::Hwc2::Composer* getComposer() { return mComposer.get(); } @@ -109,37 +110,23 @@ private: // Initialization methods void loadCapabilities(); - void registerCallbacks(); - - // For use by Display - - void destroyVirtualDisplay(hwc2_display_t display); // Member variables std::unique_ptr<android::Hwc2::Composer> mComposer; - std::unordered_set<Capability> mCapabilities; - std::unordered_map<hwc2_display_t, std::weak_ptr<Display>> mDisplays; - - HotplugCallback mHotplug; - std::vector<std::pair<std::shared_ptr<Display>, Connection>> - mPendingHotplugs; - RefreshCallback mRefresh; - std::vector<std::shared_ptr<Display>> mPendingRefreshes; - VsyncCallback mVsync; - std::vector<std::pair<std::shared_ptr<Display>, nsecs_t>> mPendingVsyncs; + std::unordered_map<hwc2_display_t, std::unique_ptr<Display>> mDisplays; + bool mRegisteredCallback; }; // Convenience C++ class to access hwc2_device_t Display functions directly. -class Display : public std::enable_shared_from_this<Display> +class Display { public: - Display(Device& device, hwc2_display_t id); + Display(android::Hwc2::Composer& composer, + const std::unordered_set<Capability>& capabilities, + hwc2_display_t id, DisplayType type); ~Display(); - friend class HWC2::Device; - friend class HWC2::Layer; - class Config { public: @@ -212,12 +199,12 @@ public: // Required by HWC2 [[clang::warn_unused_result]] Error acceptChanges(); - [[clang::warn_unused_result]] Error createLayer( - std::shared_ptr<Layer>* outLayer); + [[clang::warn_unused_result]] Error createLayer(Layer** outLayer); + [[clang::warn_unused_result]] Error destroyLayer(Layer* layer); [[clang::warn_unused_result]] Error getActiveConfig( std::shared_ptr<const Config>* outConfig) const; [[clang::warn_unused_result]] Error getChangedCompositionTypes( - std::unordered_map<std::shared_ptr<Layer>, Composition>* outTypes); + std::unordered_map<Layer*, Composition>* outTypes); [[clang::warn_unused_result]] Error getColorModes( std::vector<android_color_mode_t>* outModes) const; @@ -227,14 +214,13 @@ public: [[clang::warn_unused_result]] Error getName(std::string* outName) const; [[clang::warn_unused_result]] Error getRequests( DisplayRequest* outDisplayRequests, - std::unordered_map<std::shared_ptr<Layer>, LayerRequest>* - outLayerRequests); + std::unordered_map<Layer*, LayerRequest>* outLayerRequests); [[clang::warn_unused_result]] Error getType(DisplayType* outType) const; [[clang::warn_unused_result]] Error supportsDoze(bool* outSupport) const; [[clang::warn_unused_result]] Error getHdrCapabilities( std::unique_ptr<android::HdrCapabilities>* outCapabilities) const; [[clang::warn_unused_result]] Error getReleaseFences( - std::unordered_map<std::shared_ptr<Layer>, + std::unordered_map<Layer*, android::sp<android::Fence>>* outFences) const; [[clang::warn_unused_result]] Error present( android::sp<android::Fence>* outPresentFence); @@ -266,32 +252,31 @@ public: // Other Display methods - Device& getDevice() const { return mDevice; } hwc2_display_t getId() const { return mId; } bool isConnected() const { return mIsConnected; } + void setConnected(bool connected); // For use by Device only private: - // For use by Device - - void setConnected(bool connected) { mIsConnected = connected; } int32_t getAttribute(hwc2_config_t configId, Attribute attribute); void loadConfig(hwc2_config_t configId); void loadConfigs(); - // For use by Layer - void destroyLayer(hwc2_layer_t layerId); - // This may fail (and return a null pointer) if no layer with this ID exists // on this display - std::shared_ptr<Layer> getLayerById(hwc2_layer_t id) const; + Layer* getLayerById(hwc2_layer_t id) const; // Member variables - Device& mDevice; + // These are references to data owned by HWC2::Device, which will outlive + // this HWC2::Display, so these references are guaranteed to be valid for + // the lifetime of this object. + android::Hwc2::Composer& mComposer; + const std::unordered_set<Capability>& mCapabilities; + hwc2_display_t mId; bool mIsConnected; DisplayType mType; - std::unordered_map<hwc2_layer_t, std::weak_ptr<Layer>> mLayers; + std::unordered_map<hwc2_layer_t, std::unique_ptr<Layer>> mLayers; // The ordering in this map matters, for getConfigs(), when it is // converted to a vector std::map<hwc2_config_t, std::shared_ptr<const Config>> mConfigs; @@ -301,12 +286,18 @@ private: class Layer { public: - Layer(const std::shared_ptr<Display>& display, hwc2_layer_t id); + Layer(android::Hwc2::Composer& composer, + const std::unordered_set<Capability>& capabilities, + hwc2_display_t displayId, hwc2_layer_t layerId); ~Layer(); - bool isAbandoned() const { return mDisplay.expired(); } hwc2_layer_t getId() const { return mId; } + // Register a listener to be notified when the layer is destroyed. When the + // listener function is called, the Layer will be in the process of being + // destroyed, so it's not safe to call methods on it. + void setLayerDestroyedListener(std::function<void(Layer*)> listener); + [[clang::warn_unused_result]] Error setCursorPosition(int32_t x, int32_t y); [[clang::warn_unused_result]] Error setBuffer(uint32_t slot, const android::sp<android::GraphicBuffer>& buffer, @@ -333,11 +324,16 @@ public: [[clang::warn_unused_result]] Error setInfo(uint32_t type, uint32_t appId); private: - std::weak_ptr<Display> mDisplay; + // These are references to data owned by HWC2::Device, which will outlive + // this HWC2::Layer, so these references are guaranteed to be valid for + // the lifetime of this object. + android::Hwc2::Composer& mComposer; + const std::unordered_set<Capability>& mCapabilities; + hwc2_display_t mDisplayId; - Device& mDevice; hwc2_layer_t mId; android_dataspace mDataSpace = HAL_DATASPACE_UNKNOWN; + std::function<void(Layer*)> mLayerDestroyedListener; }; } // namespace HWC2 diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp index abf7dd12d0..b096a3ae57 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp +++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp @@ -65,7 +65,6 @@ HWComposer::HWComposer(const std::string& serviceName) mFreeDisplaySlots(), mHwcDisplaySlots(), mCBContext(), - mEventHandler(nullptr), mVSyncCounts(), mRemainingHwcVirtualDisplays(0) { @@ -74,41 +73,15 @@ HWComposer::HWComposer(const std::string& serviceName) mVSyncCounts[i] = 0; } - loadHwcModule(serviceName); + mHwcDevice = std::make_unique<HWC2::Device>(serviceName); + mRemainingHwcVirtualDisplays = mHwcDevice->getMaxVirtualDisplayCount(); } HWComposer::~HWComposer() {} -void HWComposer::setEventHandler(EventHandler* handler) -{ - if (handler == nullptr) { - ALOGE("setEventHandler: Rejected attempt to clear handler"); - return; - } - - bool wasNull = (mEventHandler == nullptr); - mEventHandler = handler; - - if (wasNull) { - auto hotplugHook = std::bind(&HWComposer::hotplug, this, - std::placeholders::_1, std::placeholders::_2); - mHwcDevice->registerHotplugCallback(hotplugHook); - auto invalidateHook = std::bind(&HWComposer::invalidate, this, - std::placeholders::_1); - mHwcDevice->registerRefreshCallback(invalidateHook); - auto vsyncHook = std::bind(&HWComposer::vsync, this, - std::placeholders::_1, std::placeholders::_2); - mHwcDevice->registerVsyncCallback(vsyncHook); - } -} - -// Load and prepare the hardware composer module. Sets mHwc. -void HWComposer::loadHwcModule(const std::string& serviceName) -{ - ALOGV("loadHwcModule"); - mHwcDevice = std::make_unique<HWC2::Device>(serviceName); - - mRemainingHwcVirtualDisplays = mHwcDevice->getMaxVirtualDisplayCount(); +void HWComposer::registerCallback(HWC2::ComposerCallback* callback, + int32_t sequenceId) { + mHwcDevice->registerCallback(callback, sequenceId); } bool HWComposer::hasCapability(HWC2::Capability capability) const @@ -146,54 +119,51 @@ void HWComposer::validateChange(HWC2::Composition from, HWC2::Composition to) { } } -void HWComposer::hotplug(const std::shared_ptr<HWC2::Display>& display, - HWC2::Connection connected) { - ALOGV("hotplug: %" PRIu64 ", %s", display->getId(), - to_string(connected).c_str()); - int32_t disp = 0; +void HWComposer::onHotplug(hwc2_display_t displayId, + HWC2::Connection connection) { + ALOGV("hotplug: %" PRIu64 ", %s", displayId, + to_string(connection).c_str()); + mHwcDevice->onHotplug(displayId, connection); if (!mDisplayData[0].hwcDisplay) { - ALOGE_IF(connected != HWC2::Connection::Connected, "Assumed primary" + ALOGE_IF(connection != HWC2::Connection::Connected, "Assumed primary" " display would be connected"); - mDisplayData[0].hwcDisplay = display; - mHwcDisplaySlots[display->getId()] = 0; - disp = DisplayDevice::DISPLAY_PRIMARY; + mDisplayData[0].hwcDisplay = mHwcDevice->getDisplayById(displayId); + mHwcDisplaySlots[displayId] = 0; } else { // Disconnect is handled through HWComposer::disconnectDisplay via // SurfaceFlinger's onHotplugReceived callback handling - if (connected == HWC2::Connection::Connected) { - mDisplayData[1].hwcDisplay = display; - mHwcDisplaySlots[display->getId()] = 1; + if (connection == HWC2::Connection::Connected) { + mDisplayData[1].hwcDisplay = mHwcDevice->getDisplayById(displayId); + mHwcDisplaySlots[displayId] = 1; } - disp = DisplayDevice::DISPLAY_EXTERNAL; } - mEventHandler->onHotplugReceived(this, disp, - connected == HWC2::Connection::Connected); } -void HWComposer::invalidate(const std::shared_ptr<HWC2::Display>& /*display*/) { - mEventHandler->onInvalidateReceived(this); -} - -void HWComposer::vsync(const std::shared_ptr<HWC2::Display>& display, - int64_t timestamp) { +bool HWComposer::onVsync(hwc2_display_t displayId, int64_t timestamp, + int32_t* outDisplay) { + auto display = mHwcDevice->getDisplayById(displayId); + if (!display) { + ALOGE("onVsync Failed to find display %" PRIu64, displayId); + return false; + } auto displayType = HWC2::DisplayType::Invalid; auto error = display->getType(&displayType); if (error != HWC2::Error::None) { - ALOGE("vsync: Failed to determine type of display %" PRIu64, + ALOGE("onVsync: Failed to determine type of display %" PRIu64, display->getId()); - return; + return false; } if (displayType == HWC2::DisplayType::Virtual) { ALOGE("Virtual display %" PRIu64 " passed to vsync callback", display->getId()); - return; + return false; } if (mHwcDisplaySlots.count(display->getId()) == 0) { ALOGE("Unknown physical display %" PRIu64 " passed to vsync callback", display->getId()); - return; + return false; } int32_t disp = mHwcDisplaySlots[display->getId()]; @@ -207,17 +177,21 @@ void HWComposer::vsync(const std::shared_ptr<HWC2::Display>& display, if (timestamp == mLastHwVSync[disp]) { ALOGW("Ignoring duplicate VSYNC event from HWC (t=%" PRId64 ")", timestamp); - return; + return false; } mLastHwVSync[disp] = timestamp; } + if (outDisplay) { + *outDisplay = disp; + } + char tag[16]; snprintf(tag, sizeof(tag), "HW_VSYNC_%1u", disp); ATRACE_INT(tag, ++mVSyncCounts[disp] & 1); - mEventHandler->onVSyncReceived(this, disp, timestamp); + return true; } status_t HWComposer::allocateVirtualDisplay(uint32_t width, uint32_t height, @@ -236,7 +210,7 @@ status_t HWComposer::allocateVirtualDisplay(uint32_t width, uint32_t height, return INVALID_OPERATION; } - std::shared_ptr<HWC2::Display> display; + HWC2::Display* display; auto error = mHwcDevice->createVirtualDisplay(width, height, format, &display); if (error != HWC2::Error::None) { @@ -265,13 +239,13 @@ status_t HWComposer::allocateVirtualDisplay(uint32_t width, uint32_t height, return NO_ERROR; } -std::shared_ptr<HWC2::Layer> HWComposer::createLayer(int32_t displayId) { +HWC2::Layer* HWComposer::createLayer(int32_t displayId) { if (!isValidDisplay(displayId)) { ALOGE("Failed to create layer on invalid display %d", displayId); return nullptr; } auto display = mDisplayData[displayId].hwcDisplay; - std::shared_ptr<HWC2::Layer> layer; + HWC2::Layer* layer; auto error = display->createLayer(&layer); if (error != HWC2::Error::None) { ALOGE("Failed to create layer on display %d: %s (%d)", displayId, @@ -281,6 +255,19 @@ std::shared_ptr<HWC2::Layer> HWComposer::createLayer(int32_t displayId) { return layer; } +void HWComposer::destroyLayer(int32_t displayId, HWC2::Layer* layer) { + if (!isValidDisplay(displayId)) { + ALOGE("Failed to destroy layer on invalid display %d", displayId); + return; + } + auto display = mDisplayData[displayId].hwcDisplay; + auto error = display->destroyLayer(layer); + if (error != HWC2::Error::None) { + ALOGE("Failed to destroy layer on display %d: %s (%d)", displayId, + to_string(error).c_str(), static_cast<int32_t>(error)); + } +} + nsecs_t HWComposer::getRefreshTimestamp(int32_t displayId) const { // this returns the last refresh timestamp. // if the last one is not available, we estimate it based on @@ -348,10 +335,8 @@ std::vector<android_color_mode_t> HWComposer::getColorModes(int32_t displayId) c displayId); return modes; } - const std::shared_ptr<HWC2::Display>& hwcDisplay = - mDisplayData[displayId].hwcDisplay; - auto error = hwcDisplay->getColorModes(&modes); + auto error = mDisplayData[displayId].hwcDisplay->getColorModes(&modes); if (error != HWC2::Error::None) { ALOGE("getColorModes failed for display %d: %s (%d)", displayId, to_string(error).c_str(), static_cast<int32_t>(error)); @@ -471,7 +456,7 @@ status_t HWComposer::prepare(DisplayDevice& displayDevice) { return UNKNOWN_ERROR; } if (state == 1) { //Present Succeeded. - std::unordered_map<std::shared_ptr<HWC2::Layer>, sp<Fence>> releaseFences; + std::unordered_map<HWC2::Layer*, sp<Fence>> releaseFences; error = hwcDisplay->getReleaseFences(&releaseFences); displayData.releaseFences = std::move(releaseFences); displayData.lastPresentFence = outPresentFence; @@ -490,8 +475,7 @@ status_t HWComposer::prepare(DisplayDevice& displayDevice) { return BAD_INDEX; } - std::unordered_map<std::shared_ptr<HWC2::Layer>, HWC2::Composition> - changedTypes; + std::unordered_map<HWC2::Layer*, HWC2::Composition> changedTypes; changedTypes.reserve(numTypes); error = hwcDisplay->getChangedCompositionTypes(&changedTypes); if (error != HWC2::Error::None) { @@ -503,8 +487,7 @@ status_t HWComposer::prepare(DisplayDevice& displayDevice) { displayData.displayRequests = static_cast<HWC2::DisplayRequest>(0); - std::unordered_map<std::shared_ptr<HWC2::Layer>, HWC2::LayerRequest> - layerRequests; + std::unordered_map<HWC2::Layer*, HWC2::LayerRequest> layerRequests; layerRequests.reserve(numRequests); error = hwcDisplay->getRequests(&displayData.displayRequests, &layerRequests); @@ -598,7 +581,7 @@ sp<Fence> HWComposer::getPresentFence(int32_t displayId) const { } sp<Fence> HWComposer::getLayerReleaseFence(int32_t displayId, - const std::shared_ptr<HWC2::Layer>& layer) const { + HWC2::Layer* layer) const { if (!isValidDisplay(displayId)) { ALOGE("getLayerReleaseFence: Invalid display"); return Fence::NO_FENCE; @@ -639,7 +622,7 @@ status_t HWComposer::presentAndGetReleaseFences(int32_t displayId) { return UNKNOWN_ERROR; } - std::unordered_map<std::shared_ptr<HWC2::Layer>, sp<Fence>> releaseFences; + std::unordered_map<HWC2::Layer*, sp<Fence>> releaseFences; error = hwcDisplay->getReleaseFences(&releaseFences); if (error != HWC2::Error::None) { ALOGE("presentAndGetReleaseFences: Failed to get release fences " @@ -787,6 +770,8 @@ void HWComposer::disconnectDisplay(int displayId) { auto hwcId = displayData.hwcDisplay->getId(); mHwcDisplaySlots.erase(hwcId); displayData.reset(); + + mHwcDevice->destroyDisplay(hwcId); } status_t HWComposer::setOutputBuffer(int32_t displayId, @@ -885,7 +870,7 @@ void HWComposer::dump(String8& result) const { HWComposer::DisplayData::DisplayData() : hasClientComposition(false), hasDeviceComposition(false), - hwcDisplay(), + hwcDisplay(nullptr), lastPresentFence(Fence::NO_FENCE), outbufHandle(nullptr), outbufAcquireFence(Fence::NO_FENCE), diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h index 3dfb65b1e3..3640bb5a98 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.h +++ b/services/surfaceflinger/DisplayHardware/HWComposer.h @@ -65,23 +65,14 @@ class String8; class HWComposer { public: - class EventHandler { - friend class HWComposer; - virtual void onVSyncReceived( - HWComposer* composer, int32_t disp, nsecs_t timestamp) = 0; - virtual void onHotplugReceived(HWComposer* composer, int32_t disp, bool connected) = 0; - virtual void onInvalidateReceived(HWComposer* composer) = 0; - protected: - virtual ~EventHandler() {} - }; - // Uses the named composer service. Valid choices for normal use // are 'default' and 'vr'. HWComposer(const std::string& serviceName); ~HWComposer(); - void setEventHandler(EventHandler* handler); + void registerCallback(HWC2::ComposerCallback* callback, + int32_t sequenceId); bool hasCapability(HWC2::Capability capability) const; @@ -91,7 +82,9 @@ public: android_pixel_format_t* format, int32_t* outId); // Attempts to create a new layer on this display - std::shared_ptr<HWC2::Layer> createLayer(int32_t displayId); + HWC2::Layer* createLayer(int32_t displayId); + // Destroy a previously created layer + void destroyLayer(int32_t displayId, HWC2::Layer* layer); // Asks the HAL what it can do status_t prepare(DisplayDevice& displayDevice); @@ -126,7 +119,7 @@ public: // Get last release fence for the given layer sp<Fence> getLayerReleaseFence(int32_t displayId, - const std::shared_ptr<HWC2::Layer>& layer) const; + HWC2::Layer* layer) const; // Set the output buffer and acquire fence for a virtual display. // Returns INVALID_OPERATION if displayId is not a virtual display. @@ -142,6 +135,12 @@ public: // Events handling --------------------------------------------------------- + // Returns true if successful, false otherwise. The + // DisplayDevice::DisplayType of the display is returned as an output param. + bool onVsync(hwc2_display_t displayId, int64_t timestamp, + int32_t* outDisplay); + void onHotplug(hwc2_display_t displayId, HWC2::Connection connection); + void setVsyncEnabled(int32_t displayId, HWC2::Vsync enabled); // Query display parameters. Pass in a display index (e.g. @@ -169,19 +168,11 @@ public: private: static const int32_t VIRTUAL_DISPLAY_ID_BASE = 2; - void loadHwcModule(const std::string& serviceName); - bool isValidDisplay(int32_t displayId) const; static void validateChange(HWC2::Composition from, HWC2::Composition to); struct cb_context; - void invalidate(const std::shared_ptr<HWC2::Display>& display); - void vsync(const std::shared_ptr<HWC2::Display>& display, - int64_t timestamp); - void hotplug(const std::shared_ptr<HWC2::Display>& display, - HWC2::Connection connected); - struct DisplayData { DisplayData(); ~DisplayData(); @@ -189,11 +180,10 @@ private: bool hasClientComposition; bool hasDeviceComposition; - std::shared_ptr<HWC2::Display> hwcDisplay; + HWC2::Display* hwcDisplay; HWC2::DisplayRequest displayRequests; sp<Fence> lastPresentFence; // signals when the last set op retires - std::unordered_map<std::shared_ptr<HWC2::Layer>, sp<Fence>> - releaseFences; + std::unordered_map<HWC2::Layer*, sp<Fence>> releaseFences; buffer_handle_t outbufHandle; sp<Fence> outbufAcquireFence; mutable std::unordered_map<int32_t, @@ -214,7 +204,6 @@ private: mutable Mutex mDisplayLock; cb_context* mCBContext; - EventHandler* mEventHandler; size_t mVSyncCounts[HWC_NUM_PHYSICAL_DISPLAY_TYPES]; uint32_t mRemainingHwcVirtualDisplays; diff --git a/services/surfaceflinger/EventControlThread.cpp b/services/surfaceflinger/EventControlThread.cpp index ee6e886d12..052a959724 100644 --- a/services/surfaceflinger/EventControlThread.cpp +++ b/services/surfaceflinger/EventControlThread.cpp @@ -31,34 +31,35 @@ void EventControlThread::setVsyncEnabled(bool enabled) { } bool EventControlThread::threadLoop() { - Mutex::Autolock lock(mMutex); - - bool vsyncEnabled = mVsyncEnabled; - -#ifdef USE_HWC2 - mFlinger->setVsyncEnabled(HWC_DISPLAY_PRIMARY, mVsyncEnabled); -#else - mFlinger->eventControl(HWC_DISPLAY_PRIMARY, SurfaceFlinger::EVENT_VSYNC, - mVsyncEnabled); -#endif + enum class VsyncState {Unset, On, Off}; + auto currentVsyncState = VsyncState::Unset; while (true) { - status_t err = mCond.wait(mMutex); - if (err != NO_ERROR) { - ALOGE("error waiting for new events: %s (%d)", - strerror(-err), err); - return false; + auto requestedVsyncState = VsyncState::On; + { + Mutex::Autolock lock(mMutex); + requestedVsyncState = + mVsyncEnabled ? VsyncState::On : VsyncState::Off; + while (currentVsyncState == requestedVsyncState) { + status_t err = mCond.wait(mMutex); + if (err != NO_ERROR) { + ALOGE("error waiting for new events: %s (%d)", + strerror(-err), err); + return false; + } + requestedVsyncState = + mVsyncEnabled ? VsyncState::On : VsyncState::Off; + } } - if (vsyncEnabled != mVsyncEnabled) { + bool enable = requestedVsyncState == VsyncState::On; #ifdef USE_HWC2 - mFlinger->setVsyncEnabled(HWC_DISPLAY_PRIMARY, mVsyncEnabled); + mFlinger->setVsyncEnabled(HWC_DISPLAY_PRIMARY, enable); #else - mFlinger->eventControl(HWC_DISPLAY_PRIMARY, - SurfaceFlinger::EVENT_VSYNC, mVsyncEnabled); + mFlinger->eventControl(HWC_DISPLAY_PRIMARY, + SurfaceFlinger::EVENT_VSYNC, enable); #endif - vsyncEnabled = mVsyncEnabled; - } + currentVsyncState = requestedVsyncState; } return false; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 3903a5546f..54d4cbd613 100755 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -201,6 +201,12 @@ Layer::~Layer() { } mFlinger->deleteTextureAsync(mTextureName); mFrameTracker.logAndResetStats(mName); + +#ifdef USE_HWC2 + ALOGE_IF(!mHwcLayers.empty(), + "Found stale hardware composer layers when destroying " + "surface flinger layer"); +#endif } // --------------------------------------------------------------------------- @@ -303,7 +309,7 @@ void Layer::onRemoved() { mSurfaceFlingerConsumer->abandon(); #ifdef USE_HWC2 - clearHwcLayers(); + destroyAllHwcLayers(); #endif for (const auto& child : mCurrentChildren) { @@ -364,6 +370,48 @@ sp<IGraphicBufferProducer> Layer::getProducer() const { // h/w composer set-up // --------------------------------------------------------------------------- +#ifdef USE_HWC2 +bool Layer::createHwcLayer(HWComposer* hwc, int32_t hwcId) { + LOG_ALWAYS_FATAL_IF(mHwcLayers.count(hwcId) != 0, + "Already have a layer for hwcId %d", hwcId); + HWC2::Layer* layer = hwc->createLayer(hwcId); + if (!layer) { + return false; + } + HWCInfo& hwcInfo = mHwcLayers[hwcId]; + hwcInfo.hwc = hwc; + hwcInfo.layer = layer; + layer->setLayerDestroyedListener( + [this, hwcId] (HWC2::Layer* /*layer*/){mHwcLayers.erase(hwcId);}); + return true; +} + +void Layer::destroyHwcLayer(int32_t hwcId) { + if (mHwcLayers.count(hwcId) == 0) { + return; + } + auto& hwcInfo = mHwcLayers[hwcId]; + LOG_ALWAYS_FATAL_IF(hwcInfo.layer == nullptr, + "Attempt to destroy null layer"); + LOG_ALWAYS_FATAL_IF(hwcInfo.hwc == nullptr, "Missing HWComposer"); + hwcInfo.hwc->destroyLayer(hwcId, hwcInfo.layer); + // The layer destroyed listener should have cleared the entry from + // mHwcLayers. Verify that. + LOG_ALWAYS_FATAL_IF(mHwcLayers.count(hwcId) != 0, + "Stale layer entry in mHwcLayers"); +} + +void Layer::destroyAllHwcLayers() { + size_t numLayers = mHwcLayers.size(); + for (size_t i = 0; i < numLayers; ++i) { + LOG_ALWAYS_FATAL_IF(mHwcLayers.empty(), "destroyAllHwcLayers failed"); + destroyHwcLayer(mHwcLayers.begin()->first); + } + LOG_ALWAYS_FATAL_IF(!mHwcLayers.empty(), + "All hardware composer layers should have been destroyed"); +} +#endif + Rect Layer::getContentCrop() const { // this is the crop rectangle that applies to the buffer // itself (as opposed to the window) diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 8df8c49bbe..1b7d0759d5 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -447,37 +447,21 @@ public: #ifdef USE_HWC2 // ----------------------------------------------------------------------- + bool createHwcLayer(HWComposer* hwc, int32_t hwcId); + void destroyHwcLayer(int32_t hwcId); + void destroyAllHwcLayers(); + bool hasHwcLayer(int32_t hwcId) { - if (mHwcLayers.count(hwcId) == 0) { - return false; - } - if (mHwcLayers[hwcId].layer->isAbandoned()) { - ALOGI("Erasing abandoned layer %s on %d", mName.string(), hwcId); - mHwcLayers.erase(hwcId); - return false; - } - return true; + return mHwcLayers.count(hwcId) > 0; } - std::shared_ptr<HWC2::Layer> getHwcLayer(int32_t hwcId) { + HWC2::Layer* getHwcLayer(int32_t hwcId) { if (mHwcLayers.count(hwcId) == 0) { return nullptr; } return mHwcLayers[hwcId].layer; } - void setHwcLayer(int32_t hwcId, std::shared_ptr<HWC2::Layer>&& layer) { - if (layer) { - mHwcLayers[hwcId].layer = layer; - } else { - mHwcLayers.erase(hwcId); - } - } - - void clearHwcLayers() { - mHwcLayers.clear(); - } - #endif // ----------------------------------------------------------------------- @@ -766,12 +750,14 @@ private: // HWC items, accessed from the main thread struct HWCInfo { HWCInfo() - : layer(), + : hwc(nullptr), + layer(nullptr), forceClientComposition(false), compositionType(HWC2::Composition::Invalid), clearClientTarget(false) {} - std::shared_ptr<HWC2::Layer> layer; + HWComposer* hwc; + HWC2::Layer* layer; bool forceClientComposition; HWC2::Composition compositionType; bool clearClientTarget; diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.cpp b/services/surfaceflinger/RenderEngine/RenderEngine.cpp index ac2d8b2aba..57f468d2fa 100644 --- a/services/surfaceflinger/RenderEngine/RenderEngine.cpp +++ b/services/surfaceflinger/RenderEngine/RenderEngine.cpp @@ -64,7 +64,7 @@ RenderEngine* RenderEngine::create(EGLDisplay display, int hwcFormat, uint32_t f "EGL_ANDROIDX_no_config_context") && !findExtension(eglQueryStringImplementationANDROID(display, EGL_EXTENSIONS), "EGL_KHR_no_config_context")) { - config = chooseEglConfig(display, hwcFormat); + config = chooseEglConfig(display, hwcFormat, /*logConfig*/ true); } EGLint renderableType = 0; @@ -108,7 +108,7 @@ RenderEngine* RenderEngine::create(EGLDisplay display, int hwcFormat, uint32_t f EGLConfig dummyConfig = config; if (dummyConfig == EGL_NO_CONFIG) { - dummyConfig = chooseEglConfig(display, hwcFormat); + dummyConfig = chooseEglConfig(display, hwcFormat, /*logConfig*/ true); } EGLint attribs[] = { EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE, EGL_NONE }; EGLSurface dummy = eglCreatePbufferSurface(display, dummyConfig, attribs); @@ -406,7 +406,8 @@ static status_t selectEGLConfig(EGLDisplay display, EGLint format, return err; } -EGLConfig RenderEngine::chooseEglConfig(EGLDisplay display, int format) { +EGLConfig RenderEngine::chooseEglConfig(EGLDisplay display, int format, + bool logConfig) { status_t err; EGLConfig config; @@ -427,18 +428,20 @@ EGLConfig RenderEngine::chooseEglConfig(EGLDisplay display, int format) { } } - // print some debugging info - EGLint r,g,b,a; - eglGetConfigAttrib(display, config, EGL_RED_SIZE, &r); - eglGetConfigAttrib(display, config, EGL_GREEN_SIZE, &g); - eglGetConfigAttrib(display, config, EGL_BLUE_SIZE, &b); - eglGetConfigAttrib(display, config, EGL_ALPHA_SIZE, &a); - ALOGI("EGL information:"); - ALOGI("vendor : %s", eglQueryString(display, EGL_VENDOR)); - ALOGI("version : %s", eglQueryString(display, EGL_VERSION)); - ALOGI("extensions: %s", eglQueryString(display, EGL_EXTENSIONS)); - ALOGI("Client API: %s", eglQueryString(display, EGL_CLIENT_APIS)?:"Not Supported"); - ALOGI("EGLSurface: %d-%d-%d-%d, config=%p", r, g, b, a, config); + if (logConfig) { + // print some debugging info + EGLint r,g,b,a; + eglGetConfigAttrib(display, config, EGL_RED_SIZE, &r); + eglGetConfigAttrib(display, config, EGL_GREEN_SIZE, &g); + eglGetConfigAttrib(display, config, EGL_BLUE_SIZE, &b); + eglGetConfigAttrib(display, config, EGL_ALPHA_SIZE, &a); + ALOGI("EGL information:"); + ALOGI("vendor : %s", eglQueryString(display, EGL_VENDOR)); + ALOGI("version : %s", eglQueryString(display, EGL_VERSION)); + ALOGI("extensions: %s", eglQueryString(display, EGL_EXTENSIONS)); + ALOGI("Client API: %s", eglQueryString(display, EGL_CLIENT_APIS)?:"Not Supported"); + ALOGI("EGLSurface: %d-%d-%d-%d, config=%p", r, g, b, a, config); + } return config; } diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.h b/services/surfaceflinger/RenderEngine/RenderEngine.h index 56f582755e..954457946e 100644 --- a/services/surfaceflinger/RenderEngine/RenderEngine.h +++ b/services/surfaceflinger/RenderEngine/RenderEngine.h @@ -64,7 +64,7 @@ public: }; static RenderEngine* create(EGLDisplay display, int hwcFormat, uint32_t featureFlags); - static EGLConfig chooseEglConfig(EGLDisplay display, int format); + static EGLConfig chooseEglConfig(EGLDisplay display, int format, bool logConfig); void primeCache() const; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 4154d6a87f..9dfdaa1d99 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -77,6 +77,7 @@ #include "MonitoredProducer.h" #include "SurfaceFlinger.h" +#include "DisplayHardware/ComposerHal.h" #include "DisplayHardware/FramebufferSurface.h" #include "DisplayHardware/HWComposer.h" #include "DisplayHardware/VirtualDisplaySurface.h" @@ -101,10 +102,24 @@ EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint na namespace android { - using namespace android::hardware::configstore; using namespace android::hardware::configstore::V1_0; +namespace { +class ConditionalLock { +public: + ConditionalLock(Mutex& mutex, bool lock) : mMutex(mutex), mLocked(lock) { + if (lock) { + mMutex.lock(); + } + } + ~ConditionalLock() { if (mLocked) mMutex.unlock(); } +private: + Mutex& mMutex; + bool mLocked; +}; +} // namespace anonymous + // --------------------------------------------------------------------------- const String16 sHardwareTest("android.permission.HARDWARE_TEST"); @@ -147,9 +162,6 @@ SurfaceFlinger::SurfaceFlinger() mLayersRemoved(false), mLayersAdded(false), mRepaintEverything(0), - mHwc(nullptr), - mRealHwc(nullptr), - mVrHwc(nullptr), mHwcServiceName(getHwcServiceName()), mRenderEngine(nullptr), mBootTime(systemTime()), @@ -177,7 +189,9 @@ SurfaceFlinger::SurfaceFlinger() mTotalTime(0), mLastSwapTime(0), mNumLayers(0), - mVrFlingerRequestsDisplay(false) + mVrFlingerRequestsDisplay(false), + mMainThreadId(std::this_thread::get_id()), + mComposerSequenceId(0) { ALOGI("SurfaceFlinger is starting"); @@ -583,48 +597,46 @@ void SurfaceFlinger::init() { ALOGI("Phase offset NS: %" PRId64 "", vsyncPhaseOffsetNs); - { // Autolock scope - Mutex::Autolock _l(mStateLock); + Mutex::Autolock _l(mStateLock); - // initialize EGL for the default display - mEGLDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); - eglInitialize(mEGLDisplay, NULL, NULL); - - // start the EventThread - sp<VSyncSource> vsyncSrc = new DispSyncSource(&mPrimaryDispSync, - vsyncPhaseOffsetNs, true, "app"); - mEventThread = new EventThread(vsyncSrc, *this, false); - sp<VSyncSource> sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync, - sfVsyncPhaseOffsetNs, true, "sf"); - mSFEventThread = new EventThread(sfVsyncSrc, *this, true); - mEventQueue.setEventThread(mSFEventThread); + // initialize EGL for the default display + mEGLDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); + eglInitialize(mEGLDisplay, NULL, NULL); - // set EventThread and SFEventThread to SCHED_FIFO to minimize jitter - struct sched_param param = {0}; - param.sched_priority = 2; - if (sched_setscheduler(mSFEventThread->getTid(), SCHED_FIFO, ¶m) != 0) { - ALOGE("Couldn't set SCHED_FIFO for SFEventThread"); - } - if (sched_setscheduler(mEventThread->getTid(), SCHED_FIFO, ¶m) != 0) { - ALOGE("Couldn't set SCHED_FIFO for EventThread"); - } + // start the EventThread + sp<VSyncSource> vsyncSrc = new DispSyncSource(&mPrimaryDispSync, + vsyncPhaseOffsetNs, true, "app"); + mEventThread = new EventThread(vsyncSrc, *this, false); + sp<VSyncSource> sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync, + sfVsyncPhaseOffsetNs, true, "sf"); + mSFEventThread = new EventThread(sfVsyncSrc, *this, true); + mEventQueue.setEventThread(mSFEventThread); - // Get a RenderEngine for the given display / config (can't fail) - mRenderEngine = RenderEngine::create(mEGLDisplay, - HAL_PIXEL_FORMAT_RGBA_8888, - hasWideColorDisplay ? RenderEngine::WIDE_COLOR_SUPPORT : 0); + // set EventThread and SFEventThread to SCHED_FIFO to minimize jitter + struct sched_param param = {0}; + param.sched_priority = 2; + if (sched_setscheduler(mSFEventThread->getTid(), SCHED_FIFO, ¶m) != 0) { + ALOGE("Couldn't set SCHED_FIFO for SFEventThread"); + } + if (sched_setscheduler(mEventThread->getTid(), SCHED_FIFO, ¶m) != 0) { + ALOGE("Couldn't set SCHED_FIFO for EventThread"); } - // Drop the state lock while we initialize the hardware composer. We drop - // the lock because on creation, it will call back into SurfaceFlinger to - // initialize the primary display. - LOG_ALWAYS_FATAL_IF(mVrFlingerRequestsDisplay, - "Starting with vr flinger active is not currently supported."); - mRealHwc = new HWComposer(mHwcServiceName); - mHwc = mRealHwc; - mHwc->setEventHandler(static_cast<HWComposer::EventHandler*>(this)); + // Get a RenderEngine for the given display / config (can't fail) + mRenderEngine = RenderEngine::create(mEGLDisplay, + HAL_PIXEL_FORMAT_RGBA_8888, + hasWideColorDisplay ? RenderEngine::WIDE_COLOR_SUPPORT : 0); - Mutex::Autolock _l(mStateLock); + // retrieve the EGL context that was selected/created + mEGLContext = mRenderEngine->getEGLContext(); + + LOG_ALWAYS_FATAL_IF(mEGLContext == EGL_NO_CONTEXT, + "couldn't create EGLContext"); + + LOG_ALWAYS_FATAL_IF(mVrFlingerRequestsDisplay, + "Starting with vr flinger active is not currently supported."); + mHwc.reset(new HWComposer(mHwcServiceName)); + mHwc->registerCallback(this, mComposerSequenceId); if (useVrFlinger) { auto vrFlingerRequestDisplayCallback = [this] (bool requestDisplay) { @@ -639,16 +651,6 @@ void SurfaceFlinger::init() { } } - // retrieve the EGL context that was selected/created - mEGLContext = mRenderEngine->getEGLContext(); - - LOG_ALWAYS_FATAL_IF(mEGLContext == EGL_NO_CONTEXT, - "couldn't create EGLContext"); - - // make the GLContext current so that we can create textures when creating - // Layers (which may happens before we render something) - getDefaultDisplayDeviceLocked()->makeCurrent(mEGLDisplay, mEGLContext); - mEventControlThread = new EventControlThread(this); mEventControlThread->run("EventControl", PRIORITY_URGENT_DISPLAY); @@ -1218,11 +1220,16 @@ void SurfaceFlinger::resyncWithRateLimit() { sLastResyncAttempted = now; } -void SurfaceFlinger::onVSyncReceived(HWComposer* composer, int32_t type, - nsecs_t timestamp) { +void SurfaceFlinger::onVsyncReceived(int32_t sequenceId, + hwc2_display_t displayId, int64_t timestamp) { Mutex::Autolock lock(mStateLock); - // Ignore any vsyncs from the non-active hardware composer. - if (composer != mHwc) { + // Ignore any vsyncs from a previous hardware composer. + if (sequenceId != mComposerSequenceId) { + return; + } + + int32_t type; + if (!mHwc->onVsync(displayId, timestamp, &type)) { return; } @@ -1230,7 +1237,7 @@ void SurfaceFlinger::onVSyncReceived(HWComposer* composer, int32_t type, { // Scope for the lock Mutex::Autolock _l(mHWVsyncLock); - if (type == 0 && mPrimaryHWVsyncEnabled) { + if (type == DisplayDevice::DISPLAY_PRIMARY && mPrimaryHWVsyncEnabled) { needsHwVsync = mPrimaryDispSync.addResyncSample(timestamp); } } @@ -1248,7 +1255,7 @@ void SurfaceFlinger::getCompositorTiming(CompositorTiming* compositorTiming) { } void SurfaceFlinger::createDefaultDisplayDevice() { - const int32_t type = DisplayDevice::DISPLAY_PRIMARY; + const DisplayDevice::DisplayType type = DisplayDevice::DISPLAY_PRIMARY; wp<IBinder> token = mBuiltinDisplays[type]; // All non-virtual displays are currently considered secure. @@ -1279,28 +1286,49 @@ void SurfaceFlinger::createDefaultDisplayDevice() { mDisplays.add(token, hw); setActiveColorModeInternal(hw, HAL_COLOR_MODE_NATIVE); hw->setCompositionDataSpace(HAL_DATASPACE_UNKNOWN); -} -void SurfaceFlinger::onHotplugReceived(HWComposer* composer, int32_t disp, bool connected) { - ALOGV("onHotplugReceived(%d, %s)", disp, connected ? "true" : "false"); + // Add the primary display token to mDrawingState so we don't try to + // recreate the DisplayDevice for the primary display. + mDrawingState.displays.add(token, DisplayDeviceState(type, true)); - if (composer->isUsingVrComposer()) { - // We handle initializing the primary display device for the VR - // window manager hwc explicitly at the time of transition. - if (disp != DisplayDevice::DISPLAY_PRIMARY) { - ALOGE("External displays are not supported by the vr hardware composer."); + // make the GLContext current so that we can create textures when creating + // Layers (which may happens before we render something) + hw->makeCurrent(mEGLDisplay, mEGLContext); +} + +void SurfaceFlinger::onHotplugReceived(int32_t sequenceId, + hwc2_display_t display, HWC2::Connection connection, + bool primaryDisplay) { + ALOGV("onHotplugReceived(%d, %" PRIu64 ", %s, %s)", + sequenceId, display, + connection == HWC2::Connection::Connected ? + "connected" : "disconnected", + primaryDisplay ? "primary" : "external"); + + // Only lock if we're not on the main thread. This function is normally + // called on a hwbinder thread, but for the primary display it's called on + // the main thread with the state lock already held, so don't attempt to + // acquire it here. + ConditionalLock lock(mStateLock, + std::this_thread::get_id() != mMainThreadId); + + if (primaryDisplay) { + mHwc->onHotplug(display, connection); + if (!mBuiltinDisplays[DisplayDevice::DISPLAY_PRIMARY].get()) { + createBuiltinDisplayLocked(DisplayDevice::DISPLAY_PRIMARY); } - return; - } - - if (disp == DisplayDevice::DISPLAY_PRIMARY) { - Mutex::Autolock lock(mStateLock); - createBuiltinDisplayLocked(DisplayDevice::DISPLAY_PRIMARY); createDefaultDisplayDevice(); } else { + if (sequenceId != mComposerSequenceId) { + return; + } + if (mHwc->isUsingVrComposer()) { + ALOGE("External displays are not supported by the vr hardware composer."); + return; + } + mHwc->onHotplug(display, connection); auto type = DisplayDevice::DISPLAY_EXTERNAL; - Mutex::Autolock _l(mStateLock); - if (connected) { + if (connection == HWC2::Connection::Connected) { createBuiltinDisplayLocked(type); } else { mCurrentState.displays.removeItem(mBuiltinDisplays[type]); @@ -1312,46 +1340,31 @@ void SurfaceFlinger::onHotplugReceived(HWComposer* composer, int32_t disp, bool } } -void SurfaceFlinger::onInvalidateReceived(HWComposer* composer) { +void SurfaceFlinger::onRefreshReceived(int sequenceId, + hwc2_display_t /*display*/) { Mutex::Autolock lock(mStateLock); - if (composer == mHwc) { - repaintEverything(); - } else { - // This isn't from our current hardware composer. If it's a callback - // from the real composer, forward the refresh request to vr - // flinger. Otherwise ignore it. - if (!composer->isUsingVrComposer()) { - mVrFlinger->OnHardwareComposerRefresh(); - } + if (sequenceId != mComposerSequenceId) { + return; } + repaintEverything(); } void SurfaceFlinger::setVsyncEnabled(int disp, int enabled) { ATRACE_CALL(); + Mutex::Autolock lock(mStateLock); getHwComposer().setVsyncEnabled(disp, enabled ? HWC2::Vsync::Enable : HWC2::Vsync::Disable); } // Note: it is assumed the caller holds |mStateLock| when this is called -void SurfaceFlinger::resetHwcLocked() { +void SurfaceFlinger::resetDisplayState() { disableHardwareVsync(true); - clearHwcLayers(mDrawingState.layersSortedByZ); - clearHwcLayers(mCurrentState.layersSortedByZ); - for (size_t disp = 0; disp < mDisplays.size(); ++disp) { - clearHwcLayers(mDisplays[disp]->getVisibleLayersSortedByZ()); - } // Clear the drawing state so that the logic inside of // handleTransactionLocked will fire. It will determine the delta between // mCurrentState and mDrawingState and re-apply all changes when we make the // transition. mDrawingState.displays.clear(); - // Release virtual display hwcId during vr mode transition. - for (size_t displayId = 0; displayId < mDisplays.size(); ++displayId) { - const sp<DisplayDevice>& displayDevice = mDisplays[displayId]; - if (displayDevice->getDisplayType() == DisplayDevice::DISPLAY_VIRTUAL) { - displayDevice->disconnect(getHwComposer()); - } - } + eglMakeCurrent(mEGLDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); mDisplays.clear(); } @@ -1363,57 +1376,54 @@ void SurfaceFlinger::updateVrFlinger() { return; } - if (vrFlingerRequestsDisplay && !mVrHwc) { - // Construct new HWComposer without holding any locks. - mVrHwc = new HWComposer("vr"); - - // Set up the event handlers. This step is neccessary to initialize the internal state of - // the hardware composer object properly. Our callbacks are designed such that if they are - // triggered between now and the point where the display is properly re-initialized, they - // will not have any effect, so this is safe to do here, before the lock is aquired. - mVrHwc->setEventHandler(static_cast<HWComposer::EventHandler*>(this)); - ALOGV("Vr HWC created"); + if (vrFlingerRequestsDisplay && !mHwc->getComposer()->isRemote()) { + ALOGE("Vr flinger is only supported for remote hardware composer" + " service connections. Ignoring request to transition to vr" + " flinger."); + mVrFlingerRequestsDisplay = false; + return; } Mutex::Autolock _l(mStateLock); - if (vrFlingerRequestsDisplay) { - resetHwcLocked(); - - mHwc = mVrHwc; - mVrFlinger->GrantDisplayOwnership(); + int currentDisplayPowerMode = getDisplayDeviceLocked( + mBuiltinDisplays[DisplayDevice::DISPLAY_PRIMARY])->getPowerMode(); - } else { + if (!vrFlingerRequestsDisplay) { mVrFlinger->SeizeDisplayOwnership(); + } - resetHwcLocked(); + resetDisplayState(); + mHwc.reset(); // Delete the current instance before creating the new one + mHwc.reset(new HWComposer( + vrFlingerRequestsDisplay ? "vr" : mHwcServiceName)); + mHwc->registerCallback(this, ++mComposerSequenceId); - mHwc = mRealHwc; + LOG_ALWAYS_FATAL_IF(!mHwc->getComposer()->isRemote(), + "Switched to non-remote hardware composer"); + + if (vrFlingerRequestsDisplay) { + mVrFlinger->GrantDisplayOwnership(); + } else { enableHardwareVsync(); } mVisibleRegionsDirty = true; invalidateHwcGeometry(); - // Explicitly re-initialize the primary display. This is because some other - // parts of this class rely on the primary display always being available. - createDefaultDisplayDevice(); - // Re-enable default display. - sp<LambdaMessage> requestMessage = new LambdaMessage([&]() { - sp<DisplayDevice> hw(getDisplayDevice(mBuiltinDisplays[DisplayDevice::DISPLAY_PRIMARY])); - setPowerModeInternal(hw, HWC_POWER_MODE_NORMAL); + sp<DisplayDevice> hw(getDisplayDeviceLocked( + mBuiltinDisplays[DisplayDevice::DISPLAY_PRIMARY])); + setPowerModeInternal(hw, currentDisplayPowerMode, /*stateLockHeld*/ true); - // Reset the timing values to account for the period of the swapped in HWC - const auto& activeConfig = mHwc->getActiveConfig(HWC_DISPLAY_PRIMARY); - const nsecs_t period = activeConfig->getVsyncPeriod(); - mAnimFrameTracker.setDisplayRefreshPeriod(period); + // Reset the timing values to account for the period of the swapped in HWC + const auto& activeConfig = mHwc->getActiveConfig(HWC_DISPLAY_PRIMARY); + const nsecs_t period = activeConfig->getVsyncPeriod(); + mAnimFrameTracker.setDisplayRefreshPeriod(period); - // Use phase of 0 since phase is not known. - // Use latency of 0, which will snap to the ideal latency. - setCompositorTimingSnapped(0, period, 0); - }); - postMessageAsync(requestMessage); + // Use phase of 0 since phase is not known. + // Use latency of 0, which will snap to the ideal latency. + setCompositorTimingSnapped(0, period, 0); android_atomic_or(1, &mRepaintEverything); setTransactionFlags(eDisplayTransactionNeeded); @@ -1749,15 +1759,14 @@ void SurfaceFlinger::rebuildLayerStacks() { } else { // Clear out the HWC layer if this layer was // previously visible, but no longer is - layer->setHwcLayer(displayDevice->getHwcDisplayId(), - nullptr); + layer->destroyHwcLayer( + displayDevice->getHwcDisplayId()); } } else { // WM changes displayDevice->layerStack upon sleep/awake. // Here we make sure we delete the HWC layers even if // WM changed their layer stack. - layer->setHwcLayer(displayDevice->getHwcDisplayId(), - nullptr); + layer->destroyHwcLayer(displayDevice->getHwcDisplayId()); } }); } @@ -1872,10 +1881,7 @@ void SurfaceFlinger::setUpHWComposer() { for (size_t i = 0; i < currentLayers.size(); i++) { const auto& layer = currentLayers[i]; if (!layer->hasHwcLayer(hwcId)) { - auto hwcLayer = mHwc->createLayer(hwcId); - if (hwcLayer) { - layer->setHwcLayer(hwcId, std::move(hwcLayer)); - } else { + if (!layer->createHwcLayer(mHwc.get(), hwcId)) { layer->forceClientComposition(hwcId); continue; } @@ -2161,7 +2167,7 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) if (state.surface != NULL) { // Allow VR composer to use virtual displays. - if (mUseHwcVirtualDisplays || mHwc == mVrHwc) { + if (mUseHwcVirtualDisplays || mHwc->isUsingVrComposer()) { int width = 0; int status = state.surface->query( NATIVE_WINDOW_WIDTH, &width); @@ -3285,7 +3291,8 @@ void SurfaceFlinger::onInitializeDisplays() { d.height = 0; displays.add(d); setTransactionState(state, displays, 0); - setPowerModeInternal(getDisplayDevice(d.token), HWC_POWER_MODE_NORMAL); + setPowerModeInternal(getDisplayDevice(d.token), HWC_POWER_MODE_NORMAL, + /*stateLockHeld*/ false); const auto& activeConfig = mHwc->getActiveConfig(HWC_DISPLAY_PRIMARY); const nsecs_t period = activeConfig->getVsyncPeriod(); @@ -3311,7 +3318,7 @@ void SurfaceFlinger::initializeDisplays() { } void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& hw, - int mode) { + int mode, bool stateLockHeld) { ALOGD("Set power mode=%d, type=%d flinger=%p", mode, hw->getDisplayType(), this); int32_t type = hw->getDisplayType(); @@ -3328,7 +3335,7 @@ void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& hw, } if (mInterceptor.isEnabled()) { - Mutex::Autolock _l(mStateLock); + ConditionalLock lock(mStateLock, !stateLockHeld); ssize_t idx = mCurrentState.displays.indexOfKey(hw->getDisplayToken()); if (idx < 0) { ALOGW("Surface Interceptor SavePowerMode: invalid display token"); @@ -3414,7 +3421,8 @@ void SurfaceFlinger::setPowerMode(const sp<IBinder>& display, int mode) { ALOGW("Attempt to set power mode = %d for virtual display", mMode); } else { - mFlinger.setPowerModeInternal(hw, mMode); + mFlinger.setPowerModeInternal( + hw, mMode, /*stateLockHeld*/ false); } return true; } diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 5123b58913..058f4a1d3b 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -60,13 +60,20 @@ #include "SurfaceInterceptor.h" #include "StartPropertySetThread.h" +#ifdef USE_HWC2 +#include "DisplayHardware/HWC2.h" #include "DisplayHardware/HWComposer.h" +#else +#include "DisplayHardware/HWComposer_hwc1.h" +#endif + #include "Effects/Daltonizer.h" #include <map> #include <mutex> #include <queue> #include <string> +#include <thread> #include <utility> namespace android { @@ -99,7 +106,11 @@ enum { class SurfaceFlinger : public BnSurfaceComposer, private IBinder::DeathRecipient, +#ifdef USE_HWC2 + private HWC2::ComposerCallback +#else private HWComposer::EventHandler +#endif { public: @@ -314,11 +325,20 @@ private: virtual void onFirstRef(); /* ------------------------------------------------------------------------ - * HWComposer::EventHandler interface + * HWC2::ComposerCallback / HWComposer::EventHandler interface */ - virtual void onVSyncReceived(HWComposer* composer, int type, nsecs_t timestamp); - virtual void onHotplugReceived(HWComposer* composer, int disp, bool connected); - virtual void onInvalidateReceived(HWComposer* composer); +#ifdef USE_HWC2 + void onVsyncReceived(int32_t sequenceId, hwc2_display_t display, + int64_t timestamp) override; + void onHotplugReceived(int32_t sequenceId, hwc2_display_t display, + HWC2::Connection connection, + bool primaryDisplay) override; + void onRefreshReceived(int32_t sequenceId, hwc2_display_t display) override; +#else + void onVSyncReceived(HWComposer* composer, int type, nsecs_t timestamp) override; + void onHotplugReceived(HWComposer* composer, int disp, bool connected) override; + void onInvalidateReceived(HWComposer* composer) override; +#endif /* ------------------------------------------------------------------------ * Message handling @@ -333,7 +353,12 @@ private: // called on the main thread in response to setActiveConfig() void setActiveConfigInternal(const sp<DisplayDevice>& hw, int mode); // called on the main thread in response to setPowerMode() +#ifdef USE_HWC2 + void setPowerModeInternal(const sp<DisplayDevice>& hw, int mode, + bool stateLockHeld); +#else void setPowerModeInternal(const sp<DisplayDevice>& hw, int mode); +#endif // Called on the main thread in response to setActiveColorMode() void setActiveColorModeInternal(const sp<DisplayDevice>& hw, android_color_mode_t colorMode); @@ -591,13 +616,7 @@ private: /* ------------------------------------------------------------------------ * VrFlinger */ - template<typename T> - void clearHwcLayers(const T& layers) { - for (size_t i = 0; i < layers.size(); ++i) { - layers[i]->clearHwcLayers(); - } - } - void resetHwcLocked(); + void resetDisplayState(); // Check to see if we should handoff to vr flinger. void updateVrFlinger(); @@ -624,13 +643,14 @@ private: // access must be protected by mInvalidateLock volatile int32_t mRepaintEverything; - // current, real and vr hardware composers. - HWComposer* mHwc; + // The current hardware composer interface. When switching into and out of + // vr, our HWComposer instance will be recreated. + std::unique_ptr<HWComposer> mHwc; + #ifdef USE_HWC2 - HWComposer* mRealHwc; - HWComposer* mVrHwc; const std::string mHwcServiceName; // "default" for real use, something else for testing. #endif + // constant members (no synchronization needed for access) RenderEngine* mRenderEngine; nsecs_t mBootTime; @@ -644,10 +664,6 @@ private: EGLDisplay mEGLDisplay; sp<IBinder> mBuiltinDisplays[DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES]; -#ifdef USE_HWC2 - std::unique_ptr<dvr::VrFlinger> mVrFlinger; -#endif - // Can only accessed from the main thread, these members // don't need synchronization State mDrawingState{LayerVector::StateSet::Drawing}; @@ -769,8 +785,14 @@ private: status_t CheckTransactCodeCredentials(uint32_t code); #ifdef USE_HWC2 + std::unique_ptr<dvr::VrFlinger> mVrFlinger; std::atomic<bool> mVrFlingerRequestsDisplay; static bool useVrFlinger; + std::thread::id mMainThreadId; + // The composer sequence id is a monotonically increasing integer that we + // use to differentiate callbacks from different hardware composer + // instances. Each hardware composer instance gets a different sequence id. + int32_t mComposerSequenceId; #endif float mSaturation = 1.0f; diff --git a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp index 7aaa42aa4b..78a04e08e1 100644 --- a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp +++ b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp @@ -535,8 +535,8 @@ void SurfaceFlinger::init() { // Initialize the H/W composer object. There may or may not be an // actual hardware composer underneath. - mHwc = new HWComposer(this, - *static_cast<HWComposer::EventHandler *>(this)); + mHwc.reset(new HWComposer(this, + *static_cast<HWComposer::EventHandler *>(this))); // get a RenderEngine for the given display / config (can't fail) mRenderEngine = RenderEngine::create(mEGLDisplay, |