Merge "sdm:hwc2: Correct frame capture buffer stride value"
diff --git a/libdrmutils/drm_interface.h b/libdrmutils/drm_interface.h
index 35285ee..5dc5e4b 100644
--- a/libdrmutils/drm_interface.h
+++ b/libdrmutils/drm_interface.h
@@ -318,6 +318,13 @@
V3,
};
+/* QSEED3 Step version */
+enum struct QSEEDStepVersion {
+ V2,
+ V3,
+ V4,
+};
+
enum struct SmartDMARevision {
V1,
V2,
@@ -372,6 +379,7 @@
uint32_t max_vertical_deci;
uint64_t max_pipe_bandwidth;
uint32_t cache_size; // cache size in bytes for inline rotation support.
+ QSEEDStepVersion qseed3_version;
};
// All DRM Planes as map<Plane_id , plane_type_info> listed from highest to lowest priority
@@ -422,6 +430,7 @@
bool roi_merge;
DRMRotation panel_orientation;
drm_panel_hdr_properties panel_hdr_prop;
+ uint32_t transfer_time_us;
};
/* Identifier token for a display */
diff --git a/libgralloc1/gr_adreno_info.cpp b/libgralloc1/gr_adreno_info.cpp
index ecac238..f71f1d2 100644
--- a/libgralloc1/gr_adreno_info.cpp
+++ b/libgralloc1/gr_adreno_info.cpp
@@ -48,16 +48,12 @@
lock_guard<mutex> obj(s_lock);
if (!s_instance) {
s_instance = new AdrenoMemInfo();
- if (!s_instance->Init()) {
- delete s_instance;
- s_instance = nullptr;
- }
}
return s_instance;
}
-bool AdrenoMemInfo::Init() {
+AdrenoMemInfo::AdrenoMemInfo() {
libadreno_utils_ = ::dlopen("libadreno_utils.so", RTLD_NOW);
if (libadreno_utils_) {
*reinterpret_cast<void **>(&LINK_adreno_compute_aligned_width_and_height) =
@@ -74,7 +70,6 @@
::dlsym(libadreno_utils_, "get_gpu_pixel_alignment");
} else {
ALOGE(" Failed to load libadreno_utils.so");
- return false;
}
// Check if the overriding property debug.gralloc.gfx_ubwc_disable
@@ -91,8 +86,6 @@
(!strncasecmp(property, "true", PROPERTY_VALUE_MAX)))) {
map_fb_ = true;
}
-
- return true;
}
AdrenoMemInfo::~AdrenoMemInfo() {
@@ -170,6 +163,8 @@
width, height, format, 0, raster_mode, padding_threshold,
reinterpret_cast<int *>(aligned_w), reinterpret_cast<int *>(aligned_h), &bytesPerPixel);
} else {
+ *aligned_w = (unsigned int)ALIGN(width, 32);
+ *aligned_h = (unsigned int)ALIGN(height, 32);
ALOGW("%s: Warning!! compute_compressedfmt_aligned_width_and_height not found", __FUNCTION__);
}
}
diff --git a/libgralloc1/gr_adreno_info.h b/libgralloc1/gr_adreno_info.h
index 75ba507..b19256a 100644
--- a/libgralloc1/gr_adreno_info.h
+++ b/libgralloc1/gr_adreno_info.h
@@ -71,8 +71,6 @@
class AdrenoMemInfo {
public:
- bool Init();
-
/*
* Function to compute aligned width and aligned height based on
* width, height, format and usage flags.
@@ -123,6 +121,7 @@
static AdrenoMemInfo *GetInstance();
private:
+ AdrenoMemInfo();
~AdrenoMemInfo();
// link(s)to adreno surface padding library.
int (*LINK_adreno_compute_padding)(int width, int bpp, int surface_tile_height,
diff --git a/libgralloc1/gr_utils.cpp b/libgralloc1/gr_utils.cpp
index b3056e1..560bb08 100644
--- a/libgralloc1/gr_utils.cpp
+++ b/libgralloc1/gr_utils.cpp
@@ -509,7 +509,9 @@
// Query GPU for UBWC only if buffer is intended to be used by GPU.
if ((cons_usage & GRALLOC1_CONSUMER_USAGE_GPU_TEXTURE) ||
(prod_usage & GRALLOC1_PRODUCER_USAGE_GPU_RENDER_TARGET)) {
- enable = AdrenoMemInfo::GetInstance()->IsUBWCSupportedByGPU(format);
+ if (AdrenoMemInfo::GetInstance()) {
+ enable = AdrenoMemInfo::GetInstance()->IsUBWCSupportedByGPU(format);
+ }
}
// Allow UBWC, only if CPU usage flags are not set
@@ -675,8 +677,10 @@
int tile = ubwc_enabled;
if (IsUncompressedRGBFormat(format)) {
- AdrenoMemInfo::GetInstance()->AlignUnCompressedRGB(width, height, format, tile, alignedw,
- alignedh);
+ if (AdrenoMemInfo::GetInstance()) {
+ AdrenoMemInfo::GetInstance()->AlignUnCompressedRGB(width, height, format, tile, alignedw,
+ alignedh);
+ }
return;
}
@@ -686,7 +690,9 @@
}
if (IsCompressedRGBFormat(format)) {
- AdrenoMemInfo::GetInstance()->AlignCompressedRGB(width, height, format, alignedw, alignedh);
+ if (AdrenoMemInfo::GetInstance()) {
+ AdrenoMemInfo::GetInstance()->AlignCompressedRGB(width, height, format, alignedw, alignedh);
+ }
return;
}
@@ -698,6 +704,9 @@
switch (format) {
case HAL_PIXEL_FORMAT_YCrCb_420_SP:
case HAL_PIXEL_FORMAT_YCbCr_420_SP:
+ if (AdrenoMemInfo::GetInstance() == nullptr) {
+ return;
+ }
alignment = AdrenoMemInfo::GetInstance()->GetGpuPixelAlignment();
aligned_w = ALIGN(width, alignment);
break;
diff --git a/sdm/include/private/hw_info_types.h b/sdm/include/private/hw_info_types.h
index 752d0c4..421277a 100644
--- a/sdm/include/private/hw_info_types.h
+++ b/sdm/include/private/hw_info_types.h
@@ -88,6 +88,7 @@
enum HWAlphaInterpolation {
kInterpolationPixelRepeat,
kInterpolationBilinear,
+ kInterpolation2D,
kInterpolationMax,
};
@@ -136,6 +137,12 @@
void Reset() { *this = HWRotatorInfo(); }
};
+enum HWQseedStepVersion {
+ kQseed3v2,
+ kQseed3v3,
+ kQseed3v4,
+};
+
struct HWDestScalarInfo {
uint32_t count = 0;
uint32_t max_input_width = 0;
@@ -205,6 +212,7 @@
CompRatioMap comp_ratio_rt_map;
CompRatioMap comp_ratio_nrt_map;
uint32_t cache_size = 0; // cache size in bytes
+ HWQseedStepVersion pipe_qseed3_version = kQseed3v2; // only valid when has_qseed3=true
void Reset() { *this = HWResourceInfo(); }
};
@@ -274,6 +282,7 @@
uint32_t blackness_level = 0; // Panel's blackness level
HWColorPrimaries primaries = {}; // WRGB color primaries
HWPanelOrientation panel_orientation = {}; // Panel Orientation
+ uint32_t transfer_time_us = 0; // transfer time in micro seconds to panel's active region
bool operator !=(const HWPanelInfo &panel_info) {
return ((port != panel_info.port) || (mode != panel_info.mode) ||
@@ -289,7 +298,8 @@
(max_fps != panel_info.max_fps) || (is_primary_panel != panel_info.is_primary_panel) ||
(split_info != panel_info.split_info) || (s3d_mode != panel_info.s3d_mode) ||
(left_roi_count != panel_info.left_roi_count) ||
- (right_roi_count != panel_info.right_roi_count));
+ (right_roi_count != panel_info.right_roi_count) ||
+ (transfer_time_us != panel_info.transfer_time_us));
}
bool operator ==(const HWPanelInfo &panel_info) {
diff --git a/sdm/libs/core/drm/hw_device_drm.cpp b/sdm/libs/core/drm/hw_device_drm.cpp
index 1ed9042..a5ed8a2 100644
--- a/sdm/libs/core/drm/hw_device_drm.cpp
+++ b/sdm/libs/core/drm/hw_device_drm.cpp
@@ -494,6 +494,7 @@
hw_panel_info_.primaries.green[1] = connector_info_.panel_hdr_prop.display_primaries[5];
hw_panel_info_.primaries.blue[0] = connector_info_.panel_hdr_prop.display_primaries[6];
hw_panel_info_.primaries.blue[1] = connector_info_.panel_hdr_prop.display_primaries[7];
+ hw_panel_info_.transfer_time_us = connector_info_.transfer_time_us;
// no supprt for 90 rotation only flips or 180 supported
hw_panel_info_.panel_orientation.rotation = 0;
@@ -519,6 +520,7 @@
DLOGI("FPS: min = %d, max =%d", hw_panel_info_.min_fps, hw_panel_info_.max_fps);
DLOGI("Left Split = %d, Right Split = %d", hw_panel_info_.split_info.left_split,
hw_panel_info_.split_info.right_split);
+ DLOGI("Panel Transfer time = %d us", hw_panel_info_.transfer_time_us);
}
void HWDeviceDRM::GetHWDisplayPortAndMode() {
@@ -792,6 +794,7 @@
drm_atomic_intf_->Perform(DRMOps::CRTC_SET_DRAM_AB, token_.crtc_id, qos_data.dram_ab_bps);
drm_atomic_intf_->Perform(DRMOps::CRTC_SET_DRAM_IB, token_.crtc_id, qos_data.dram_ib_bps);
drm_atomic_intf_->Perform(DRMOps::CRTC_SET_ROT_CLK, token_.crtc_id, qos_data.rot_clock_hz);
+ drm_atomic_intf_->Perform(DRMOps::CRTC_SET_SECURITY_LEVEL, token_.crtc_id, crtc_security_level);
DLOGI_IF(kTagDriverConfig, "System Clock=%d Hz, Core: AB=%llu Bps, IB=%llu Bps, " \
"LLCC: AB=%llu Bps, IB=%llu Bps, DRAM AB=%llu Bps, IB=%llu Bps Rot Clock=%d",
diff --git a/sdm/libs/core/drm/hw_info_drm.cpp b/sdm/libs/core/drm/hw_info_drm.cpp
index 69af1bd..b8eb564 100644
--- a/sdm/libs/core/drm/hw_info_drm.cpp
+++ b/sdm/libs/core/drm/hw_info_drm.cpp
@@ -101,6 +101,23 @@
char buf_[1024] = {};
};
+static HWQseedStepVersion GetQseedStepVersion(sde_drm::QSEEDStepVersion drm_version) {
+ HWQseedStepVersion sdm_version;
+ switch (drm_version) {
+ case sde_drm::QSEEDStepVersion::V2:
+ default:
+ sdm_version = kQseed3v2;
+ break;
+ case sde_drm::QSEEDStepVersion::V3:
+ sdm_version = kQseed3v3;
+ break;
+ case sde_drm::QSEEDStepVersion::V4:
+ sdm_version = kQseed3v4;
+ break;
+ }
+ return sdm_version;
+}
+
HWResourceInfo *HWInfoDRM::hw_resource_ = nullptr;
HWInfoDRM::HWInfoDRM() {
@@ -374,6 +391,7 @@
hw_resource->has_decimation = info.max_horizontal_deci > 1 && info.max_vertical_deci > 1;
hw_resource->max_pipe_bw = info.max_pipe_bandwidth / kKiloUnit;
hw_resource->cache_size = info.cache_size;
+ hw_resource->pipe_qseed3_version = GetQseedStepVersion(info.qseed3_version);
}
void HWInfoDRM::PopulateSupportedFmts(HWSubBlockType sub_blk_type,
diff --git a/sdm/libs/core/drm/hw_info_drm.h b/sdm/libs/core/drm/hw_info_drm.h
index 5d92c41..7883592 100644
--- a/sdm/libs/core/drm/hw_info_drm.h
+++ b/sdm/libs/core/drm/hw_info_drm.h
@@ -64,7 +64,6 @@
HWResourceInfo *hw_resource);
void PopulatePipeCaps(const sde_drm::DRMPlaneTypeInfo &info, HWResourceInfo *hw_resource);
-
sde_drm::DRMManagerInterface *drm_mgr_intf_ = {};
bool default_mode_ = false;
diff --git a/sdm/libs/core/drm/hw_scale_drm.cpp b/sdm/libs/core/drm/hw_scale_drm.cpp
index 96f084e..de0ccb2 100644
--- a/sdm/libs/core/drm/hw_scale_drm.cpp
+++ b/sdm/libs/core/drm/hw_scale_drm.cpp
@@ -58,6 +58,8 @@
return FILTER_ALPHA_DROP_REPEAT;
case kInterpolationBilinear:
return FILTER_ALPHA_BILINEAR;
+ case kInterpolation2D:
+ return FILTER_ALPHA_2D;
default:
DLOGE("Invalid Alpha Interpolation");
return kInterpolationMax;
diff --git a/sdm/libs/hwc2/hwc_buffer_allocator.cpp b/sdm/libs/hwc2/hwc_buffer_allocator.cpp
index 3c8d460..4865e08 100644
--- a/sdm/libs/hwc2/hwc_buffer_allocator.cpp
+++ b/sdm/libs/hwc2/hwc_buffer_allocator.cpp
@@ -41,23 +41,43 @@
namespace sdm {
-HWCBufferAllocator::HWCBufferAllocator() {
+DisplayError HWCBufferAllocator::Init() {
int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module_);
if (err != 0) {
- DLOGE("FATAL: can not open GRALLOC module");
- } else {
- gralloc1_open(module_, &gralloc_device_);
+ DLOGE("FATAL: can not get GRALLOC module");
+ return kErrorResources;
}
+
+ err = gralloc1_open(module_, &gralloc_device_);
+ if (err != 0) {
+ DLOGE("FATAL: can not open GRALLOC device");
+ return kErrorResources;
+ }
+
+ if (gralloc_device_ == nullptr) {
+ DLOGE("FATAL: gralloc device is null");
+ return kErrorResources;
+ }
+
ReleaseBuffer_ = reinterpret_cast<GRALLOC1_PFN_RELEASE>(
gralloc_device_->getFunction(gralloc_device_, GRALLOC1_FUNCTION_RELEASE));
Perform_ = reinterpret_cast<GRALLOC1_PFN_PERFORM>(
gralloc_device_->getFunction(gralloc_device_, GRALLOC1_FUNCTION_PERFORM));
+ Lock_ = reinterpret_cast<GRALLOC1_PFN_LOCK>(
+ gralloc_device_->getFunction(gralloc_device_, GRALLOC1_FUNCTION_LOCK));
+
+ return kErrorNone;
}
-HWCBufferAllocator::~HWCBufferAllocator() {
+DisplayError HWCBufferAllocator::Deinit() {
if (gralloc_device_ != nullptr) {
- gralloc1_close(gralloc_device_);
+ int err = gralloc1_close(gralloc_device_);
+ if (err != 0) {
+ DLOGE("FATAL: can not close GRALLOC device");
+ return kErrorResources;
+ }
}
+ return kErrorNone;
}
DisplayError HWCBufferAllocator::AllocateBuffer(BufferInfo *buffer_info) {
@@ -354,4 +374,21 @@
return kErrorNone;
}
+DisplayError HWCBufferAllocator::MapBuffer(const private_handle_t *handle, int acquire_fence) {
+ void* buffer_ptr = NULL;
+ const gralloc1_rect_t accessRegion = {
+ .left = 0,
+ .top = 0,
+ .width = 0,
+ .height = 0
+ };
+ Lock_(gralloc_device_, handle, GRALLOC1_PRODUCER_USAGE_CPU_READ, GRALLOC1_CONSUMER_USAGE_NONE,
+ &accessRegion, &buffer_ptr, acquire_fence);
+ if (!buffer_ptr) {
+ return kErrorUndefined;
+ }
+
+ return kErrorNone;
+}
+
} // namespace sdm
diff --git a/sdm/libs/hwc2/hwc_buffer_allocator.h b/sdm/libs/hwc2/hwc_buffer_allocator.h
index d574401..8101d85 100644
--- a/sdm/libs/hwc2/hwc_buffer_allocator.h
+++ b/sdm/libs/hwc2/hwc_buffer_allocator.h
@@ -45,9 +45,8 @@
class HWCBufferAllocator : public BufferAllocator {
public:
- HWCBufferAllocator();
- ~HWCBufferAllocator();
-
+ DisplayError Init();
+ DisplayError Deinit();
DisplayError AllocateBuffer(BufferInfo *buffer_info);
DisplayError FreeBuffer(BufferInfo *buffer_info);
uint32_t GetBufferSize(BufferInfo *buffer_info);
@@ -61,12 +60,14 @@
uint32_t stride[4], uint32_t offset[4],
uint32_t *num_planes);
int SetBufferInfo(LayerBufferFormat format, int *target, uint64_t *flags);
+ DisplayError MapBuffer(const private_handle_t *handle, int acquire_fence);
private:
gralloc1_device_t *gralloc_device_ = nullptr;
const hw_module_t *module_;
GRALLOC1_PFN_RELEASE ReleaseBuffer_ = nullptr;
GRALLOC1_PFN_PERFORM Perform_ = nullptr;
+ GRALLOC1_PFN_LOCK Lock_ = nullptr;
};
} // namespace sdm
diff --git a/sdm/libs/hwc2/hwc_session.cpp b/sdm/libs/hwc2/hwc_session.cpp
index 7f39d7f..293ffce 100644
--- a/sdm/libs/hwc2/hwc_session.cpp
+++ b/sdm/libs/hwc2/hwc_session.cpp
@@ -35,6 +35,8 @@
#include <algorithm>
#include <string>
#include <bitset>
+#include <thread>
+#include <memory>
#include "hwc_buffer_allocator.h"
#include "hwc_buffer_sync_handler.h"
@@ -66,8 +68,63 @@
};
namespace sdm {
+
+static HWCUEvent g_hwc_uevent_;
Locker HWCSession::locker_;
+void HWCUEvent::UEventThread(HWCUEvent *hwc_uevent) {
+ const char *uevent_thread_name = "HWC_UeventThread";
+
+ prctl(PR_SET_NAME, uevent_thread_name, 0, 0, 0);
+ setpriority(PRIO_PROCESS, 0, HAL_PRIORITY_URGENT_DISPLAY);
+
+ int status = uevent_init();
+ if (!status) {
+ std::unique_lock<std::mutex> caller_lock(hwc_uevent->mutex_);
+ hwc_uevent->caller_cv_.notify_one();
+ DLOGE("Failed to init uevent with err %d", status);
+ return;
+ }
+
+ {
+ // Signal caller thread that worker thread is ready to listen to events.
+ std::unique_lock<std::mutex> caller_lock(hwc_uevent->mutex_);
+ hwc_uevent->init_done_ = true;
+ hwc_uevent->caller_cv_.notify_one();
+ }
+
+ while (1) {
+ char uevent_data[PAGE_SIZE] = {};
+
+ // keep last 2 zeroes to ensure double 0 termination
+ int length = uevent_next_event(uevent_data, INT32(sizeof(uevent_data)) - 2);
+
+ // scope of lock to this block only, so that caller is free to set event handler to nullptr;
+ {
+ std::lock_guard<std::mutex> guard(hwc_uevent->mutex_);
+ if (hwc_uevent->uevent_listener_) {
+ hwc_uevent->uevent_listener_->UEventHandler(uevent_data, length);
+ } else {
+ DLOGW("UEvent dropped. No uevent listener.");
+ }
+ }
+ }
+}
+
+HWCUEvent::HWCUEvent() {
+ std::unique_lock<std::mutex> caller_lock(mutex_);
+ std::thread thread(HWCUEvent::UEventThread, this);
+ thread.detach();
+ caller_cv_.wait(caller_lock);
+}
+
+void HWCUEvent::Register(HWCUEventListener *uevent_listener) {
+ DLOGI("Set uevent listener = %p", uevent_listener);
+
+ std::lock_guard<std::mutex> obj(mutex_);
+ uevent_listener_ = uevent_listener;
+}
+
HWCSession::HWCSession(const hw_module_t *module) {
hwc2_device_t::common.tag = HARDWARE_DEVICE_TAG;
hwc2_device_t::common.version = HWC_DEVICE_API_VERSION_2_0;
@@ -81,6 +138,10 @@
int status = -EINVAL;
const char *qservice_name = "display.qservice";
+ if (!g_hwc_uevent_.InitDone()) {
+ return status;
+ }
+
// Start QService and connect to it.
qService::QService::init();
android::sp<qService::IQService> iqservice = android::interface_cast<qService::IQService>(
@@ -96,19 +157,29 @@
StartServices();
- DisplayError error = CoreInterface::CreateCore(HWCDebugHandler::Get(), &buffer_allocator_,
- &buffer_sync_handler_, &socket_handler_,
- &core_intf_);
+ DisplayError error = buffer_allocator_.Init();
if (error != kErrorNone) {
+ DLOGE("Buffer allocaor initialization failed. Error = %d", error);
+ return -EINVAL;
+ }
+
+ error = CoreInterface::CreateCore(HWCDebugHandler::Get(), &buffer_allocator_,
+ &buffer_sync_handler_, &socket_handler_, &core_intf_);
+ if (error != kErrorNone) {
+ buffer_allocator_.Deinit();
DLOGE("Display core initialization failed. Error = %d", error);
return -EINVAL;
}
+ g_hwc_uevent_.Register(this);
+
// If HDMI display is primary display, defer display creation until hotplug event is received.
HWDisplayInterfaceInfo hw_disp_info = {};
error = core_intf_->GetFirstDisplayInterfaceType(&hw_disp_info);
if (error != kErrorNone) {
+ g_hwc_uevent_.Register(nullptr);
CoreInterface::DestroyCore();
+ buffer_allocator_.Deinit();
DLOGE("Primary display type not recognized. Error = %d", error);
return -EINVAL;
}
@@ -132,7 +203,9 @@
}
if (status) {
+ g_hwc_uevent_.Register(nullptr);
CoreInterface::DestroyCore();
+ buffer_allocator_.Deinit();
return status;
}
@@ -146,9 +219,6 @@
}
}
- std::thread uevent_thread(HWCUeventThread, this);
- uevent_thread_.swap(uevent_thread);
-
return 0;
}
@@ -167,10 +237,7 @@
color_mgr_->DestroyColorManager();
}
- DLOGD("Terminating uevent thread");
- uevent_thread_exit_ = true;
- // todo(user): add a local event to interrupt thread execution and join.
- uevent_thread_.detach();
+ g_hwc_uevent_.Register(nullptr);
DisplayError error = CoreInterface::DestroyCore();
if (error != kErrorNone) {
@@ -1238,52 +1305,26 @@
return (ret ? -EINVAL : 0);
}
-void *HWCSession::HWCUeventThread(void *context) {
- if (context) {
- return reinterpret_cast<HWCSession *>(context)->HWCUeventThreadHandler();
- }
-
- return NULL;
-}
-
-void *HWCSession::HWCUeventThreadHandler() {
- static char uevent_data[PAGE_SIZE];
- int length = 0;
- prctl(PR_SET_NAME, uevent_thread_name_, 0, 0, 0);
- setpriority(PRIO_PROCESS, 0, HAL_PRIORITY_URGENT_DISPLAY);
- if (!uevent_init()) {
- DLOGE("Failed to init uevent");
- pthread_exit(0);
- return NULL;
- }
-
- while (!uevent_thread_exit_) {
- // keep last 2 zeroes to ensure double 0 termination
- length = uevent_next_event(uevent_data, INT32(sizeof(uevent_data)) - 2);
-
- if (strcasestr(HWC_UEVENT_SWITCH_HDMI, uevent_data)) {
- DLOGI("Uevent HDMI = %s", uevent_data);
- int connected = GetEventValue(uevent_data, length, "SWITCH_STATE=");
- if (connected >= 0) {
- DLOGI("HDMI = %s", connected ? "connected" : "disconnected");
- if (HotPlugHandler(connected) == -1) {
- DLOGE("Failed handling Hotplug = %s", connected ? "connected" : "disconnected");
- }
+void HWCSession::UEventHandler(const char *uevent_data, int length) {
+ if (strcasestr(uevent_data, HWC_UEVENT_SWITCH_HDMI)) {
+ DLOGI("Uevent HDMI = %s", uevent_data);
+ int connected = GetEventValue(uevent_data, length, "SWITCH_STATE=");
+ if (connected >= 0) {
+ DLOGI("HDMI = %s", connected ? "connected" : "disconnected");
+ if (HotPlugHandler(connected) == -1) {
+ DLOGE("Failed handling Hotplug = %s", connected ? "connected" : "disconnected");
}
- } else if (strcasestr(HWC_UEVENT_GRAPHICS_FB0, uevent_data)) {
- DLOGI("Uevent FB0 = %s", uevent_data);
- int panel_reset = GetEventValue(uevent_data, length, "PANEL_ALIVE=");
- if (panel_reset == 0) {
- callbacks_.Refresh(0);
- reset_panel_ = true;
- }
- } else if (strcasestr(uevent_data, HWC_UEVENT_DRM_EXT_HOTPLUG)) {
- HandleExtHPD(uevent_data, length);
}
+ } else if (strcasestr(uevent_data, HWC_UEVENT_GRAPHICS_FB0)) {
+ DLOGI("Uevent FB0 = %s", uevent_data);
+ int panel_reset = GetEventValue(uevent_data, length, "PANEL_ALIVE=");
+ if (panel_reset == 0) {
+ callbacks_.Refresh(0);
+ reset_panel_ = true;
+ }
+ } else if (strcasestr(uevent_data, HWC_UEVENT_DRM_EXT_HOTPLUG)) {
+ HandleExtHPD(uevent_data, length);
}
- pthread_exit(0);
-
- return NULL;
}
void HWCSession::HandleExtHPD(const char *uevent_data, int length) {
diff --git a/sdm/libs/hwc2/hwc_session.h b/sdm/libs/hwc2/hwc_session.h
index cd9831d..7d2a30c 100644
--- a/sdm/libs/hwc2/hwc_session.h
+++ b/sdm/libs/hwc2/hwc_session.h
@@ -23,7 +23,6 @@
#include <vendor/display/config/1.0/IDisplayConfig.h>
#include <core/core_interface.h>
#include <utils/locker.h>
-#include <thread>
#include "hwc_callbacks.h"
#include "hwc_layers.h"
@@ -39,7 +38,32 @@
using ::vendor::display::config::V1_0::IDisplayConfig;
using ::android::hardware::Return;
-class HWCSession : hwc2_device_t, public IDisplayConfig, public qClient::BnQClient {
+// Create a singleton uevent listener thread valid for life of hardware composer process.
+// This thread blocks on uevents poll inside uevent library implementation. This poll exits
+// only when there is a valid uevent, it can not be interrupted otherwise. Tieing life cycle
+// of this thread with HWC session cause HWC deinitialization to wait infinitely for the
+// thread to exit.
+class HWCUEventListener {
+ public:
+ virtual ~HWCUEventListener() {}
+ virtual void UEventHandler(const char *uevent_data, int length) = 0;
+};
+
+class HWCUEvent {
+ public:
+ HWCUEvent();
+ static void UEventThread(HWCUEvent *hwc_event);
+ void Register(HWCUEventListener *uevent_listener);
+ inline bool InitDone() { return init_done_; }
+
+ private:
+ std::mutex mutex_;
+ std::condition_variable caller_cv_;
+ HWCUEventListener *uevent_listener_ = nullptr;
+ bool init_done_ = false;
+};
+
+class HWCSession : hwc2_device_t, HWCUEventListener, IDisplayConfig, public qClient::BnQClient {
public:
struct HWCModuleMethods : public hw_module_methods_t {
HWCModuleMethods() { hw_module_methods_t::open = HWCSession::Open; }
@@ -120,9 +144,8 @@
int32_t *outCapabilities);
static hwc2_function_pointer_t GetFunction(struct hwc2_device *device, int32_t descriptor);
- // Uevent thread
- static void *HWCUeventThread(void *context);
- void *HWCUeventThreadHandler();
+ // Uevent handler
+ virtual void UEventHandler(const char *uevent_data, int length);
int GetEventValue(const char *uevent_data, int length, const char *event_info);
void HandleExtHPD(const char *uevent_data, int length);
int HotPlugHandler(bool connected);
@@ -192,9 +215,6 @@
CoreInterface *core_intf_ = nullptr;
HWCDisplay *hwc_display_[HWC_NUM_DISPLAY_TYPES] = {nullptr};
HWCCallbacks callbacks_;
- std::thread uevent_thread_;
- bool uevent_thread_exit_ = false;
- const char *uevent_thread_name_ = "HWC_UeventThread";
HWCBufferAllocator buffer_allocator_;
HWCBufferSyncHandler buffer_sync_handler_;
HWCColorManager *color_mgr_ = nullptr;
diff --git a/sdm/libs/hwc2/hwc_tonemapper.cpp b/sdm/libs/hwc2/hwc_tonemapper.cpp
index 2626d93..a224e8d 100644
--- a/sdm/libs/hwc2/hwc_tonemapper.cpp
+++ b/sdm/libs/hwc2/hwc_tonemapper.cpp
@@ -289,6 +289,7 @@
}
void HWCToneMapper::DumpToneMapOutput(ToneMapSession *session, int *acquire_fd) {
+ DisplayError error = kErrorNone;
if (!dump_frame_count_) {
return;
}
@@ -304,6 +305,12 @@
}
}
+ error = buffer_allocator_->MapBuffer(target_buffer, *acquire_fd);
+ if (error != kErrorNone) {
+ DLOGE("MapBuffer failed, base addr = %x", target_buffer->base);
+ return;
+ }
+
size_t result = 0;
char dump_file_name[PATH_MAX];
snprintf(dump_file_name, sizeof(dump_file_name), "%s/frame_dump_primary"