Use the HWC caching mechanism to avoid stalls in the ion driver.
HWC supports caching buffers for layers using "slot" assignments.
Use this in VrFlinger to avoid importing a buffer handle every
frame. The avoids periodic stalls we observe in the ion driver
when mapping a buffer into the HWC address space.
Bug: 66459419
Test: Observe systraces no longer have MapBuffer in HWC in steady
state; system does not drop frames.
Change-Id: Iba4161b33561322bfbccbfafe600b432a6fa7c44
diff --git a/libs/vr/libvrflinger/hardware_composer.cpp b/libs/vr/libvrflinger/hardware_composer.cpp
index de6477b..b3da120 100644
--- a/libs/vr/libvrflinger/hardware_composer.cpp
+++ b/libs/vr/libvrflinger/hardware_composer.cpp
@@ -605,7 +605,7 @@
} else if (pfd[0].revents != 0) {
return 0;
} else if (pfd[1].revents != 0) {
- ALOGI("VrHwcPost thread interrupted");
+ ALOGI("VrHwcPost thread interrupted: revents=%x", pfd[1].revents);
return kPostThreadInterrupted;
} else {
return 0;
@@ -1069,6 +1069,7 @@
acquire_fence_.Close();
surface_rect_functions_applied_ = false;
pending_visibility_settings_ = true;
+ cached_buffer_map_.clear();
}
Layer::Layer(const std::shared_ptr<DirectDisplaySurface>& surface,
@@ -1112,6 +1113,7 @@
swap(surface_rect_functions_applied_,
other.surface_rect_functions_applied_);
swap(pending_visibility_settings_, other.pending_visibility_settings_);
+ swap(cached_buffer_map_, other.cached_buffer_map_);
}
return *this;
}
@@ -1205,15 +1207,30 @@
UpdateLayerSettings();
}
+bool Layer::CheckAndUpdateCachedBuffer(std::size_t slot, int buffer_id) {
+ auto search = cached_buffer_map_.find(slot);
+ if (search != cached_buffer_map_.end() && search->second == buffer_id)
+ return true;
+
+ // Assign or update the buffer slot.
+ if (buffer_id >= 0)
+ cached_buffer_map_[slot] = buffer_id;
+ return false;
+}
+
void Layer::Prepare() {
- int right, bottom;
+ int right, bottom, id;
sp<GraphicBuffer> handle;
+ std::size_t slot;
// Acquire the next buffer according to the type of source.
IfAnyOf<SourceSurface, SourceBuffer>::Call(&source_, [&](auto& source) {
- std::tie(right, bottom, handle, acquire_fence_) = source.Acquire();
+ std::tie(right, bottom, id, handle, acquire_fence_, slot) =
+ source.Acquire();
});
+ TRACE_FORMAT("Layer::Prepare|buffer_id=%d;slot=%zu|", id, slot);
+
// Update any visibility (blending, z-order) changes that occurred since
// last prepare.
UpdateVisibilitySettings();
@@ -1243,10 +1260,15 @@
composition_type_.cast<Hwc2::IComposerClient::Composition>());
}
+ // See if the HWC cache already has this buffer.
+ const bool cached = CheckAndUpdateCachedBuffer(slot, id);
+ if (cached)
+ handle = nullptr;
+
HWC::Error error{HWC::Error::None};
error =
composer_->setLayerBuffer(HWC_DISPLAY_PRIMARY, hardware_composer_layer_,
- 0, handle, acquire_fence_.Get());
+ slot, handle, acquire_fence_.Get());
ALOGE_IF(error != HWC::Error::None,
"Layer::Prepare: Error setting layer buffer: %s",