diff options
Diffstat (limited to 'sdm')
-rw-r--r-- | sdm/libs/core/drm/hw_device_drm.cpp | 12 | ||||
-rw-r--r-- | sdm/libs/core/drm/hw_device_drm.h | 1 | ||||
-rw-r--r-- | sdm/libs/core/drm/hw_info_drm.cpp | 1 | ||||
-rw-r--r-- | sdm/libs/core/drm/hw_peripheral_drm.cpp | 112 | ||||
-rw-r--r-- | sdm/libs/core/drm/hw_peripheral_drm.h | 13 | ||||
-rw-r--r-- | sdm/libs/core/drm/hw_virtual_drm.cpp | 14 | ||||
-rw-r--r-- | sdm/libs/core/drm/hw_virtual_drm.h | 3 | ||||
-rw-r--r-- | sdm/libs/hwc2/hwc_color_manager.cpp | 13 | ||||
-rw-r--r-- | sdm/libs/hwc2/hwc_display.h | 16 | ||||
-rw-r--r-- | sdm/libs/hwc2/hwc_display_primary.cpp | 118 | ||||
-rw-r--r-- | sdm/libs/hwc2/hwc_display_primary.h | 16 | ||||
-rw-r--r-- | sdm/libs/hwc2/hwc_session.cpp | 49 | ||||
-rw-r--r-- | sdm/libs/hwc2/hwc_session.h | 8 |
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]; |