diff options
| -rw-r--r-- | libs/vr/libvrflinger/display_service.cpp | 8 | ||||
| -rw-r--r-- | libs/vr/libvrflinger/hardware_composer.cpp | 354 | ||||
| -rw-r--r-- | libs/vr/libvrflinger/hardware_composer.h | 100 |
3 files changed, 267 insertions, 195 deletions
diff --git a/libs/vr/libvrflinger/display_service.cpp b/libs/vr/libvrflinger/display_service.cpp index af18e218d5..10abc5efa3 100644 --- a/libs/vr/libvrflinger/display_service.cpp +++ b/libs/vr/libvrflinger/display_service.cpp @@ -349,17 +349,9 @@ DisplayService::GetVisibleDisplaySurfaces() const { void DisplayService::UpdateActiveDisplaySurfaces() { auto visible_surfaces = GetVisibleDisplaySurfaces(); - - std::sort(visible_surfaces.begin(), visible_surfaces.end(), - [](const std::shared_ptr<DisplaySurface>& a, - const std::shared_ptr<DisplaySurface>& b) { - return a->z_order() < b->z_order(); - }); - ALOGD_IF(TRACE, "DisplayService::UpdateActiveDisplaySurfaces: %zd visible surfaces", visible_surfaces.size()); - hardware_composer_.SetDisplaySurfaces(std::move(visible_surfaces)); } diff --git a/libs/vr/libvrflinger/hardware_composer.cpp b/libs/vr/libvrflinger/hardware_composer.cpp index f9a5dcd987..66325ef3dd 100644 --- a/libs/vr/libvrflinger/hardware_composer.cpp +++ b/libs/vr/libvrflinger/hardware_composer.cpp @@ -85,9 +85,6 @@ bool SetThreadPolicy(const std::string& scheduler_class, } // anonymous namespace -// HardwareComposer static data; -constexpr size_t HardwareComposer::kMaxHardwareLayers; - HardwareComposer::HardwareComposer() : initialized_(false), request_display_callback_(nullptr) {} @@ -98,7 +95,7 @@ HardwareComposer::~HardwareComposer(void) { } bool HardwareComposer::Initialize( - Hwc2::Composer* hidl, RequestDisplayCallback request_display_callback) { + Hwc2::Composer* composer, RequestDisplayCallback request_display_callback) { if (initialized_) { ALOGE("HardwareComposer::Initialize: already initialized."); return false; @@ -109,7 +106,7 @@ bool HardwareComposer::Initialize( HWC::Error error = HWC::Error::None; Hwc2::Config config; - error = hidl->getActiveConfig(HWC_DISPLAY_PRIMARY, &config); + error = composer->getActiveConfig(HWC_DISPLAY_PRIMARY, &config); if (error != HWC::Error::None) { ALOGE("HardwareComposer: Failed to get current display config : %d", @@ -117,7 +114,7 @@ bool HardwareComposer::Initialize( return false; } - error = GetDisplayMetrics(hidl, HWC_DISPLAY_PRIMARY, config, + error = GetDisplayMetrics(composer, HWC_DISPLAY_PRIMARY, config, &native_display_metrics_); if (error != HWC::Error::None) { @@ -140,6 +137,9 @@ bool HardwareComposer::Initialize( display_transform_ = HWC_TRANSFORM_NONE; display_metrics_ = native_display_metrics_; + // Setup the display metrics used by all Layer instances. + Layer::SetDisplayMetrics(native_display_metrics_); + post_thread_event_fd_.Reset(eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK)); LOG_ALWAYS_FATAL_IF( !post_thread_event_fd_, @@ -198,9 +198,10 @@ void HardwareComposer::UpdatePostThreadState(PostThreadStateType state, } void HardwareComposer::OnPostThreadResumed() { - hidl_.reset(new Hwc2::Composer("default")); - hidl_callback_ = new ComposerCallback; - hidl_->registerCallback(hidl_callback_); + composer_.reset(new Hwc2::Composer("default")); + composer_callback_ = new ComposerCallback; + composer_->registerCallback(composer_callback_); + Layer::SetComposer(composer_.get()); EnableVsync(true); @@ -217,19 +218,15 @@ void HardwareComposer::OnPostThreadResumed() { void HardwareComposer::OnPostThreadPaused() { retire_fence_fds_.clear(); - display_surfaces_.clear(); - - for (size_t i = 0; i < kMaxHardwareLayers; ++i) { - layers_[i].Reset(); - } - active_layer_count_ = 0; + layers_.clear(); - if (hidl_) { + if (composer_) { EnableVsync(false); } - hidl_callback_ = nullptr; - hidl_.reset(nullptr); + composer_callback_ = nullptr; + composer_.reset(nullptr); + Layer::SetComposer(nullptr); // Trigger target-specific performance mode change. property_set(kDvrPerformanceProperty, "idle"); @@ -239,21 +236,21 @@ HWC::Error HardwareComposer::Validate(hwc2_display_t display) { uint32_t num_types; uint32_t num_requests; HWC::Error error = - hidl_->validateDisplay(display, &num_types, &num_requests); + composer_->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 = hidl_->acceptDisplayChanges(display); + error = composer_->acceptDisplayChanges(display); } return error; } HWC::Error HardwareComposer::EnableVsync(bool enabled) { - return hidl_->setVsyncEnabled( + return composer_->setVsyncEnabled( HWC_DISPLAY_PRIMARY, (Hwc2::IComposerClient::Vsync)(enabled ? HWC2_VSYNC_ENABLE : HWC2_VSYNC_DISABLE)); @@ -261,7 +258,7 @@ HWC::Error HardwareComposer::EnableVsync(bool enabled) { HWC::Error HardwareComposer::Present(hwc2_display_t display) { int32_t present_fence; - HWC::Error error = hidl_->presentDisplay(display, &present_fence); + HWC::Error error = composer_->presentDisplay(display, &present_fence); // According to the documentation, this fence is signaled at the time of // vsync/DMA for physical displays. @@ -275,21 +272,21 @@ HWC::Error HardwareComposer::Present(hwc2_display_t display) { return error; } -HWC::Error HardwareComposer::GetDisplayAttribute(Hwc2::Composer* hidl, +HWC::Error HardwareComposer::GetDisplayAttribute(Hwc2::Composer* composer, hwc2_display_t display, hwc2_config_t config, hwc2_attribute_t attribute, int32_t* out_value) const { - return hidl->getDisplayAttribute( + return composer->getDisplayAttribute( display, config, (Hwc2::IComposerClient::Attribute)attribute, out_value); } HWC::Error HardwareComposer::GetDisplayMetrics( - Hwc2::Composer* hidl, hwc2_display_t display, hwc2_config_t config, + Hwc2::Composer* composer, hwc2_display_t display, hwc2_config_t config, HWCDisplayMetrics* out_metrics) const { HWC::Error error; - error = GetDisplayAttribute(hidl, display, config, HWC2_ATTRIBUTE_WIDTH, + error = GetDisplayAttribute(composer, display, config, HWC2_ATTRIBUTE_WIDTH, &out_metrics->width); if (error != HWC::Error::None) { ALOGE( @@ -298,7 +295,7 @@ HWC::Error HardwareComposer::GetDisplayMetrics( return error; } - error = GetDisplayAttribute(hidl, display, config, HWC2_ATTRIBUTE_HEIGHT, + error = GetDisplayAttribute(composer, display, config, HWC2_ATTRIBUTE_HEIGHT, &out_metrics->height); if (error != HWC::Error::None) { ALOGE( @@ -307,7 +304,7 @@ HWC::Error HardwareComposer::GetDisplayMetrics( return error; } - error = GetDisplayAttribute(hidl, display, config, + error = GetDisplayAttribute(composer, display, config, HWC2_ATTRIBUTE_VSYNC_PERIOD, &out_metrics->vsync_period_ns); if (error != HWC::Error::None) { @@ -317,7 +314,7 @@ HWC::Error HardwareComposer::GetDisplayMetrics( return error; } - error = GetDisplayAttribute(hidl, display, config, HWC2_ATTRIBUTE_DPI_X, + error = GetDisplayAttribute(composer, display, config, HWC2_ATTRIBUTE_DPI_X, &out_metrics->dpi.x); if (error != HWC::Error::None) { ALOGE( @@ -326,7 +323,7 @@ HWC::Error HardwareComposer::GetDisplayMetrics( return error; } - error = GetDisplayAttribute(hidl, display, config, HWC2_ATTRIBUTE_DPI_Y, + error = GetDisplayAttribute(composer, display, config, HWC2_ATTRIBUTE_DPI_Y, &out_metrics->dpi.y); if (error != HWC::Error::None) { ALOGE( @@ -349,10 +346,10 @@ std::string HardwareComposer::Dump() { << std::endl; stream << "Post thread resumed: " << post_thread_resumed_ << std::endl; - stream << "Active layers: " << active_layer_count_ << std::endl; + stream << "Active layers: " << layers_.size() << std::endl; stream << std::endl; - for (size_t i = 0; i < active_layer_count_; i++) { + for (size_t i = 0; i < layers_.size(); i++) { stream << "Layer " << i << ":"; stream << " type=" << layers_[i].GetCompositionType().to_string(); stream << " surface_id=" << layers_[i].GetSurfaceId(); @@ -363,7 +360,7 @@ std::string HardwareComposer::Dump() { if (post_thread_resumed_) { stream << "Hardware Composer Debug Info:" << std::endl; - stream << hidl_->dumpDebugInfo(); + stream << composer_->dumpDebugInfo(); } return stream.str(); @@ -373,8 +370,8 @@ void HardwareComposer::PostLayers() { ATRACE_NAME("HardwareComposer::PostLayers"); // Setup the hardware composer layers with current buffers. - for (size_t i = 0; i < active_layer_count_; i++) { - layers_[i].Prepare(); + for (auto& layer : layers_) { + layer.Prepare(); } HWC::Error error = Validate(HWC_DISPLAY_PRIMARY); @@ -408,8 +405,8 @@ void HardwareComposer::PostLayers() { "Warning: dropping a frame to catch up with HWC (pending = %zd)", retire_fence_fds_.size()); - for (size_t i = 0; i < active_layer_count_; i++) { - layers_[i].Drop(); + for (auto& layer : layers_) { + layer.Drop(); } return; } else { @@ -419,7 +416,7 @@ void HardwareComposer::PostLayers() { } #if TRACE > 1 - for (size_t i = 0; i < active_layer_count_; i++) { + for (size_t i = 0; i < layers_.size(); i++) { ALOGI("HardwareComposer::PostLayers: layer=%zu buffer_id=%d composition=%s", i, layers_[i].GetBufferId(), layers_[i].GetCompositionType().to_string().c_str()); @@ -435,18 +432,18 @@ void HardwareComposer::PostLayers() { std::vector<Hwc2::Layer> out_layers; std::vector<int> out_fences; - error = hidl_->getReleaseFences(HWC_DISPLAY_PRIMARY, &out_layers, - &out_fences); + error = composer_->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()); - // Perform post-frame bookkeeping. Unused layers are a no-op. + // Perform post-frame bookkeeping. uint32_t num_elements = out_layers.size(); for (size_t i = 0; i < num_elements; ++i) { - for (size_t j = 0; j < active_layer_count_; ++j) { - if (layers_[j].GetLayerHandle() == out_layers[i]) { - layers_[j].Finish(out_fences[i]); + for (auto& layer : layers_) { + if (layer.GetLayerHandle() == out_layers[i]) { + layer.Finish(out_fences[i]); } } } @@ -618,12 +615,12 @@ int HardwareComposer::ReadWaitPPState() { // vsync already passed since the last call, returns the latest vsync timestamp // instead of blocking. int HardwareComposer::WaitForVSync(int64_t* timestamp) { - int error = PostThreadPollInterruptible( - hidl_callback_->GetVsyncEventFd(), POLLIN, /*timeout_ms*/ 1000); + int error = PostThreadPollInterruptible(composer_callback_->GetVsyncEventFd(), + POLLIN, /*timeout_ms*/ 1000); if (error == kPostThreadInterrupted || error < 0) { return error; } else { - *timestamp = hidl_callback_->GetVsyncTime(); + *timestamp = composer_callback_->GetVsyncTime(); return 0; } } @@ -827,38 +824,60 @@ bool HardwareComposer::UpdateLayerConfig() { ATRACE_NAME("UpdateLayerConfig_HwLayers"); - display_surfaces_.clear(); + // Sort the new direct surface list by z-order to determine the relative order + // of the surfaces. This relative order is used for the HWC z-order value to + // insulate VrFlinger and HWC z-order semantics from each other. + std::sort(surfaces.begin(), surfaces.end(), [](const auto& a, const auto& b) { + return a->z_order() < b->z_order(); + }); - Layer* target_layer; - size_t layer_index; - for (layer_index = 0; - layer_index < std::min(surfaces.size(), kMaxHardwareLayers); - layer_index++) { + // Prepare a new layer stack, pulling in layers from the previous + // layer stack that are still active and updating their attributes. + std::vector<Layer> layers; + size_t layer_index = 0; + for (const auto& surface : surfaces) { // 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], native_display_metrics_, - hidl_.get(), blending, - display_transform_, HWC::Composition::Device, - layer_index); - display_surfaces_.push_back(surfaces[layer_index]); - } - // Clear unused layers. - for (size_t i = layer_index; i < kMaxHardwareLayers; i++) - layers_[i].Reset(); + // Try to find a layer for this surface in the set of active layers. + auto search = + std::lower_bound(layers_.begin(), layers_.end(), surface->surface_id()); + const bool found = search != layers_.end() && + search->GetSurfaceId() == surface->surface_id(); + if (found) { + // Update the attributes of the layer that may have changed. + search->SetBlending(blending); + search->SetZOrder(layer_index); // Relative z-order. + + // Move the existing layer to the new layer set and remove the empty layer + // object from the current set. + layers.push_back(std::move(*search)); + layers_.erase(search); + } else { + // Insert a layer for the new surface. + layers.emplace_back(surface, blending, display_transform_, + HWC::Composition::Device, layer_index); + } - active_layer_count_ = layer_index; - ALOGD_IF(TRACE, "HardwareComposer::UpdateLayerConfig: %zd active layers", - active_layer_count_); + ALOGI_IF( + TRACE, + "HardwareComposer::UpdateLayerConfig: layer_index=%zu surface_id=%d", + layer_index, layers[layer_index].GetSurfaceId()); + + layer_index++; + } + + // Sort the new layer stack by ascending surface id. + std::sort(layers.begin(), layers.end()); - // Any surfaces left over could not be assigned a hardware layer and will - // not be displayed. - ALOGW_IF(surfaces.size() != display_surfaces_.size(), - "HardwareComposer::UpdateLayerConfig: More surfaces than layers: " - "pending_surfaces=%zu display_surfaces=%zu", - surfaces.size(), display_surfaces_.size()); + // Replace the previous layer set with the new layer set. The destructor of + // the previous set will clean up the remaining Layers that are not moved to + // the new layer set. + layers_ = std::move(layers); + ALOGD_IF(TRACE, "HardwareComposer::UpdateLayerConfig: %zd active layers", + layers_.size()); return true; } @@ -920,13 +939,15 @@ int64_t HardwareComposer::ComposerCallback::GetVsyncTime() { return return_val; } +Hwc2::Composer* Layer::composer_{nullptr}; +HWCDisplayMetrics Layer::display_metrics_{0, 0, {0, 0}, 0}; + void Layer::Reset() { - if (hidl_ != nullptr && hardware_composer_layer_) { - hidl_->destroyLayer(HWC_DISPLAY_PRIMARY, hardware_composer_layer_); + if (hardware_composer_layer_) { + composer_->destroyLayer(HWC_DISPLAY_PRIMARY, hardware_composer_layer_); hardware_composer_layer_ = 0; } - hidl_ = nullptr; z_order_ = 0; blending_ = HWC::BlendMode::None; transform_ = HWC::Transform::None; @@ -935,38 +956,52 @@ void Layer::Reset() { source_ = EmptyVariant{}; acquire_fence_.Close(); surface_rect_functions_applied_ = false; + pending_visibility_settings_ = true; } -void Layer::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_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(display_metrics); +Layer::Layer(const std::shared_ptr<DirectDisplaySurface>& surface, + HWC::BlendMode blending, HWC::Transform transform, + HWC::Composition composition_type, size_t z_order) + : z_order_{z_order}, + blending_{blending}, + transform_{transform}, + target_composition_type_{composition_type}, + source_{SourceSurface{surface}} { + CommonLayerSetup(); } -void Layer::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) { - 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(display_metrics); +Layer::Layer(const std::shared_ptr<IonBuffer>& buffer, HWC::BlendMode blending, + HWC::Transform transform, HWC::Composition composition_type, + size_t z_order) + : z_order_{z_order}, + blending_{blending}, + transform_{transform}, + target_composition_type_{composition_type}, + source_{SourceBuffer{buffer}} { + CommonLayerSetup(); +} + +Layer::~Layer() { Reset(); } + +Layer::Layer(Layer&& other) { *this = std::move(other); } + +Layer& Layer::operator=(Layer&& other) { + if (this != &other) { + Reset(); + using std::swap; + swap(hardware_composer_layer_, other.hardware_composer_layer_); + swap(z_order_, other.z_order_); + swap(blending_, other.blending_); + swap(transform_, other.transform_); + swap(composition_type_, other.composition_type_); + swap(target_composition_type_, other.target_composition_type_); + swap(source_, other.source_); + swap(acquire_fence_, other.acquire_fence_); + swap(surface_rect_functions_applied_, + other.surface_rect_functions_applied_); + swap(pending_visibility_settings_, other.pending_visibility_settings_); + } + return *this; } void Layer::UpdateBuffer(const std::shared_ptr<IonBuffer>& buffer) { @@ -974,8 +1009,19 @@ void Layer::UpdateBuffer(const std::shared_ptr<IonBuffer>& buffer) { std::get<SourceBuffer>(source_) = {buffer}; } -void Layer::SetBlending(HWC::BlendMode blending) { blending_ = blending; } -void Layer::SetZOrder(size_t z_order) { z_order_ = z_order; } +void Layer::SetBlending(HWC::BlendMode blending) { + if (blending_ != blending) { + blending_ = blending; + pending_visibility_settings_ = true; + } +} + +void Layer::SetZOrder(size_t z_order) { + if (z_order_ != z_order) { + z_order_ = z_order; + pending_visibility_settings_ = true; + } +} IonBuffer* Layer::GetBuffer() { struct Visitor { @@ -986,18 +1032,35 @@ IonBuffer* Layer::GetBuffer() { return source_.Visit(Visitor{}); } -void Layer::UpdateLayerSettings(const HWCDisplayMetrics& display_metrics) { - if (!IsLayerSetup()) { - ALOGE( - "HardwareComposer::Layer::UpdateLayerSettings: Attempt to update " - "unused Layer!"); - return; +void Layer::UpdateVisibilitySettings() { + if (pending_visibility_settings_) { + pending_visibility_settings_ = false; + + HWC::Error error; + hwc2_display_t display = HWC_DISPLAY_PRIMARY; + + error = composer_->setLayerBlendMode( + display, hardware_composer_layer_, + blending_.cast<Hwc2::IComposerClient::BlendMode>()); + ALOGE_IF(error != HWC::Error::None, + "Layer::UpdateLayerSettings: Error setting layer blend mode: %s", + error.to_string().c_str()); + + error = + composer_->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::UpdateLayerSettings() { HWC::Error error; hwc2_display_t display = HWC_DISPLAY_PRIMARY; - error = hidl_->setLayerCompositionType( + UpdateVisibilitySettings(); + + error = composer_->setLayerCompositionType( display, hardware_composer_layer_, composition_type_.cast<Hwc2::IComposerClient::Composition>()); ALOGE_IF( @@ -1005,48 +1068,37 @@ void Layer::UpdateLayerSettings(const HWCDisplayMetrics& display_metrics) { "Layer::UpdateLayerSettings: Error setting layer composition type: %s", error.to_string().c_str()); - error = hidl_->setLayerBlendMode( - display, hardware_composer_layer_, - blending_.cast<Hwc2::IComposerClient::BlendMode>()); - ALOGE_IF(error != HWC::Error::None, - "Layer::UpdateLayerSettings: Error setting layer blend mode: %s", - error.to_string().c_str()); - // TODO(eieio): Use surface attributes or some other mechanism to control // the layer display frame. - error = hidl_->setLayerDisplayFrame( + error = composer_->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 = hidl_->setLayerVisibleRegion( + error = composer_->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 = hidl_->setLayerPlaneAlpha(display, hardware_composer_layer_, 1.0f); + error = + composer_->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 = 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(const HWCDisplayMetrics& display_metrics) { +void Layer::CommonLayerSetup() { HWC::Error error = - 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(display_metrics); + composer_->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(); } void Layer::Prepare() { @@ -1058,19 +1110,23 @@ void Layer::Prepare() { std::tie(right, bottom, handle, acquire_fence_) = source.Acquire(); }); - // When a layer is first setup there may be some time before the first buffer - // arrives. Setup the HWC layer as a solid color to stall for time until the - // first buffer arrives. Once the first buffer arrives there will always be a - // buffer for the frame even if it is old. + // Update any visibility (blending, z-order) changes that occurred since + // last prepare. + UpdateVisibilitySettings(); + + // When a layer is first setup there may be some time before the first + // buffer arrives. Setup the HWC layer as a solid color to stall for time + // until the first buffer arrives. Once the first buffer arrives there will + // always be a buffer for the frame even if it is old. if (!handle.get()) { if (composition_type_ == HWC::Composition::Invalid) { composition_type_ = HWC::Composition::SolidColor; - hidl_->setLayerCompositionType( + composer_->setLayerCompositionType( HWC_DISPLAY_PRIMARY, hardware_composer_layer_, composition_type_.cast<Hwc2::IComposerClient::Composition>()); Hwc2::IComposerClient::Color layer_color = {0, 0, 0, 0}; - hidl_->setLayerColor(HWC_DISPLAY_PRIMARY, hardware_composer_layer_, - layer_color); + composer_->setLayerColor(HWC_DISPLAY_PRIMARY, hardware_composer_layer_, + layer_color); } else { // The composition type is already set. Nothing else to do until a // buffer arrives. @@ -1078,15 +1134,15 @@ void Layer::Prepare() { } else { if (composition_type_ != target_composition_type_) { composition_type_ = target_composition_type_; - hidl_->setLayerCompositionType( + composer_->setLayerCompositionType( HWC_DISPLAY_PRIMARY, hardware_composer_layer_, composition_type_.cast<Hwc2::IComposerClient::Composition>()); } HWC::Error error{HWC::Error::None}; - error = hidl_->setLayerBuffer(HWC_DISPLAY_PRIMARY, - hardware_composer_layer_, 0, handle, - acquire_fence_.Get()); + error = + composer_->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", @@ -1095,9 +1151,9 @@ void Layer::Prepare() { if (!surface_rect_functions_applied_) { const float float_right = right; const float float_bottom = bottom; - error = hidl_->setLayerSourceCrop(HWC_DISPLAY_PRIMARY, - hardware_composer_layer_, - {0, 0, float_right, float_bottom}); + error = composer_->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 fc0efeeeb4..550e6877f5 100644 --- a/libs/vr/libvrflinger/hardware_composer.h +++ b/libs/vr/libvrflinger/hardware_composer.h @@ -52,10 +52,7 @@ struct HWCDisplayMetrics { // source supplying buffers for the layer's contents. class Layer { public: - Layer() {} - - // Releases any shared pointers and fence handles held by this instance. - void Reset(); + Layer() = default; // Sets up the layer to use a display surface as its content source. The Layer // automatically handles ACQUIRE/RELEASE phases for the surface's buffer train @@ -66,10 +63,9 @@ class Layer { // |composition_type| receives either HWC_FRAMEBUFFER for most layers or // 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); + Layer(const std::shared_ptr<DirectDisplaySurface>& surface, + HWC::BlendMode blending, HWC::Transform transform, + HWC::Composition composition_type, size_t z_roder); // Sets up the layer to use a direct buffer as its content source. No special // handling of the buffer is performed; responsibility for updating or @@ -79,10 +75,17 @@ 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, - const HWCDisplayMetrics& display_metrics, Hwc2::Composer* hidl, - HWC::BlendMode blending, HWC::Transform transform, - HWC::Composition composition_type, size_t z_order); + Layer(const std::shared_ptr<IonBuffer>& buffer, HWC::BlendMode blending, + HWC::Transform transform, HWC::Composition composition_type, + size_t z_order); + + Layer(Layer&&); + Layer& operator=(Layer&&); + + ~Layer(); + + // Releases any shared pointers and fence handles held by this instance. + void Reset(); // Layers that use a direct IonBuffer should call this each frame to update // which buffer will be used for the next PostLayers. @@ -117,9 +120,6 @@ class Layer { HWC::Layer GetLayerHandle() const { return hardware_composer_layer_; } bool IsLayerSetup() const { return !source_.empty(); } - // Applies all of the settings to this layer using the hwc functions - void UpdateLayerSettings(const HWCDisplayMetrics& display_metrics); - int GetSurfaceId() const { int surface_id = -1; pdx::rpc::IfAnyOf<SourceSurface>::Call( @@ -138,10 +138,41 @@ class Layer { return buffer_id; } + // Compares Layers by surface id. + bool operator<(const Layer& other) const { + return GetSurfaceId() < other.GetSurfaceId(); + } + bool operator<(int surface_id) const { + return GetSurfaceId() < surface_id; + } + + // Sets the composer instance used by all Layer instances. + static void SetComposer(Hwc2::Composer* composer) { composer_ = composer; } + + // Sets the display metrics used by all Layer instances. + static void SetDisplayMetrics(HWCDisplayMetrics display_metrics) { + display_metrics_ = display_metrics; + } + private: - void CommonLayerSetup(const HWCDisplayMetrics& display_metrics); + void CommonLayerSetup(); + + // Applies all of the settings to this layer using the hwc functions + void UpdateLayerSettings(); - Hwc2::Composer* hidl_ = nullptr; + // Applies visibility settings that may have changed. + void UpdateVisibilitySettings(); + + // Composer instance shared by all instances of Layer. This must be set + // whenever a new instance of the Composer is created. This may be set to + // nullptr as long as there are no instances of Layer that might need to use + // it. + static Hwc2::Composer* composer_; + + // Display metrics shared by all instances of Layer. This must be set at least + // once during VrFlinger initialization and is expected to remain constant + // thereafter. + static HWCDisplayMetrics display_metrics_; // The hardware composer layer and metrics to use during the prepare cycle. hwc2_layer_t hardware_composer_layer_ = 0; @@ -235,6 +266,7 @@ class Layer { pdx::LocalHandle acquire_fence_; bool surface_rect_functions_applied_ = false; + bool pending_visibility_settings_ = true; Layer(const Layer&) = delete; void operator=(const Layer&) = delete; @@ -254,14 +286,10 @@ class HardwareComposer { using VSyncCallback = std::function<void(int, int64_t, int64_t, uint32_t)>; using RequestDisplayCallback = std::function<void(bool)>; - // Since there is no universal way to query the number of hardware layers, - // just set it to 4 for now. - static constexpr size_t kMaxHardwareLayers = 4; - HardwareComposer(); ~HardwareComposer(); - bool Initialize(Hwc2::Composer* hidl, + bool Initialize(Hwc2::Composer* composer, RequestDisplayCallback request_display_callback); bool IsInitialized() const { return initialized_; } @@ -299,11 +327,11 @@ class HardwareComposer { void OnDeletedGlobalBuffer(DvrGlobalBufferKey key); private: - HWC::Error GetDisplayAttribute(Hwc2::Composer* hidl, hwc2_display_t display, - hwc2_config_t config, + HWC::Error GetDisplayAttribute(Hwc2::Composer* composer, + 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, + HWC::Error GetDisplayMetrics(Hwc2::Composer* composer, hwc2_display_t display, hwc2_config_t config, HWCDisplayMetrics* out_metrics) const; @@ -319,6 +347,7 @@ class HardwareComposer { int64_t timestamp) override; const pdx::LocalHandle& GetVsyncEventFd() const; int64_t GetVsyncTime(); + private: std::mutex vsync_mutex_; pdx::LocalHandle vsync_event_fd_; @@ -356,8 +385,7 @@ class HardwareComposer { // the case of a timeout. If we're interrupted, kPostThreadInterrupted will be // returned. int PostThreadPollInterruptible(const pdx::LocalHandle& event_fd, - int requested_events, - int timeout_ms); + int requested_events, int timeout_ms); // WaitForVSync and SleepUntil are blocking calls made on the post thread that // can be interrupted by a control thread. If interrupted, these calls return @@ -386,8 +414,8 @@ class HardwareComposer { bool initialized_; - std::unique_ptr<Hwc2::Composer> hidl_; - sp<ComposerCallback> hidl_callback_; + std::unique_ptr<Hwc2::Composer> composer_; + sp<ComposerCallback> composer_callback_; RequestDisplayCallback request_display_callback_; // Display metrics of the physical display. @@ -403,13 +431,9 @@ class HardwareComposer { // thread and read by the post thread. std::vector<std::shared_ptr<DirectDisplaySurface>> pending_surfaces_; - // The surfaces displayed by the post thread. Used exclusively by the post - // thread. - std::vector<std::shared_ptr<DirectDisplaySurface>> display_surfaces_; - - // Layer array for handling buffer flow into hardware composer layers. - std::array<Layer, kMaxHardwareLayers> layers_; - size_t active_layer_count_ = 0; + // Layer set for handling buffer flow into hardware composer layers. This + // vector must be sorted by surface_id in ascending order. + std::vector<Layer> layers_; // Handler to hook vsync events outside of this class. VSyncCallback vsync_callback_; @@ -419,8 +443,8 @@ class HardwareComposer { std::thread post_thread_; // Post thread state machine and synchronization primitives. - PostThreadStateType post_thread_state_{ - PostThreadState::Idle | PostThreadState::Suspended}; + 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_; |