Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

drm_hwcomposer: Add writeback connector support #92

Open
wants to merge 1 commit into
base: celadon/u/mr0/master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,121 changes: 1,121 additions & 0 deletions 1

Large diffs are not rendered by default.

22 changes: 20 additions & 2 deletions drm/DrmAtomicStateManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,26 @@ auto DrmAtomicStateManager::CommitFrame(AtomicCommitArgs &args) -> int {
}

int out_fence = -1;
if (!crtc->GetOutFencePtrProperty().AtomicSet(*pset, uint64_t(&out_fence))) {
return -EINVAL;
if (!args.writeback_fb) {
if (!crtc->GetOutFencePtrProperty(). //
AtomicSet(*pset, uint64_t(&out_fence))) {
return -EINVAL;
}
} else {
if (!connector->GetWritebackOutFenceProperty(). //
AtomicSet(*pset, uint64_t(&out_fence))) {
return -EINVAL;
}

if (!connector->GetWritebackFbIdProperty(). //
AtomicSet(*pset, args.writeback_fb->GetFbId())) {
return -EINVAL;
}

if (args.writeback_release_fence) {
sync_wait(*args.writeback_release_fence, -1);
args.writeback_release_fence.reset();
}
}

bool nonblock = true;
Expand Down
2 changes: 2 additions & 0 deletions drm/DrmAtomicStateManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ struct AtomicCommitArgs {
std::optional<bool> active;
std::shared_ptr<DrmKmsPlan> composition;
bool color_adjustment = false;
std::shared_ptr<DrmFbIdHandle> writeback_fb;
SharedFd writeback_release_fence;

/* out */
UniqueFd out_fence;
Expand Down
7 changes: 7 additions & 0 deletions drm/DrmConnector.h
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,13 @@ class DrmConnector : public PipelineBindable<DrmConnector> {
return hdr_metadata_;
}

auto &GetWritebackFbIdProperty() const {
return writeback_fb_id_;
}

auto &GetWritebackOutFenceProperty() const {
return writeback_out_fence_;
}

auto IsConnected() const {
return connector_->connection == DRM_MODE_CONNECTED;
Expand Down
5 changes: 5 additions & 0 deletions drm/DrmDevice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,11 @@ auto DrmDevice::GetConnectors()
return connectors_;
}

auto DrmDevice::GetWritebackConnectors()
-> const std::vector<std::unique_ptr<DrmConnector>> & {
return writeback_connectors_;
}

auto DrmDevice::GetPlanes() -> const std::vector<std::unique_ptr<DrmPlane>> & {
return planes_;
}
Expand Down
3 changes: 2 additions & 1 deletion drm/DrmDevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ class DrmDevice {
}

auto GetConnectors() -> const std::vector<std::unique_ptr<DrmConnector>> &;
auto GetWritebackConnectors() -> const std::vector<std::unique_ptr<DrmConnector>> &;
auto GetPlanes() -> const std::vector<std::unique_ptr<DrmPlane>> &;
auto GetCrtcs() -> const std::vector<std::unique_ptr<DrmCrtc>> &;
auto GetEncoders() -> const std::vector<std::unique_ptr<DrmEncoder>> &;
Expand Down Expand Up @@ -121,7 +122,7 @@ class DrmDevice {
bool hdr_device_checked_ = false;

std::vector<std::unique_ptr<DrmConnector>> connectors_;
std::vector<std::unique_ptr<DrmConnector>> writeback_connectors_;
std::vector<std::unique_ptr<DrmConnector>> rriteback_connectors_;
std::vector<std::unique_ptr<DrmEncoder>> encoders_;
std::vector<std::unique_ptr<DrmCrtc>> crtcs_;
std::vector<std::unique_ptr<DrmPlane>> planes_;
Expand Down
26 changes: 26 additions & 0 deletions drm/ResourceManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -293,4 +293,30 @@ auto ResourceManager::GetOrderedConnectors() -> std::vector<DrmConnector *> {

return ordered_connectors;
}

auto ResourceManager::GetVirtualDisplayPipeline()
-> std::shared_ptr<DrmDisplayPipeline> {
for (auto &drm : drms_) {
for (const auto &conn : drm->GetWritebackConnectors()) {
auto pipeline = DrmDisplayPipeline::CreatePipeline(*conn);
if (!pipeline) {
ALOGE("Failed to create pipeline for writeback connector %s",
conn->GetName().c_str());
}
if (pipeline) {
return pipeline;
}
}
}
return {};
}

auto ResourceManager::GetWritebackConnectorsCount() -> uint32_t {
uint32_t count = 0;
for (auto &drm : drms_) {
count += drm->GetWritebackConnectors().size();
}
return count;
}

} // namespace android
2 changes: 2 additions & 0 deletions drm/ResourceManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ class ResourceManager {
return main_lock_;
}

auto GetVirtualDisplayPipeline() -> std::shared_ptr<DrmDisplayPipeline>;
auto GetWritebackConnectorsCount() -> uint32_t;
static auto GetTimeMonotonicNs() -> int64_t;

private:
Expand Down
43 changes: 39 additions & 4 deletions hwc2_device/HwcDisplay.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,9 @@ HwcDisplay::HwcDisplay(hwc2_display_t handle, HWC2::DisplayType type,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0};
// clang-format on
if (type_ == HWC2::DisplayType::Virtual) {
writeback_layer_ = std::make_unique<HwcLayer>(this);
}
}

HwcDisplay::~HwcDisplay() = default;
Expand Down Expand Up @@ -159,6 +162,14 @@ HWC2::Error HwcDisplay::Init() {
return HWC2::Error::BadDisplay;
}

if (type_ != HWC2::DisplayType::Virtual) {
vsync_worker_ = VSyncWorker::CreateInstance(pipeline_, vsw_callbacks);
if (!vsync_worker_) {
ALOGE("Failed to create event worker for d=%d\n", int(handle_));
return HWC2::Error::BadDisplay;
}
}

if (!IsInHeadlessMode()) {
ret = BackendManager::GetInstance().SetBackendForDisplay(this);
if (ret) {
Expand All @@ -174,6 +185,9 @@ HWC2::Error HwcDisplay::Init() {

HWC2::Error HwcDisplay::ChosePreferredConfig() {
HWC2::Error err{};
if (type_ == HWC2::DisplayType::Virtual) {
configs_.GenFakeMode(virtual_disp_width_, virtual_disp_height_);
} else
if (!IsInHeadlessMode()) {
err = configs_.Update(*pipeline_->connector->Get());
} else {
Expand Down Expand Up @@ -585,6 +599,13 @@ HWC2::Error HwcDisplay::CreateComposition(AtomicCommitArgs &a_args) {
*/
current_plan_ = DrmKmsPlan::CreateDrmKmsPlan(GetPipe(),
std::move(composition_layers));

if (type_ == HWC2::DisplayType::Virtual) {
a_args.writeback_fb = writeback_layer_->GetLayerData().fb;
a_args.writeback_release_fence = writeback_layer_->GetLayerData()
.acquire_fence;
}

if (!current_plan_) {
if (!a_args.test_only) {
ALOGE("Failed to create DrmKmsPlan");
Expand Down Expand Up @@ -745,10 +766,16 @@ HWC2::Error HwcDisplay::SetColorTransform(const float *matrix, int32_t hint) {
return HWC2::Error::None;
}

HWC2::Error HwcDisplay::SetOutputBuffer(buffer_handle_t /*buffer*/,
int32_t /*release_fence*/) {
// TODO(nobody): Need virtual display support
return HWC2::Error::Unsupported;
HWC2::Error HwcDisplay::SetOutputBuffer(buffer_handle_t buffer,
int32_t release_fence) {
writeback_layer_->SetLayerBuffer(buffer, release_fence);
writeback_layer_->PopulateLayerData();
if (!writeback_layer_->IsLayerUsableAsDevice()) {
ALOGE("Output layer must be always usable by DRM/KMS");
return HWC2::Error::BadLayer;
}
/* TODO: Check if format is supported by writeback connector */
return HWC2::Error::None;
}

HWC2::Error HwcDisplay::SetPowerMode(int32_t mode_in) {
Expand Down Expand Up @@ -797,6 +824,10 @@ HWC2::Error HwcDisplay::SetPowerMode(int32_t mode_in) {
}

HWC2::Error HwcDisplay::SetVsyncEnabled(int32_t enabled) {
if (type_ == HWC2::DisplayType::Virtual) {
return HWC2::Error::None;
}

vsync_event_en_ = HWC2_VSYNC_ENABLE == enabled;
if (vsync_event_en_) {
vsync_worker_.VSyncControl(true);
Expand Down Expand Up @@ -876,6 +907,10 @@ HWC2::Error HwcDisplay::SetActiveConfigWithConstraints(
hwc2_config_t config,
hwc_vsync_period_change_constraints_t *vsyncPeriodChangeConstraints,
hwc_vsync_period_change_timeline_t *outTimeline) {
if (type_ == HWC2::DisplayType::Virtual) {
return HWC2::Error::None;
}

if (vsyncPeriodChangeConstraints == nullptr || outTimeline == nullptr) {
return HWC2::Error::BadParameter;
}
Expand Down
12 changes: 12 additions & 0 deletions hwc2_device/HwcDisplay.h
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,15 @@ class HwcDisplay {

void Deinit();

auto &GetWritebackLayer() {
return writeback_layer_;
}

void SetVirtualDisplayResolution(uint16_t width, uint16_t height) {
virtual_disp_width_ = width;
virtual_disp_height_ = height;
}

private:
enum ClientFlattenningState : int32_t {
Disabled = -3,
Expand Down Expand Up @@ -227,6 +236,9 @@ class HwcDisplay {

std::map<hwc2_layer_t, HwcLayer> layers_;
HwcLayer client_layer_;
std::unique_ptr<HwcLayer> writeback_layer_;
uint16_t virtual_disp_width_{};
uint16_t virtual_disp_height_{};
int32_t color_mode_{};
std::vector<int32_t> current_color_mode_ = {HAL_COLOR_MODE_NATIVE, HAL_COLOR_MODE_BT2020, HAL_COLOR_MODE_BT2100_PQ, HAL_COLOR_MODE_BT2100_HLG, /*HAL_COLOR_MODE_DISPLAY_BT2020*/};
std::array<float, MATRIX_SIZE> color_transform_matrix_{};
Expand Down