drm_hwcomposer: Rework HWC frontends buffer management
Change summary:
- Use BufferInfo instead of native_buffer to configure the HwcLayer.
- Extend buffer properties with slot info.
- Provide fence and active slot ID separate from the buffer.
- Move swapchain tracking into HWC2. HWC3 doesn't need that.
Why:
- Support more flexible resource management control from the frontend
side, which is required by HWC3 API.
- Move more Android-specific data types to the frontend module.
Change-Id: Idaa4c552f600f78d6f0ad21997cfa7f3a6c6cbd8
Signed-off-by: Roman Stratiienko <r.stratiienko@gmail.com>
diff --git a/hwc3/ComposerClient.cpp b/hwc3/ComposerClient.cpp
index 52c0e4a..c58e6e4 100644
--- a/hwc3/ComposerClient.cpp
+++ b/hwc3/ComposerClient.cpp
@@ -40,6 +40,7 @@
#include <cutils/native_handle.h>
#include <hardware/hwcomposer2.h>
#include <hardware/hwcomposer_defs.h>
+#include <ui/GraphicBufferMapper.h>
#include "bufferinfo/BufferInfo.h"
#include "compositor/DisplayInfo.h"
@@ -351,6 +352,92 @@
} // namespace
+class Hwc3BufferHandle : public PrimeFdsSharedBase {
+ public:
+ static auto Create(buffer_handle_t handle)
+ -> std::shared_ptr<Hwc3BufferHandle> {
+ auto hwc3 = std::shared_ptr<Hwc3BufferHandle>(new Hwc3BufferHandle());
+
+ ::android::GraphicBufferMapper::get()
+ .importBufferNoValidate(handle, &hwc3->imported_handle_);
+
+ return hwc3;
+ }
+
+ auto GetHandle() const -> buffer_handle_t {
+ return imported_handle_;
+ }
+
+ ~Hwc3BufferHandle() override {
+ ::android::GraphicBufferMapper::get().freeBuffer(imported_handle_);
+ }
+
+ private:
+ Hwc3BufferHandle() = default;
+ buffer_handle_t imported_handle_{};
+};
+
+class Hwc3Layer : public ::android::FrontendLayerBase {
+ public:
+ auto HandleNextBuffer(std::optional<buffer_handle_t> raw_handle,
+ ::android::SharedFd fence_fd, int32_t slot_id)
+ -> std::optional<HwcLayer::LayerProperties> {
+ HwcLayer::LayerProperties lp;
+ if (!raw_handle && slots_.count(slot_id) != 0) {
+ lp.active_slot = {
+ .slot_id = slot_id,
+ .fence = std::move(fence_fd),
+ };
+
+ return lp;
+ }
+
+ if (!raw_handle) {
+ ALOGE("Buffer handle is nullopt but slot was not cached.");
+ return std::nullopt;
+ }
+
+ auto hwc3 = Hwc3BufferHandle::Create(*raw_handle);
+ if (!hwc3) {
+ return std::nullopt;
+ }
+
+ auto bi = ::android::BufferInfoGetter::GetInstance()->GetBoInfo(
+ hwc3->GetHandle());
+ if (!bi) {
+ return std::nullopt;
+ }
+
+ bi->fds_shared = hwc3;
+
+ lp.slot_buffer = {
+ .slot_id = slot_id,
+ .bi = bi,
+ };
+
+ lp.active_slot = {
+ .slot_id = slot_id,
+ .fence = std::move(fence_fd),
+ };
+
+ slots_[slot_id] = hwc3;
+
+ return lp;
+ }
+
+ private:
+ std::map<int32_t /*slot*/, std::shared_ptr<Hwc3BufferHandle>> slots_;
+};
+
+static auto GetHwc3Layer(HwcLayer& layer) -> std::shared_ptr<Hwc3Layer> {
+ auto frontend_private_data = layer.GetFrontendPrivateData();
+ if (!frontend_private_data) {
+ frontend_private_data = std::make_shared<Hwc3Layer>();
+ layer.SetFrontendPrivateData(frontend_private_data);
+ }
+ return std::static_pointer_cast<Hwc3Layer>(frontend_private_data);
+}
+
ComposerClient::ComposerClient() {
DEBUG_FUNC();
}
@@ -491,14 +578,26 @@
HwcLayer::LayerProperties properties;
if (command.buffer) {
- HwcLayer::Buffer buffer;
- auto err = ImportLayerBuffer(display_id, command.layer, *command.buffer,
- &buffer);
- if (err != hwc3::Error::kNone) {
- cmd_result_writer_->AddError(err);
+ auto hwc3_layer = GetHwc3Layer(*layer);
+ std::optional<buffer_handle_t> buffer_handle = std::nullopt;
+ if (command.buffer->handle) {
+ buffer_handle = ::android::makeFromAidl(*command.buffer->handle);
+ }
+
+ // NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast)
+ auto fence = const_cast<::ndk::ScopedFileDescriptor&>(command.buffer->fence)
+ .release();
+
+ auto lp = hwc3_layer->HandleNextBuffer(buffer_handle,
+ ::android::MakeSharedFd(fence),
+ command.buffer->slot);
+
+ if (!lp) {
+ cmd_result_writer_->AddError(hwc3::Error::kBadLayer);
return;
}
- properties.buffer.emplace(buffer);
+
+ properties = lp.value();
}
properties.blend_mode = AidlToBlendMode(command.blendMode);
@@ -1297,7 +1396,8 @@
}
ndk::ScopedAStatus ComposerClient::notifyExpectedPresent(
- int64_t /*display*/, const ClockMonotonicTimestamp& /*expected_present_time*/,
+ int64_t /*display*/,
+ const ClockMonotonicTimestamp& /*expected_present_time*/,
int32_t /*frame_interval_ns*/) {
return ToBinderStatus(hwc3::Error::kUnsupported);
}
@@ -1319,19 +1419,6 @@
return binder;
}
-hwc3::Error ComposerClient::ImportLayerBuffer(int64_t display_id,
- int64_t layer_id,
- const Buffer& buffer,
- HwcLayer::Buffer* out_buffer) {
- auto releaser = ComposerResources::CreateResourceReleaser(true);
- auto err = composer_resources_->GetLayerBuffer(display_id, layer_id, buffer,
- &out_buffer->buffer_handle,
- releaser.get());
- out_buffer->acquire_fence = ::android::MakeSharedFd(
- buffer.fence.dup().release());
- return err;
-}
-
void ComposerClient::ExecuteSetDisplayClientTarget(
uint64_t display_id, const ClientTarget& command) {
auto* display = GetDisplay(display_id);
@@ -1340,31 +1427,35 @@
return;
}
- buffer_handle_t imported_buffer = nullptr;
- auto buf_releaser = ComposerResources::CreateResourceReleaser(true);
+ auto& client_layer = display->GetClientLayer();
+ auto hwc3layer = GetHwc3Layer(client_layer);
- auto error = composer_resources_->GetDisplayClientTarget(display_id,
- command.buffer,
- &imported_buffer,
- buf_releaser.get());
- if (error != hwc3::Error::kNone) {
- cmd_result_writer_->AddError(error);
- return;
+ std::optional<buffer_handle_t> raw_buffer = std::nullopt;
+ if (command.buffer.handle) {
+ raw_buffer = ::android::makeFromAidl(*command.buffer.handle);
}
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast)
auto fence = const_cast<::ndk::ScopedFileDescriptor&>(command.buffer.fence)
.release();
- auto& client_layer = display->GetClientLayer();
- HwcLayer::LayerProperties properties;
- properties.buffer = {
- .buffer_handle = imported_buffer,
- .acquire_fence = ::android::MakeSharedFd(fence),
- };
- properties.color_space = AidlToColorSpace(command.dataspace);
- properties.sample_range = AidlToSampleRange(command.dataspace);
- client_layer.SetLayerProperties(properties);
+ auto properties = hwc3layer->HandleNextBuffer(raw_buffer,
+ ::android::MakeSharedFd(fence),
+ command.buffer.slot);
+
+ if (!properties) {
+ ALOGE("Failed to import client target buffer.");
+ /* Here, sending an error would be the natural way to do the thing.
+ * But VTS checks for no error. Is it the VTS issue?
+ * https://cs.android.com/android/platform/superproject/main/+/main:hardware/interfaces/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_TargetTest.cpp;l=1892;drc=2647200f4c535ca6567b452695b7d13f2aaf3f2a
+ */
+ return;
+ }
+
+ properties->color_space = AidlToColorSpace(command.dataspace);
+ properties->sample_range = AidlToSampleRange(command.dataspace);
+
+ client_layer.SetLayerProperties(properties.value());
}
void ComposerClient::ExecuteSetDisplayOutputBuffer(uint64_t display_id,
@@ -1375,33 +1466,32 @@
return;
}
- buffer_handle_t imported_buffer = nullptr;
- auto buf_releaser = ComposerResources::CreateResourceReleaser(true);
-
- auto error = composer_resources_->GetDisplayOutputBuffer(display_id, buffer,
- &imported_buffer,
- buf_releaser.get());
- if (error != hwc3::Error::kNone) {
- cmd_result_writer_->AddError(error);
- return;
- }
-
- // NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast)
- auto fence = const_cast<::ndk::ScopedFileDescriptor&>(buffer.fence).release();
-
auto& writeback_layer = display->GetWritebackLayer();
if (!writeback_layer) {
cmd_result_writer_->AddError(hwc3::Error::kBadLayer);
return;
}
- HwcLayer::LayerProperties properties;
- properties.buffer = {
- .buffer_handle = imported_buffer,
- .acquire_fence = ::android::MakeSharedFd(fence),
- };
+ auto hwc3layer = GetHwc3Layer(*writeback_layer);
- writeback_layer->SetLayerProperties(properties);
+ std::optional<buffer_handle_t> raw_buffer = std::nullopt;
+ if (buffer.handle) {
+ raw_buffer = ::android::makeFromAidl(*buffer.handle);
+ }
+
+ // NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast)
+ auto fence = const_cast<::ndk::ScopedFileDescriptor&>(buffer.fence).release();
+
+ auto properties = hwc3layer->HandleNextBuffer(raw_buffer,
+ ::android::MakeSharedFd(fence),
+ buffer.slot);
+
+ if (!properties) {
+ cmd_result_writer_->AddError(hwc3::Error::kBadLayer);
+ return;
+ }
+
+ writeback_layer->SetLayerProperties(properties.value());
}
} // namespace aidl::android::hardware::graphics::composer3::impl