hwc2: Enable virtual display
* Create output buffer
* Set DisplayConfig on virtual display from provided width/height
* Handle virtual display fences correctly
* Take lock when creating/destroying virtual displays
Change-Id: I9556f12b69bfea56e18f0e3721a9e03d553468f0
CRs-fixed: 1012677
diff --git a/sdm/libs/hwc2/hwc_display.cpp b/sdm/libs/hwc2/hwc_display.cpp
index f9cb466..e241402 100644
--- a/sdm/libs/hwc2/hwc_display.cpp
+++ b/sdm/libs/hwc2/hwc_display.cpp
@@ -1214,7 +1214,7 @@
int HWCDisplay::SetFrameBufferResolution(uint32_t x_pixels, uint32_t y_pixels) {
if (x_pixels <= 0 || y_pixels <= 0) {
- DLOGV("Unsupported config: x_pixels=%d, y_pixels=%d", x_pixels, y_pixels);
+ DLOGW("Unsupported config: x_pixels=%d, y_pixels=%d", x_pixels, y_pixels);
return -EINVAL;
}
diff --git a/sdm/libs/hwc2/hwc_display.h b/sdm/libs/hwc2/hwc_display.h
index a5ef7eb..69a2dea 100644
--- a/sdm/libs/hwc2/hwc_display.h
+++ b/sdm/libs/hwc2/hwc_display.h
@@ -255,13 +255,13 @@
bool validated_ = false;
bool color_tranform_failed_ = false;
HWCColorMode *color_mode_ = NULL;
+ int32_t stored_retire_fence_ = -1;
private:
void DumpInputBuffers(void);
BlitEngine *blit_engine_ = NULL;
qService::QService *qservice_ = NULL;
DisplayClass display_class_;
- int32_t stored_retire_fence_ = -1;
uint32_t geometry_changes_ = GeometryChanges::kNone;
};
diff --git a/sdm/libs/hwc2/hwc_display_virtual.cpp b/sdm/libs/hwc2/hwc_display_virtual.cpp
index e81781f..89f313a 100644
--- a/sdm/libs/hwc2/hwc_display_virtual.cpp
+++ b/sdm/libs/hwc2/hwc_display_virtual.cpp
@@ -44,27 +44,29 @@
uint32_t height, int32_t *format, HWCDisplay **hwc_display) {
int status = 0;
HWCDisplayVirtual *hwc_display_virtual = new HWCDisplayVirtual(core_intf, callbacks);
- uint32_t virtual_width = 0, virtual_height = 0;
// TODO(user): Populate format correctly
+ DLOGI("Creating virtual display: w: %d h:%d format:0x%x", width, height, *format);
status = hwc_display_virtual->Init();
if (status) {
+ DLOGW("Failed to initialize virtual display");
delete hwc_display_virtual;
return status;
}
status = INT32(hwc_display_virtual->SetPowerMode(HWC2::PowerMode::On));
if (status) {
+ DLOGW("Failed to set power mode on virtual display");
Destroy(hwc_display_virtual);
return status;
}
- hwc_display_virtual->GetMixerResolution(&virtual_width, &virtual_height);
-
+ // TODO(user): Validate that we support this width/height
status = hwc_display_virtual->SetFrameBufferResolution(width, height);
if (status) {
+ DLOGW("Failed to set virtual display FB resolution");
Destroy(hwc_display_virtual);
return status;
}
@@ -85,12 +87,16 @@
}
int HWCDisplayVirtual::Init() {
+ output_buffer_ = new LayerBuffer();
return HWCDisplay::Init();
}
int HWCDisplayVirtual::Deinit() {
int status = 0;
-
+ if (output_buffer_) {
+ delete output_buffer_;
+ output_buffer_ = nullptr;
+ }
status = HWCDisplay::Deinit();
return status;
@@ -105,6 +111,7 @@
}
BuildLayerStack();
+ layer_stack_.output_buffer = output_buffer_;
status = PrepareLayerStack(out_num_types, out_num_requests);
return status;
}
@@ -135,6 +142,13 @@
}
status = HWCDisplay::PostCommitLayerStack(out_retire_fence);
+ // On Virtual displays, use the output buffer release fence as the retire fence
+ // Close the layer stack retire fence as it is unused
+ if (layer_stack_.output_buffer) {
+ stored_retire_fence_ = layer_stack_.output_buffer->release_fence_fd;
+ close(layer_stack_.retire_fence_fd);
+ layer_stack_.retire_fence_fd = -1;
+ }
}
}
CloseAcquireFds();
@@ -142,6 +156,9 @@
}
HWC2::Error HWCDisplayVirtual::SetOutputBuffer(buffer_handle_t buf, int32_t release_fence) {
+ if (buf == nullptr || release_fence == 0) {
+ return HWC2::Error::BadParameter;
+ }
const private_handle_t *output_handle = static_cast<const private_handle_t *>(buf);
// Fill output buffer parameters (width, height, format, plane information, fence)
@@ -182,7 +199,6 @@
output_buffer_->planes[0].stride = UINT32(output_handle->width);
}
- layer_stack_.output_buffer = output_buffer_;
return HWC2::Error::None;
}
diff --git a/sdm/libs/hwc2/hwc_display_virtual.h b/sdm/libs/hwc2/hwc_display_virtual.h
index 0ca2fd1..a68ac65 100644
--- a/sdm/libs/hwc2/hwc_display_virtual.h
+++ b/sdm/libs/hwc2/hwc_display_virtual.h
@@ -38,8 +38,8 @@
class HWCDisplayVirtual : public HWCDisplay {
public:
- static int Create(CoreInterface *core_intf, HWCCallbacks *callbacks, uint32_t primary_width,
- uint32_t primary_height, int32_t *format, HWCDisplay **hwc_display);
+ static int Create(CoreInterface *core_intf, HWCCallbacks *callbacks, uint32_t width,
+ uint32_t height, int32_t *format, HWCDisplay **hwc_display);
static void Destroy(HWCDisplay *hwc_display);
virtual int Init();
virtual int Deinit();
diff --git a/sdm/libs/hwc2/hwc_session.cpp b/sdm/libs/hwc2/hwc_session.cpp
index 7e87b10..f75e6b8 100644
--- a/sdm/libs/hwc2/hwc_session.cpp
+++ b/sdm/libs/hwc2/hwc_session.cpp
@@ -237,6 +237,8 @@
int32_t HWCSession::CreateVirtualDisplay(hwc2_device_t *device, uint32_t width, uint32_t height,
int32_t *format, hwc2_display_t *out_display_id) {
+ // TODO(user): Handle concurrency with HDMI
+ SCOPE_LOCK(locker_);
if (!device) {
return HWC2_ERROR_BAD_DISPLAY;
}
@@ -245,6 +247,7 @@
auto status = hwc_session->CreateVirtualDisplayObject(width, height, format);
if (status == HWC2::Error::None)
*out_display_id = HWC_DISPLAY_VIRTUAL;
+ DLOGI("Created virtual display id:% " PRIu64 " with res: %dx%d", *out_display_id, width, height);
return INT32(status);
}
@@ -255,10 +258,12 @@
}
int32_t HWCSession::DestroyVirtualDisplay(hwc2_device_t *device, hwc2_display_t display) {
+ SCOPE_LOCK(locker_);
if (!device) {
return HWC2_ERROR_BAD_DISPLAY;
}
+ DLOGI("Destroying virtual display id:%" PRIu64, display);
auto *hwc_session = static_cast<HWCSession *>(device);
if (hwc_session->hwc_display_[display]) {