summaryrefslogtreecommitdiffstats
path: root/sdm
diff options
context:
space:
mode:
authorSushil Chauhan <sushilchauhan@codeaurora.org>2018-03-19 14:00:23 -0700
committerGerrit - the friendly Code Review server <code-review@localhost>2018-04-17 15:04:35 -0700
commit80e360ff0940b256737089c8db47836b3a2f83f3 (patch)
tree623c454a0e2b697f055c6822d015c0ebf1eb246f /sdm
parentcfd04f8672774e126b5f8a35bb436ff9740b742c (diff)
downloadandroid_hardware_qcom_sdm710_display-80e360ff0940b256737089c8db47836b3a2f83f3.tar.gz
android_hardware_qcom_sdm710_display-80e360ff0940b256737089c8db47836b3a2f83f3.tar.bz2
android_hardware_qcom_sdm710_display-80e360ff0940b256737089c8db47836b3a2f83f3.zip
sdm: hwc2: Add support for HWC Readback feature
Add support for HWC Readback feature in HWC2 and SDM. CRs-Fixed: 2217822 Change-Id: If2df64dc0bdea7a9ca4c2b0498f1cd3f3dc9de9d
Diffstat (limited to 'sdm')
-rw-r--r--sdm/libs/core/drm/hw_device_drm.cpp12
-rw-r--r--sdm/libs/core/drm/hw_device_drm.h1
-rw-r--r--sdm/libs/core/drm/hw_info_drm.cpp1
-rw-r--r--sdm/libs/core/drm/hw_peripheral_drm.cpp112
-rw-r--r--sdm/libs/core/drm/hw_peripheral_drm.h13
-rw-r--r--sdm/libs/core/drm/hw_virtual_drm.cpp14
-rw-r--r--sdm/libs/core/drm/hw_virtual_drm.h3
-rw-r--r--sdm/libs/hwc2/hwc_color_manager.cpp13
-rw-r--r--sdm/libs/hwc2/hwc_display.h16
-rw-r--r--sdm/libs/hwc2/hwc_display_primary.cpp118
-rw-r--r--sdm/libs/hwc2/hwc_display_primary.h16
-rw-r--r--sdm/libs/hwc2/hwc_session.cpp49
-rw-r--r--sdm/libs/hwc2/hwc_session.h8
13 files changed, 301 insertions, 75 deletions
diff --git a/sdm/libs/core/drm/hw_device_drm.cpp b/sdm/libs/core/drm/hw_device_drm.cpp
index f9c95ce2..81237389 100644
--- a/sdm/libs/core/drm/hw_device_drm.cpp
+++ b/sdm/libs/core/drm/hw_device_drm.cpp
@@ -1577,4 +1577,16 @@ void HWDeviceDRM::SetFullROI() {
drm_atomic_intf_->Perform(DRMOps::CONNECTOR_SET_ROI, token_.conn_id, 1, &conn_rects);
}
+void HWDeviceDRM::DumpConnectorModeInfo() {
+ for (uint32_t i = 0; i < (uint32_t)connector_info_.modes.size(); i++) {
+ DLOGI("Mode[%d] Name:%s vref:%d hdisp:%d hsync_s:%d hsync_e:%d htotal:%d " \
+ "vdisp:%d vsync_s:%d vsync_e:%d vtotal:%d\n", i, connector_info_.modes[i].mode.name,
+ connector_info_.modes[i].mode.vrefresh, connector_info_.modes[i].mode.hdisplay,
+ connector_info_.modes[i].mode.hsync_start, connector_info_.modes[i].mode.hsync_end,
+ connector_info_.modes[i].mode.htotal, connector_info_.modes[i].mode.vdisplay,
+ connector_info_.modes[i].mode.vsync_start, connector_info_.modes[i].mode.vsync_end,
+ connector_info_.modes[i].mode.vtotal);
+ }
+}
+
} // namespace sdm
diff --git a/sdm/libs/core/drm/hw_device_drm.h b/sdm/libs/core/drm/hw_device_drm.h
index d2fa276f..1419d9fd 100644
--- a/sdm/libs/core/drm/hw_device_drm.h
+++ b/sdm/libs/core/drm/hw_device_drm.h
@@ -133,6 +133,7 @@ class HWDeviceDRM : public HWInterface {
void SetTopology(sde_drm::DRMTopology drm_topology, HWTopology *hw_topology);
void SetMultiRectMode(const uint32_t flags, sde_drm::DRMMultiRectMode *target);
void SetFullROI();
+ void DumpConnectorModeInfo();
class Registry {
public:
diff --git a/sdm/libs/core/drm/hw_info_drm.cpp b/sdm/libs/core/drm/hw_info_drm.cpp
index 68ca41d8..13027b3f 100644
--- a/sdm/libs/core/drm/hw_info_drm.cpp
+++ b/sdm/libs/core/drm/hw_info_drm.cpp
@@ -430,6 +430,7 @@ void HWInfoDRM::GetWBInfo(HWResourceInfo *hw_resource) {
hw_resource->supported_formats_map.erase(sub_blk_type);
hw_resource->supported_formats_map.insert(make_pair(sub_blk_type, supported_sdm_formats));
+ hw_resource->has_concurrent_writeback = connector_info.concurrent_writeback;
drm_mgr_intf_->UnregisterDisplay(token);
}
diff --git a/sdm/libs/core/drm/hw_peripheral_drm.cpp b/sdm/libs/core/drm/hw_peripheral_drm.cpp
index 44c22e79..dc2a81d0 100644
--- a/sdm/libs/core/drm/hw_peripheral_drm.cpp
+++ b/sdm/libs/core/drm/hw_peripheral_drm.cpp
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2017, The Linux Foundation. All rights reserved.
+Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
@@ -36,6 +36,8 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using sde_drm::DRMDisplayType;
using sde_drm::DRMOps;
using sde_drm::DRMPowerMode;
+using sde_drm::DRMSecureMode;
+using sde_drm::DRMCWbCaptureMode;
namespace sdm {
@@ -62,6 +64,7 @@ DisplayError HWPeripheralDRM::Init() {
DisplayError HWPeripheralDRM::Validate(HWLayers *hw_layers) {
HWLayersInfo &hw_layer_info = hw_layers->info;
SetDestScalarData(hw_layer_info);
+ SetupConcurrentWriteback(hw_layer_info, true);
return HWDeviceDRM::Validate(hw_layers);
}
@@ -69,8 +72,15 @@ DisplayError HWPeripheralDRM::Validate(HWLayers *hw_layers) {
DisplayError HWPeripheralDRM::Commit(HWLayers *hw_layers) {
HWLayersInfo &hw_layer_info = hw_layers->info;
SetDestScalarData(hw_layer_info);
+ SetupConcurrentWriteback(hw_layer_info, false);
- return HWDeviceDRM::Commit(hw_layers);
+ DisplayError error = HWDeviceDRM::Commit(hw_layers);
+
+ if (cwb_config_.enabled && (error == kErrorNone)) {
+ PostCommitConcurrentWriteback(hw_layer_info);
+ }
+
+ return error;
}
void HWPeripheralDRM::ResetDisplayParams() {
@@ -131,5 +141,103 @@ DisplayError HWPeripheralDRM::Flush() {
return kErrorNone;
}
+void HWPeripheralDRM::SetupConcurrentWriteback(HWLayersInfo &hw_layer_info, bool validate) {
+ bool enable = hw_resource_.has_concurrent_writeback && hw_layer_info.stack->output_buffer;
+ if (!(enable || cwb_config_.enabled)) {
+ return;
+ }
+
+ bool setup_modes = enable && !cwb_config_.enabled && validate;
+ if (setup_modes && (SetupConcurrentWritebackModes() == kErrorNone)) {
+ cwb_config_.enabled = true;
+ }
+
+ if (cwb_config_.enabled) {
+ if (enable) {
+ // Set DRM properties for Concurrent Writeback.
+ ConfigureConcurrentWriteback(hw_layer_info.stack);
+ } else {
+ // Tear down the Concurrent Writeback topology.
+ drm_atomic_intf_->Perform(DRMOps::CONNECTOR_SET_CRTC, cwb_config_.token.conn_id, 0);
+ }
+ }
+}
+
+DisplayError HWPeripheralDRM::SetupConcurrentWritebackModes() {
+ // To setup Concurrent Writeback topology, get the Connector ID of Virtual display
+ if (drm_mgr_intf_->RegisterDisplay(DRMDisplayType::VIRTUAL, &cwb_config_.token)) {
+ DLOGE("RegisterDisplay failed for Concurrent Writeback");
+ return kErrorResources;
+ }
+
+ // Set the modes based on Primary display.
+ std::vector<drmModeModeInfo> modes;
+ for (auto &item : connector_info_.modes) {
+ modes.push_back(item.mode);
+ }
+
+ // Inform the mode list to driver.
+ struct sde_drm_wb_cfg cwb_cfg = {};
+ cwb_cfg.connector_id = cwb_config_.token.conn_id;
+ cwb_cfg.flags = SDE_DRM_WB_CFG_FLAGS_CONNECTED;
+ cwb_cfg.count_modes = UINT32(modes.size());
+ cwb_cfg.modes = (uint64_t)modes.data();
+
+ int ret = -EINVAL;
+#ifdef DRM_IOCTL_SDE_WB_CONFIG
+ ret = drmIoctl(dev_fd_, DRM_IOCTL_SDE_WB_CONFIG, &cwb_cfg);
+#endif
+ if (ret) {
+ drm_mgr_intf_->UnregisterDisplay(cwb_config_.token);
+ DLOGE("Dump CWBConfig: mode_count %d flags %x", cwb_cfg.count_modes, cwb_cfg.flags);
+ DumpConnectorModeInfo();
+ return kErrorHardware;
+ }
+
+ return kErrorNone;
+}
+
+void HWPeripheralDRM::ConfigureConcurrentWriteback(LayerStack *layer_stack) {
+ LayerBuffer *output_buffer = layer_stack->output_buffer;
+ registry_.MapBufferToFbId(output_buffer);
+
+ // Set the topology for Concurrent Writeback: [CRTC_PRIMARY_DISPLAY - CONNECTOR_VIRTUAL_DISPLAY].
+ drm_atomic_intf_->Perform(DRMOps::CONNECTOR_SET_CRTC, cwb_config_.token.conn_id, token_.crtc_id);
+
+ // Set CRTC Capture Mode
+ DRMCWbCaptureMode capture_mode = layer_stack->flags.post_processed_output ?
+ DRMCWbCaptureMode::DSPP_OUT : DRMCWbCaptureMode::MIXER_OUT;
+ drm_atomic_intf_->Perform(DRMOps::CRTC_SET_CAPTURE_MODE, token_.crtc_id, capture_mode);
+
+ // Set Connector Output FB
+ uint32_t fb_id = registry_.GetFbId(output_buffer->planes[0].fd);
+ drm_atomic_intf_->Perform(DRMOps::CONNECTOR_SET_OUTPUT_FB_ID, cwb_config_.token.conn_id, fb_id);
+
+ // Set Connector Secure Mode
+ bool secure = output_buffer->flags.secure;
+ DRMSecureMode mode = secure ? DRMSecureMode::SECURE : DRMSecureMode::NON_SECURE;
+ drm_atomic_intf_->Perform(DRMOps::CONNECTOR_SET_FB_SECURE_MODE, cwb_config_.token.conn_id, mode);
+
+ // Set Connector Output Rect
+ sde_drm::DRMRect dst = {};
+ dst.left = 0;
+ dst.top = 0;
+ dst.right = display_attributes_[current_mode_index_].x_pixels;
+ dst.bottom = display_attributes_[current_mode_index_].y_pixels;
+ drm_atomic_intf_->Perform(DRMOps::CONNECTOR_SET_OUTPUT_RECT, cwb_config_.token.conn_id, dst);
+}
+
+void HWPeripheralDRM::PostCommitConcurrentWriteback(HWLayersInfo &hw_layer_info) {
+ bool enabled = hw_resource_.has_concurrent_writeback && hw_layer_info.stack->output_buffer;
+
+ if (enabled) {
+ // Get Concurrent Writeback fence
+ int *fence = &hw_layer_info.stack->output_buffer->release_fence_fd;
+ drm_atomic_intf_->Perform(DRMOps::CONNECTOR_GET_RETIRE_FENCE, cwb_config_.token.conn_id, fence);
+ } else {
+ drm_mgr_intf_->UnregisterDisplay(cwb_config_.token);
+ cwb_config_.enabled = false;
+ }
+}
} // namespace sdm
diff --git a/sdm/libs/core/drm/hw_peripheral_drm.h b/sdm/libs/core/drm/hw_peripheral_drm.h
index e4b33cf3..e4ecae7a 100644
--- a/sdm/libs/core/drm/hw_peripheral_drm.h
+++ b/sdm/libs/core/drm/hw_peripheral_drm.h
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2017, The Linux Foundation. All rights reserved.
+Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
@@ -35,6 +35,11 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace sdm {
+struct CWBConfig {
+ bool enabled = false;
+ sde_drm::DRMDisplayToken token = {};
+};
+
class HWPeripheralDRM : public HWDeviceDRM {
public:
explicit HWPeripheralDRM(BufferSyncHandler *buffer_sync_handler,
@@ -50,8 +55,14 @@ class HWPeripheralDRM : public HWDeviceDRM {
private:
void SetDestScalarData(HWLayersInfo hw_layer_info);
void ResetDisplayParams();
+ DisplayError SetupConcurrentWritebackModes();
+ void SetupConcurrentWriteback(HWLayersInfo &hw_layer_info, bool validate);
+ void ConfigureConcurrentWriteback(LayerStack *stack);
+ void PostCommitConcurrentWriteback(HWLayersInfo &hw_layer_info);
+
sde_drm_dest_scaler_data sde_dest_scalar_data_ = {};
std::vector<SDEScaler> scalar_data_ = {};
+ CWBConfig cwb_config_ = {};
};
} // namespace sdm
diff --git a/sdm/libs/core/drm/hw_virtual_drm.cpp b/sdm/libs/core/drm/hw_virtual_drm.cpp
index 6f7b12b3..29367fee 100644
--- a/sdm/libs/core/drm/hw_virtual_drm.cpp
+++ b/sdm/libs/core/drm/hw_virtual_drm.cpp
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2017, The Linux Foundation. All rights reserved.
+Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
@@ -121,18 +121,6 @@ DisplayError HWVirtualDRM::SetWbConfigs(const HWDisplayAttributes &display_attri
return kErrorNone;
}
-void HWVirtualDRM::DumpConnectorModeInfo() {
- for (uint32_t i = 0; i < (uint32_t)connector_info_.modes.size(); i++) {
- DLOGI("Mode[%d] Name:%s vref:%d hdisp:%d hsync_s:%d hsync_e:%d htotal:%d " \
- "vdisp:%d vsync_s:%d vsync_e:%d vtotal:%d\n", i, connector_info_.modes[i].mode.name,
- connector_info_.modes[i].mode.vrefresh, connector_info_.modes[i].mode.hdisplay,
- connector_info_.modes[i].mode.hsync_start, connector_info_.modes[i].mode.hsync_end,
- connector_info_.modes[i].mode.htotal, connector_info_.modes[i].mode.vdisplay,
- connector_info_.modes[i].mode.vsync_start, connector_info_.modes[i].mode.vsync_end,
- connector_info_.modes[i].mode.vtotal);
- }
-}
-
DisplayError HWVirtualDRM::Commit(HWLayers *hw_layers) {
LayerBuffer *output_buffer = hw_layers->info.stack->output_buffer;
DisplayError err = kErrorNone;
diff --git a/sdm/libs/core/drm/hw_virtual_drm.h b/sdm/libs/core/drm/hw_virtual_drm.h
index 257e08a8..d89737e3 100644
--- a/sdm/libs/core/drm/hw_virtual_drm.h
+++ b/sdm/libs/core/drm/hw_virtual_drm.h
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2017, The Linux Foundation. All rights reserved.
+Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
@@ -58,7 +58,6 @@ class HWVirtualDRM : public HWDeviceDRM {
void ConfigureWbConnectorDestRect();
void ConfigureWbConnectorSecureMode(bool secure);
void InitializeConfigs();
- void DumpConnectorModeInfo();
DisplayError SetWbConfigs(const HWDisplayAttributes &display_attributes);
void GetModeIndex(const HWDisplayAttributes &display_attributes, int *mode_index);
};
diff --git a/sdm/libs/hwc2/hwc_color_manager.cpp b/sdm/libs/hwc2/hwc_color_manager.cpp
index 8023b6a8..1b4e15ad 100644
--- a/sdm/libs/hwc2/hwc_color_manager.cpp
+++ b/sdm/libs/hwc2/hwc_color_manager.cpp
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2015 - 2017, The Linux Foundation. All rights reserved.
+* Copyright (c) 2015 - 2018, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -30,6 +30,7 @@
#include <dlfcn.h>
#include <cutils/sockets.h>
#include <cutils/native_handle.h>
+#include <sync/sync.h>
#include <utils/String16.h>
#include <binder/Parcel.h>
#include <gralloc_priv.h>
@@ -259,7 +260,13 @@ int HWCColorManager::SetFrameCapture(void *params, bool enable, HWCDisplay *hwc_
}
}
} else {
- ret = hwc_display->GetFrameCaptureStatus();
+ ret = -EAGAIN;
+ int fence_fd = -1;
+ if (hwc_display->GetFrameCaptureFence(&fence_fd) && (fence_fd >= 0)) {
+ ret = sync_wait(fence_fd, 1000);
+ ::close(fence_fd);
+ }
+
if (!ret) {
if (frame_capture_data->buffer != NULL) {
if (munmap(frame_capture_data->buffer, buffer_info.alloc_buffer_info.size) != 0) {
@@ -274,7 +281,7 @@ int HWCColorManager::SetFrameCapture(void *params, bool enable, HWCDisplay *hwc_
}
}
} else {
- DLOGE("GetFrameCaptureStatus failed. ret = %d", ret);
+ DLOGE("GetFrameCaptureFence failed. ret = %d", ret);
}
}
return ret;
diff --git a/sdm/libs/hwc2/hwc_display.h b/sdm/libs/hwc2/hwc_display.h
index f54572a0..d2620efb 100644
--- a/sdm/libs/hwc2/hwc_display.h
+++ b/sdm/libs/hwc2/hwc_display.h
@@ -137,15 +137,21 @@ class HWCDisplay : public DisplayEventHandler {
virtual int FrameCaptureAsync(const BufferInfo &output_buffer_info, bool post_processed) {
return -1;
}
- // Returns the status of frame capture operation requested with FrameCaptureAsync().
- // -EAGAIN : No status obtain yet, call API again after another frame.
- // < 0 : Operation happened but failed.
- // 0 : Success.
- virtual int GetFrameCaptureStatus() { return -EAGAIN; }
+ // Client gets release fence of the frame capture, requested with FrameCaptureAsync().
+ // True : Frame capture configured and client gets release fence.
+ // False: Frame capture is not valid and has not been configured.
+ virtual bool GetFrameCaptureFence(int32_t *release_fence) { return false; }
virtual DisplayError SetDetailEnhancerConfig(const DisplayDetailEnhancerData &de_data) {
return kErrorNotSupported;
}
+ virtual HWC2::Error SetReadbackBuffer(const native_handle_t *buffer, int32_t acquire_fence,
+ bool post_processed_output) {
+ return HWC2::Error::Unsupported;
+ }
+ virtual HWC2::Error GetReadbackBufferFence(int32_t *release_fence) {
+ return HWC2::Error::Unsupported;
+ }
// Display Configurations
virtual int SetActiveDisplayConfig(uint32_t config);
diff --git a/sdm/libs/hwc2/hwc_display_primary.cpp b/sdm/libs/hwc2/hwc_display_primary.cpp
index 75ac0f98..50e3cf3a 100644
--- a/sdm/libs/hwc2/hwc_display_primary.cpp
+++ b/sdm/libs/hwc2/hwc_display_primary.cpp
@@ -31,6 +31,7 @@
#include <sync/sync.h>
#include <utils/constants.h>
#include <utils/debug.h>
+#include <utils/utils.h>
#include <stdarg.h>
#include <sys/mman.h>
@@ -191,11 +192,15 @@ HWC2::Error HWCDisplayPrimary::Validate(uint32_t *out_num_types, uint32_t *out_n
bool pending_output_dump = dump_frame_count_ && dump_output_to_file_;
- if (frame_capture_buffer_queued_ || pending_output_dump) {
+ if (readback_buffer_queued_ || pending_output_dump) {
+ CloseFd(&output_buffer_.release_fence_fd);
// RHS values were set in FrameCaptureAsync() called from a binder thread. They are picked up
- // here in a subsequent draw round.
- layer_stack_.output_buffer = &output_buffer_;
- layer_stack_.flags.post_processed_output = post_processed_output_;
+ // here in a subsequent draw round. Readback is not allowed for any secure use case.
+ readback_configured_ = !layer_stack_.flags.secure_present;
+ if (readback_configured_) {
+ layer_stack_.output_buffer = &output_buffer_;
+ layer_stack_.flags.post_processed_output = post_processed_output_;
+ }
}
uint32_t num_updating_layers = GetUpdatingLayersCount();
@@ -245,6 +250,8 @@ HWC2::Error HWCDisplayPrimary::Present(int32_t *out_retire_fence) {
status = HWCDisplay::PostCommitLayerStack(out_retire_fence);
}
}
+
+ CloseFd(&output_buffer_.acquire_fence_fd);
pending_commit_ = false;
return status;
}
@@ -318,6 +325,52 @@ HWC2::Error HWCDisplayPrimary::SetColorTransform(const float *matrix,
return status;
}
+HWC2::Error HWCDisplayPrimary::SetReadbackBuffer(const native_handle_t *buffer,
+ int32_t acquire_fence,
+ bool post_processed_output) {
+ const private_handle_t *handle = (private_handle_t *)buffer;
+ if (!handle || (handle->fd < 0)) {
+ return HWC2::Error::BadParameter;
+ }
+
+ // Configure the output buffer as Readback buffer
+ output_buffer_.width = UINT32(handle->width);
+ output_buffer_.height = UINT32(handle->height);
+ output_buffer_.unaligned_width = UINT32(handle->unaligned_width);
+ output_buffer_.unaligned_height = UINT32(handle->unaligned_height);
+ output_buffer_.format = GetSDMFormat(handle->format, handle->flags);
+ output_buffer_.planes[0].fd = handle->fd;
+ output_buffer_.planes[0].stride = UINT32(handle->width);
+ output_buffer_.acquire_fence_fd = dup(acquire_fence);
+ output_buffer_.release_fence_fd = -1;
+
+ post_processed_output_ = post_processed_output;
+ readback_buffer_queued_ = true;
+ readback_configured_ = false;
+ validated_ = false;
+
+ DisablePartialUpdateOneFrame();
+ return HWC2::Error::None;
+}
+
+HWC2::Error HWCDisplayPrimary::GetReadbackBufferFence(int32_t *release_fence) {
+ auto status = HWC2::Error::None;
+
+ if (readback_configured_ && (output_buffer_.release_fence_fd >= 0)) {
+ *release_fence = output_buffer_.release_fence_fd;
+ } else {
+ status = HWC2::Error::Unsupported;
+ *release_fence = -1;
+ }
+
+ post_processed_output_ = false;
+ readback_buffer_queued_ = false;
+ readback_configured_ = false;
+ output_buffer_ = {};
+
+ return status;
+}
+
int HWCDisplayPrimary::Perform(uint32_t operation, ...) {
va_list args;
va_start(args, operation);
@@ -449,40 +502,21 @@ void HWCDisplayPrimary::SetIdleTimeoutMs(uint32_t timeout_ms) {
validated_ = false;
}
-static void SetLayerBuffer(const BufferInfo &output_buffer_info, LayerBuffer *output_buffer) {
- const BufferConfig& buffer_config = output_buffer_info.buffer_config;
- const AllocatedBufferInfo &alloc_buffer_info = output_buffer_info.alloc_buffer_info;
-
- output_buffer->width = alloc_buffer_info.aligned_width;
- output_buffer->height = alloc_buffer_info.aligned_height;
- output_buffer->unaligned_width = buffer_config.width;
- output_buffer->unaligned_height = buffer_config.height;
- output_buffer->format = buffer_config.format;
- output_buffer->planes[0].fd = alloc_buffer_info.fd;
- output_buffer->planes[0].stride = alloc_buffer_info.stride;
-}
-
void HWCDisplayPrimary::HandleFrameOutput() {
- if (frame_capture_buffer_queued_) {
- HandleFrameCapture();
- } else if (dump_output_to_file_) {
- HandleFrameDump();
+ if (readback_buffer_queued_) {
+ validated_ = false;
}
-}
-void HWCDisplayPrimary::HandleFrameCapture() {
- if (output_buffer_.release_fence_fd >= 0) {
- frame_capture_status_ = sync_wait(output_buffer_.release_fence_fd, 1000);
- ::close(output_buffer_.release_fence_fd);
- output_buffer_.release_fence_fd = -1;
+ if (dump_output_to_file_) {
+ HandleFrameDump();
}
-
- frame_capture_buffer_queued_ = false;
- post_processed_output_ = false;
- output_buffer_ = {};
}
void HWCDisplayPrimary::HandleFrameDump() {
+ if (!readback_configured_) {
+ dump_frame_count_ = 0;
+ }
+
if (dump_frame_count_ && output_buffer_.release_fence_fd >= 0) {
int ret = sync_wait(output_buffer_.release_fence_fd, 1000);
::close(output_buffer_.release_fence_fd);
@@ -491,6 +525,7 @@ void HWCDisplayPrimary::HandleFrameDump() {
DLOGE("sync_wait error errno = %d, desc = %s", errno, strerror(errno));
} else {
DumpOutputBuffer(output_buffer_info_, output_buffer_base_, layer_stack_.retire_fence_fd);
+ readback_buffer_queued_ = false;
}
}
@@ -504,7 +539,10 @@ void HWCDisplayPrimary::HandleFrameDump() {
DLOGE("FreeBuffer failed");
}
+ readback_buffer_queued_ = false;
post_processed_output_ = false;
+ readback_configured_ = false;
+
output_buffer_ = {};
output_buffer_info_ = {};
output_buffer_base_ = nullptr;
@@ -544,9 +582,9 @@ HWC2::Error HWCDisplayPrimary::SetFrameDumpConfig(uint32_t count, uint32_t bit_m
}
output_buffer_base_ = buffer;
- post_processed_output_ = true;
- DisablePartialUpdateOneFrame();
- validated_ = false;
+ const native_handle_t *handle = static_cast<native_handle_t *>(output_buffer_info_.private_data);
+ SetReadbackBuffer(handle, -1, true);
+
return HWC2::Error::None;
}
@@ -576,16 +614,16 @@ int HWCDisplayPrimary::FrameCaptureAsync(const BufferInfo &output_buffer_info,
return -1;
}
- SetLayerBuffer(output_buffer_info, &output_buffer_);
- post_processed_output_ = post_processed_output;
- frame_capture_buffer_queued_ = true;
- // Status is only cleared on a new call to dump and remains valid otherwise
- frame_capture_status_ = -EAGAIN;
- DisablePartialUpdateOneFrame();
+ const native_handle_t *buffer = static_cast<native_handle_t *>(output_buffer_info.private_data);
+ SetReadbackBuffer(buffer, -1, post_processed_output);
return 0;
}
+bool HWCDisplayPrimary::GetFrameCaptureFence(int32_t *release_fence) {
+ return (GetReadbackBufferFence(release_fence) == HWC2::Error::None);
+}
+
DisplayError HWCDisplayPrimary::SetDetailEnhancerConfig
(const DisplayDetailEnhancerData &de_data) {
DisplayError error = kErrorNotSupported;
diff --git a/sdm/libs/hwc2/hwc_display_primary.h b/sdm/libs/hwc2/hwc_display_primary.h
index c1e23ed0..98dcde35 100644
--- a/sdm/libs/hwc2/hwc_display_primary.h
+++ b/sdm/libs/hwc2/hwc_display_primary.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -66,9 +66,12 @@ class HWCDisplayPrimary : public HWCDisplay {
virtual void SetIdleTimeoutMs(uint32_t timeout_ms);
virtual HWC2::Error SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_layer_type);
virtual int FrameCaptureAsync(const BufferInfo &output_buffer_info, bool post_processed);
- virtual int GetFrameCaptureStatus() { return frame_capture_status_; }
+ virtual bool GetFrameCaptureFence(int32_t *release_fence);
virtual DisplayError SetDetailEnhancerConfig(const DisplayDetailEnhancerData &de_data);
virtual DisplayError ControlPartialUpdate(bool enable, uint32_t *pending);
+ virtual HWC2::Error SetReadbackBuffer(const native_handle_t *buffer, int32_t acquire_fence,
+ bool post_processed_output);
+ virtual HWC2::Error GetReadbackBufferFence(int32_t *release_fence);
private:
HWCDisplayPrimary(CoreInterface *core_intf, BufferAllocator *buffer_allocator,
@@ -82,7 +85,6 @@ class HWCDisplayPrimary : public HWCDisplay {
void ForceRefreshRate(uint32_t refresh_rate);
uint32_t GetOptimalRefreshRate(bool one_updating_layer);
void HandleFrameOutput();
- void HandleFrameCapture();
void HandleFrameDump();
DisplayError SetMixerResolution(uint32_t width, uint32_t height);
DisplayError GetMixerResolution(uint32_t *width, uint32_t *height);
@@ -90,13 +92,11 @@ class HWCDisplayPrimary : public HWCDisplay {
BufferAllocator *buffer_allocator_ = nullptr;
CPUHint *cpu_hint_ = nullptr;
- // Primary output buffer configuration
+ // Primary readback buffer configuration
LayerBuffer output_buffer_ = {};
bool post_processed_output_ = false;
-
- // Members for 1 frame capture in a client provided buffer
- bool frame_capture_buffer_queued_ = false;
- int frame_capture_status_ = -EAGAIN;
+ bool readback_buffer_queued_ = false;
+ bool readback_configured_ = false;
// Members for N frame output dump to file
bool dump_output_to_file_ = false;
diff --git a/sdm/libs/hwc2/hwc_session.cpp b/sdm/libs/hwc2/hwc_session.cpp
index 11bb60fc..473f9d50 100644
--- a/sdm/libs/hwc2/hwc_session.cpp
+++ b/sdm/libs/hwc2/hwc_session.cpp
@@ -871,6 +871,12 @@ hwc2_function_pointer_t HWCSession::GetFunction(struct hwc2_device *device,
return AsFP<HWC2_PFN_SET_VSYNC_ENABLED>(SetVsyncEnabled);
case HWC2::FunctionDescriptor::ValidateDisplay:
return AsFP<HWC2_PFN_VALIDATE_DISPLAY>(HWCSession::ValidateDisplay);
+ case HWC2::FunctionDescriptor::SetReadbackBuffer:
+ return AsFP<HWC2_PFN_SET_READBACK_BUFFER>(HWCSession::SetReadbackBuffer);
+ case HWC2::FunctionDescriptor::GetReadbackBufferAttributes:
+ return AsFP<HWC2_PFN_GET_READBACK_BUFFER_ATTRIBUTES>(HWCSession::GetReadbackBufferAttributes);
+ case HWC2::FunctionDescriptor::GetReadbackBufferFence:
+ return AsFP<HWC2_PFN_GET_READBACK_BUFFER_FENCE>(HWCSession::GetReadbackBufferFence);
default:
DLOGD("Unknown/Unimplemented function descriptor: %d (%s)", int_descriptor,
to_string(descriptor).c_str());
@@ -1905,4 +1911,47 @@ HWC2::Error HWCSession::PresentDisplayInternal(hwc2_display_t display, int32_t *
return hwc_display->Present(out_retire_fence);
}
+int32_t HWCSession::GetReadbackBufferAttributes(hwc2_device_t *device, hwc2_display_t display,
+ int32_t *format, int32_t *dataspace) {
+ if (!device || !format || !dataspace) {
+ return HWC2_ERROR_BAD_PARAMETER;
+ }
+
+ if (display != HWC_DISPLAY_PRIMARY) {
+ return HWC2_ERROR_BAD_DISPLAY;
+ }
+
+ *format = HAL_PIXEL_FORMAT_RGB_888;
+ *dataspace = HAL_DATASPACE_V0_SRGB; // ((STANDARD_BT709 | TRANSFER_SRGB) | RANGE_FULL)
+
+ return HWC2_ERROR_NONE;
+}
+
+int32_t HWCSession::SetReadbackBuffer(hwc2_device_t *device, hwc2_display_t display,
+ const native_handle_t *buffer, int32_t acquire_fence) {
+ if (!buffer) {
+ return HWC2_ERROR_BAD_PARAMETER;
+ }
+
+ if (display != HWC_DISPLAY_PRIMARY) {
+ return HWC2_ERROR_BAD_DISPLAY;
+ }
+
+ return CallDisplayFunction(device, display, &HWCDisplay::SetReadbackBuffer,
+ buffer, acquire_fence, false);
+}
+
+int32_t HWCSession::GetReadbackBufferFence(hwc2_device_t *device, hwc2_display_t display,
+ int32_t *release_fence) {
+ if (!release_fence) {
+ return HWC2_ERROR_BAD_PARAMETER;
+ }
+
+ if (display != HWC_DISPLAY_PRIMARY) {
+ return HWC2_ERROR_BAD_DISPLAY;
+ }
+
+ return CallDisplayFunction(device, display, &HWCDisplay::GetReadbackBufferFence, release_fence);
+}
+
} // namespace sdm
diff --git a/sdm/libs/hwc2/hwc_session.h b/sdm/libs/hwc2/hwc_session.h
index f09bff14..c21cba95 100644
--- a/sdm/libs/hwc2/hwc_session.h
+++ b/sdm/libs/hwc2/hwc_session.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
* Not a Contribution.
*
* Copyright 2015 The Android Open Source Project
@@ -156,6 +156,12 @@ class HWCSession : hwc2_device_t, HWCUEventListener, IDisplayConfig, public qCli
int32_t /*android_color_mode_t*/ int_mode);
static int32_t SetColorTransform(hwc2_device_t *device, hwc2_display_t display,
const float *matrix, int32_t /*android_color_transform_t*/ hint);
+ static int32_t GetReadbackBufferAttributes(hwc2_device_t *device, hwc2_display_t display,
+ int32_t *format, int32_t *dataspace);
+ static int32_t SetReadbackBuffer(hwc2_device_t *device, hwc2_display_t display,
+ const native_handle_t *buffer, int32_t acquire_fence);
+ static int32_t GetReadbackBufferFence(hwc2_device_t *device, hwc2_display_t display,
+ int32_t *release_fence);
static Locker locker_[HWC_NUM_DISPLAY_TYPES];