Merge "sdm:hwc2: Add buffer map to tonemap output buffer"
diff --git a/gpu_tonemapper/Tonemapper.cpp b/gpu_tonemapper/Tonemapper.cpp
index 981863d..811e091 100644
--- a/gpu_tonemapper/Tonemapper.cpp
+++ b/gpu_tonemapper/Tonemapper.cpp
@@ -45,7 +45,6 @@
Tonemapper::~Tonemapper()
//-----------------------------------------------------------------------------
{
- void* caller_context = engine_backup();
engine_bind(engineContext);
engine_deleteInputBuffer(tonemapTexture);
engine_deleteInputBuffer(lutXformTexture);
@@ -58,9 +57,6 @@
}
engine_shutdown(engineContext);
- // restore the caller context
- engine_bind(caller_context);
- engine_free_backup(caller_context);
}
//-----------------------------------------------------------------------------
@@ -78,7 +74,6 @@
tonemapper->engineContext = engine_initialize(isSecure);
- void* caller_context = engine_backup();
engine_bind(tonemapper->engineContext);
// load the 3d lut
@@ -117,10 +112,6 @@
tonemapper->programID =
engine_loadProgram(1, &fullscreen_vertex_shader, fragmentShaderCount, fragmentShaders);
- // restore the caller context
- engine_bind(caller_context);
- engine_free_backup(caller_context);
-
return tonemapper;
}
@@ -128,7 +119,6 @@
int Tonemapper::blit(const void *dst, const void *src, int srcFenceFd)
//-----------------------------------------------------------------------------
{
- void* caller_context = engine_backup();
// make current
engine_bind(engineContext);
@@ -159,10 +149,5 @@
// perform
int fenceFD = engine_blit(srcFenceFd);
- // restore the caller context
- engine_bind(caller_context);
- engine_free_backup(caller_context);
-
-
return fenceFD;
}
diff --git a/gpu_tonemapper/engine.h b/gpu_tonemapper/engine.h
index e0bf2aa..8fb9452 100644
--- a/gpu_tonemapper/engine.h
+++ b/gpu_tonemapper/engine.h
@@ -22,8 +22,6 @@
void* engine_initialize(bool isSecure);
void engine_bind(void*);
-void* engine_backup();
-void engine_free_backup(void*);
void engine_shutdown(void*);
unsigned int engine_loadProgram(int, const char **, int, const char **);
diff --git a/gpu_tonemapper/glengine.cpp b/gpu_tonemapper/glengine.cpp
index 6cfe15f..6c94c23 100644
--- a/gpu_tonemapper/glengine.cpp
+++ b/gpu_tonemapper/glengine.cpp
@@ -47,27 +47,6 @@
}
//-----------------------------------------------------------------------------
-// store the current context(caller)
-void* engine_backup()
-{
- EngineContext* callerContext = new EngineContext();
- // store the previous display/context
- callerContext->eglDisplay = eglGetCurrentDisplay();
- callerContext->eglContext = eglGetCurrentContext();
- callerContext->eglSurface = eglGetCurrentSurface(EGL_DRAW);
-
- return (void*)callerContext;
-}
-//-----------------------------------------------------------------------------
-// frees the backed up caller context
-void engine_free_backup(void* context)
-{
- EngineContext* callerContext = (EngineContext*)(context);
-
- delete callerContext;
-}
-
-//-----------------------------------------------------------------------------
// initialize GL
//
void* engine_initialize(bool isSecure)
diff --git a/libgralloc1/gralloc_priv.h b/libgralloc1/gralloc_priv.h
index d8dfbf3..87604c6 100644
--- a/libgralloc1/gralloc_priv.h
+++ b/libgralloc1/gralloc_priv.h
@@ -65,7 +65,7 @@
#define GRALLOC1_CONSUMER_USAGE_PRIVATE_WFD 0x00200000
/* This flag is used for SECURE display usecase */
-#define GRALLOC1_CONSUMER_USAGE_PRIVATE_SECURE_DISPLAY 0x00800000
+#define GRALLOC1_CONSUMER_USAGE_PRIVATE_SECURE_DISPLAY 0x01000000
/* Unused flag */
#define GRALLOC1_USAGE_PRIVATE_UNUSED1 0x04000000
diff --git a/sdm/include/private/color_params.h b/sdm/include/private/color_params.h
index 08895ee..14ec40f 100644
--- a/sdm/include/private/color_params.h
+++ b/sdm/include/private/color_params.h
@@ -157,6 +157,7 @@
static const uint32_t kSDEPADitherV17 = 16;
static const uint32_t kSDEIgcV30 = 17;
static const uint32_t kSDEGamutV4 = 18;
+ static const uint32_t kSDEPccV4 = 19;
uint32_t version[kMaxNumPPFeatures];
PPFeatureVersion() { memset(version, 0, sizeof(version)); }
@@ -327,6 +328,29 @@
SDEPccCfg *GetConfig() { return this; }
};
+struct SDEPccV4Coeff {
+ uint32_t c = 0;
+ uint32_t r = 0;
+ uint32_t g = 0;
+ uint32_t b = 0;
+ uint32_t rg = 0;
+ uint32_t gb = 0;
+ uint32_t rb = 0;
+ uint32_t rgb = 0;
+ uint32_t rr = 0;
+ uint32_t gg = 0;
+ uint32_t bb = 0;
+};
+
+struct SDEPccV4Cfg {
+ SDEPccV4Coeff red;
+ SDEPccV4Coeff green;
+ SDEPccV4Coeff blue;
+
+ static SDEPccV4Cfg *Init(uint32_t arg __attribute__((__unused__)));
+ SDEPccV4Cfg *GetConfig() { return this; }
+};
+
struct SDEDitherCfg {
uint32_t g_y_depth;
uint32_t r_cr_depth;
diff --git a/sdm/include/utils/debug.h b/sdm/include/utils/debug.h
index 0b40e7b..d5974d9 100644
--- a/sdm/include/utils/debug.h
+++ b/sdm/include/utils/debug.h
@@ -78,6 +78,7 @@
static bool IsAVRDisabled();
static bool IsExtAnimDisabled();
static bool IsPartialSplitDisabled();
+ static bool IsSrcSplitPreferred();
static DisplayError GetMixerResolution(uint32_t *width, uint32_t *height);
static DisplayError GetReducedConfig(uint32_t *num_vig_pipes, uint32_t *num_dma_pipes);
static int GetExtMaxlayers();
diff --git a/sdm/libs/core/Android.mk b/sdm/libs/core/Android.mk
index 14df125..cf3543c 100644
--- a/sdm/libs/core/Android.mk
+++ b/sdm/libs/core/Android.mk
@@ -13,7 +13,7 @@
LOCAL_SHARED_LIBRARIES := libdl libsdmutils
ifneq ($(TARGET_IS_HEADLESS), true)
- LOCAL_CFLAGS += -DCOMPILE_DRM -isystem external/libdrm
+ LOCAL_CFLAGS += -isystem external/libdrm
LOCAL_SHARED_LIBRARIES += libdrm libdrmutils
LOCAL_HW_INTF_PATH_2 := drm
endif
diff --git a/sdm/libs/core/drm/hw_color_manager_drm.cpp b/sdm/libs/core/drm/hw_color_manager_drm.cpp
index 67478c9..2000f9a 100644
--- a/sdm/libs/core/drm/hw_color_manager_drm.cpp
+++ b/sdm/libs/core/drm/hw_color_manager_drm.cpp
@@ -77,6 +77,11 @@
switch (feature.id) {
case kFeaturePcc:
+ if (feature.version == 1) {
+ version = PPFeatureVersion::kSDEPccV17;
+ } else if (feature.version == 4) {
+ version = PPFeatureVersion::kSDEPccV4;
+ }
break;
case kFeatureIgc:
if (feature.version == 3)
@@ -87,10 +92,13 @@
version = PPFeatureVersion::kSDEPgcV17;
break;
case kFeatureMixerGc:
+ version = PPFeatureVersion::kSDEPgcV17;
break;
case kFeaturePaV2:
+ version = PPFeatureVersion::kSDEPaV17;
break;
case kFeatureDither:
+ version = PPFeatureVersion::kSDEDitherV17;
break;
case kFeatureGamut:
if (feature.version == 1)
@@ -99,6 +107,7 @@
version = PPFeatureVersion::kSDEGamutV4;
break;
case kFeaturePADither:
+ version = PPFeatureVersion::kSDEPADitherV17;
break;
default:
break;
@@ -143,6 +152,84 @@
DisplayError HWColorManagerDrm::GetDrmPCC(const PPFeatureInfo &in_data,
DRMPPFeatureInfo *out_data) {
DisplayError ret = kErrorNone;
+#ifdef PP_DRM_ENABLE
+ struct SDEPccV4Cfg *sde_pcc = NULL;
+ struct SDEPccV4Coeff *sde_pcc_coeffs = NULL;
+ struct drm_msm_pcc *mdp_pcc = NULL;
+ struct drm_msm_pcc_coeff *mdp_pcc_coeffs = NULL;
+ uint32_t i = 0;
+
+ if (!out_data) {
+ DLOGE("Invalid input parameter for pcc");
+ return kErrorParameters;
+ }
+
+ switch (in_data.feature_version_) {
+ case PPFeatureVersion::kSDEPccV4:
+ sde_pcc = (struct SDEPccV4Cfg *) in_data.GetConfigData();
+ break;
+ default:
+ DLOGE("Unsupported pcc feature version: %d", in_data.feature_version_);
+ return kErrorParameters;
+ }
+
+ out_data->id = kFeaturePcc;
+ out_data->type = sde_drm::kPropBlob;
+ out_data->version = in_data.feature_version_;
+ out_data->payload_size = sizeof(struct drm_msm_pcc);
+
+ if (in_data.enable_flags_ & kOpsDisable) {
+ /* feature disable case */
+ out_data->payload = NULL;
+ return ret;
+ } else if (!(in_data.enable_flags_ & kOpsEnable)) {
+ out_data->payload = NULL;
+ return kErrorParameters;
+ }
+
+ mdp_pcc = new drm_msm_pcc();
+ if (!mdp_pcc) {
+ DLOGE("Failed to allocate memory for pcc");
+ return kErrorMemory;
+ }
+
+ mdp_pcc->flags = 0;
+
+ for (i = 0; i < kMaxPCCChanel; i++) {
+ switch (i) {
+ case 0:
+ sde_pcc_coeffs = &sde_pcc->red;
+ mdp_pcc_coeffs = &mdp_pcc->r;
+ mdp_pcc->r_rr = sde_pcc_coeffs->rr;
+ mdp_pcc->r_gg = sde_pcc_coeffs->gg;
+ mdp_pcc->r_bb = sde_pcc_coeffs->bb;
+ break;
+ case 1:
+ sde_pcc_coeffs = &sde_pcc->green;
+ mdp_pcc_coeffs = &mdp_pcc->g;
+ mdp_pcc->g_rr = sde_pcc_coeffs->rr;
+ mdp_pcc->g_gg = sde_pcc_coeffs->gg;
+ mdp_pcc->g_bb = sde_pcc_coeffs->bb;
+ break;
+ case 2:
+ sde_pcc_coeffs = &sde_pcc->blue;
+ mdp_pcc_coeffs = &mdp_pcc->b;
+ mdp_pcc->b_rr = sde_pcc_coeffs->rr;
+ mdp_pcc->b_gg = sde_pcc_coeffs->gg;
+ mdp_pcc->b_bb = sde_pcc_coeffs->bb;
+ break;
+ }
+ mdp_pcc_coeffs->c = sde_pcc_coeffs->c;
+ mdp_pcc_coeffs->r = sde_pcc_coeffs->r;
+ mdp_pcc_coeffs->g = sde_pcc_coeffs->g;
+ mdp_pcc_coeffs->b = sde_pcc_coeffs->b;
+ mdp_pcc_coeffs->rg = sde_pcc_coeffs->rg;
+ mdp_pcc_coeffs->gb = sde_pcc_coeffs->gb;
+ mdp_pcc_coeffs->rb = sde_pcc_coeffs->rb;
+ mdp_pcc_coeffs->rgb = sde_pcc_coeffs->rgb;
+ }
+ out_data->payload = mdp_pcc;
+#endif
return ret;
}
@@ -266,18 +353,49 @@
DisplayError HWColorManagerDrm::GetDrmMixerGC(const PPFeatureInfo &in_data,
DRMPPFeatureInfo *out_data) {
DisplayError ret = kErrorNone;
+#ifdef PP_DRM_ENABLE
+ if (!out_data) {
+ DLOGE("Invalid input parameter for Mixer GC");
+ return kErrorParameters;
+ }
+
+ out_data->id = kPPFeaturesMax;
+ out_data->type = sde_drm::kPropBlob;
+ out_data->version = in_data.feature_version_;
+#endif
return ret;
}
DisplayError HWColorManagerDrm::GetDrmPAV2(const PPFeatureInfo &in_data,
DRMPPFeatureInfo *out_data) {
DisplayError ret = kErrorNone;
+#ifdef PP_DRM_ENABLE
+ if (!out_data) {
+ DLOGE("Invalid input parameter for PA V2");
+ return kErrorParameters;
+ }
+
+ out_data->id = kPPFeaturesMax;
+ out_data->type = sde_drm::kPropBlob;
+ out_data->version = in_data.feature_version_;
+
+#endif
return ret;
}
DisplayError HWColorManagerDrm::GetDrmDither(const PPFeatureInfo &in_data,
DRMPPFeatureInfo *out_data) {
DisplayError ret = kErrorNone;
+#ifdef PP_DRM_ENABLE
+ if (!out_data) {
+ DLOGE("Invalid input parameter for dither");
+ return kErrorParameters;
+ }
+
+ out_data->id = kPPFeaturesMax;
+ out_data->type = sde_drm::kPropBlob;
+ out_data->version = in_data.feature_version_;
+#endif
return ret;
}
@@ -360,6 +478,16 @@
DisplayError HWColorManagerDrm::GetDrmPADither(const PPFeatureInfo &in_data,
DRMPPFeatureInfo *out_data) {
DisplayError ret = kErrorNone;
+#ifdef PP_DRM_ENABLE
+ if (!out_data) {
+ DLOGE("Invalid input parameter for PA dither");
+ return kErrorParameters;
+ }
+
+ out_data->id = kPPFeaturesMax;
+ out_data->type = sde_drm::kPropBlob;
+ out_data->version = in_data.feature_version_;
+#endif
return ret;
}
diff --git a/sdm/libs/core/drm/hw_color_manager_drm.h b/sdm/libs/core/drm/hw_color_manager_drm.h
index a10d00b..290c606 100644
--- a/sdm/libs/core/drm/hw_color_manager_drm.h
+++ b/sdm/libs/core/drm/hw_color_manager_drm.h
@@ -38,6 +38,8 @@
namespace sdm {
+static const uint32_t kMaxPCCChanel = 3;
+
class HWColorManagerDrm {
public:
static DisplayError (*GetDrmFeature[kMaxNumPPFeatures])(const PPFeatureInfo &in_data,
diff --git a/sdm/libs/core/hw_events_interface.cpp b/sdm/libs/core/hw_events_interface.cpp
index 5817cdb..84a7dab 100644
--- a/sdm/libs/core/hw_events_interface.cpp
+++ b/sdm/libs/core/hw_events_interface.cpp
@@ -32,9 +32,7 @@
#include "hw_events_interface.h"
#include "fb/hw_events.h"
-#ifdef COMPILE_DRM
#include "drm/hw_events_drm.h"
-#endif
#define __CLASS__ "HWEventsInterface"
@@ -48,9 +46,7 @@
if (GetDriverType() == DriverType::FB) {
hw_events = new HWEvents();
} else {
-#ifdef COMPILE_DRM
hw_events = new HWEventsDRM();
-#endif
}
error = hw_events->Init(display_type, event_handler, event_list, hw_intf);
diff --git a/sdm/libs/core/hw_info_interface.cpp b/sdm/libs/core/hw_info_interface.cpp
index 1773fe5..79bc79a 100644
--- a/sdm/libs/core/hw_info_interface.cpp
+++ b/sdm/libs/core/hw_info_interface.cpp
@@ -31,9 +31,7 @@
#include "hw_info_interface.h"
#include "fb/hw_info.h"
-#ifdef COMPILE_DRM
#include "drm/hw_info_drm.h"
-#endif
#define __CLASS__ "HWInfoInterface"
@@ -43,9 +41,7 @@
if (GetDriverType() == DriverType::FB) {
*intf = new HWInfo();
} else {
-#ifdef COMPILE_DRM
*intf = new HWInfoDRM();
-#endif
}
return kErrorNone;
diff --git a/sdm/libs/core/hw_interface.cpp b/sdm/libs/core/hw_interface.cpp
index cfaf72b..2d8d41e 100644
--- a/sdm/libs/core/hw_interface.cpp
+++ b/sdm/libs/core/hw_interface.cpp
@@ -35,11 +35,9 @@
#include "fb/hw_primary.h"
#include "fb/hw_hdmi.h"
#include "fb/hw_virtual.h"
-#ifdef COMPILE_DRM
#include "drm/hw_device_drm.h"
#include "drm/hw_virtual_drm.h"
#include "drm/hw_tv_drm.h"
-#endif
#define __CLASS__ "HWInterface"
@@ -57,27 +55,21 @@
if (driver_type == DriverType::FB) {
hw = new HWPrimary(buffer_sync_handler, hw_info_intf);
} else {
-#ifdef COMPILE_DRM
hw = new HWDeviceDRM(buffer_sync_handler, buffer_allocator, hw_info_intf);
-#endif
}
break;
case kHDMI:
if (driver_type == DriverType::FB) {
hw = new HWHDMI(buffer_sync_handler, hw_info_intf);
} else {
-#ifdef COMPILE_DRM
hw = new HWTVDRM(buffer_sync_handler, buffer_allocator, hw_info_intf);
-#endif
}
break;
case kVirtual:
if (driver_type == DriverType::FB) {
hw = new HWVirtual(buffer_sync_handler, hw_info_intf);
} else {
-#ifdef COMPILE_DRM
hw = new HWVirtualDRM(buffer_sync_handler, buffer_allocator, hw_info_intf);
-#endif
}
break;
default:
diff --git a/sdm/libs/hwc2/hwc_display.cpp b/sdm/libs/hwc2/hwc_display.cpp
index 91879ae..f7a9dec 100644
--- a/sdm/libs/hwc2/hwc_display.cpp
+++ b/sdm/libs/hwc2/hwc_display.cpp
@@ -363,11 +363,18 @@
// TODO(user): Add blit engine when needed
}
+ error = display_intf_->GetNumVariableInfoConfigs(&num_configs_);
+ if (error != kErrorNone) {
+ DLOGE("Getting config count failed. Error = %d", error);
+ return -EINVAL;
+ }
+
tone_mapper_ = new HWCToneMapper(buffer_allocator_);
display_intf_->GetRefreshRateRange(&min_refresh_rate_, &max_refresh_rate_);
current_refresh_rate_ = max_refresh_rate_;
DLOGI("Display created with id: %d", id_);
+
return 0;
}
@@ -454,12 +461,11 @@
layer->flags.solid_fill = true;
}
+ if (!hwc_layer->ValidateAndSetCSC()) {
#ifdef FEATURE_WIDE_COLOR
- if (!hwc_layer->SupportedDataspace()) {
- layer->flags.skip = true;
- DLOGW_IF(kTagStrategy, "Unsupported dataspace: 0x%x", hwc_layer->GetLayerDataspace());
- }
+ layer->flags.skip = true;
#endif
+ }
working_primaries = WidestPrimaries(working_primaries,
layer->input_buffer.color_metadata.colorPrimaries);
@@ -717,12 +723,15 @@
}
HWC2::Error HWCDisplay::GetDisplayConfigs(uint32_t *out_num_configs, hwc2_config_t *out_configs) {
- // TODO(user): Actually handle multiple configs
if (out_configs == nullptr) {
- *out_num_configs = 1;
- } else {
- *out_num_configs = 1;
- out_configs[0] = 0;
+ *out_num_configs = num_configs_;
+ return HWC2::Error::None;
+ }
+
+ *out_num_configs = num_configs_;
+
+ for (uint32_t i = 0; i < num_configs_; i++) {
+ out_configs[i] = i;
}
return HWC2::Error::None;
@@ -731,16 +740,11 @@
HWC2::Error HWCDisplay::GetDisplayAttribute(hwc2_config_t config, HWC2::Attribute attribute,
int32_t *out_value) {
DisplayConfigVariableInfo variable_config;
- DisplayError error = display_intf_->GetFrameBufferConfig(&variable_config);
- if (error != kErrorNone) {
- DLOGV("Get variable config failed. Error = %d", error);
+ if (GetDisplayAttributesForConfig(INT(config), &variable_config) != kErrorNone) {
+ DLOGE("Get variable config failed");
return HWC2::Error::BadDisplay;
}
- if (config != 0) { // We only use config[0] - see TODO above
- return HWC2::Error::BadConfig;
- }
-
switch (attribute) {
case HWC2::Attribute::VsyncPeriod:
*out_value = INT32(variable_config.vsync_period_ns);
@@ -805,14 +809,19 @@
}
}
-// TODO(user): Store configurations and hook them up here
HWC2::Error HWCDisplay::GetActiveConfig(hwc2_config_t *out_config) {
- if (out_config != nullptr) {
- *out_config = 0;
- return HWC2::Error::None;
- } else {
- return HWC2::Error::BadParameter;
+ if (out_config == nullptr) {
+ return HWC2::Error::BadDisplay;
}
+
+ uint32_t active_index = 0;
+ if (GetActiveDisplayConfig(&active_index) != kErrorNone) {
+ return HWC2::Error::BadConfig;
+ }
+
+ *out_config = active_index;
+
+ return HWC2::Error::None;
}
HWC2::Error HWCDisplay::SetClientTarget(buffer_handle_t target, int32_t acquire_fence,
@@ -837,10 +846,10 @@
}
HWC2::Error HWCDisplay::SetActiveConfig(hwc2_config_t config) {
- if (config != 0) {
+ if (SetActiveDisplayConfig(config) != kErrorNone) {
return HWC2::Error::BadConfig;
}
- // We have only one config right now - do nothing
+
return HWC2::Error::None;
}
diff --git a/sdm/libs/hwc2/hwc_display.h b/sdm/libs/hwc2/hwc_display.h
index b70f160..e773e91 100644
--- a/sdm/libs/hwc2/hwc_display.h
+++ b/sdm/libs/hwc2/hwc_display.h
@@ -299,6 +299,7 @@
bool color_tranform_failed_ = false;
HWCColorMode *color_mode_ = NULL;
HWCToneMapper *tone_mapper_ = nullptr;
+ uint32_t num_configs_ = 0;
int disable_hdr_handling_ = 0; // disables HDR handling.
private:
diff --git a/sdm/libs/hwc2/hwc_layers.cpp b/sdm/libs/hwc2/hwc_layers.cpp
index f485ac6..6b5d470 100644
--- a/sdm/libs/hwc2/hwc_layers.cpp
+++ b/sdm/libs/hwc2/hwc_layers.cpp
@@ -255,6 +255,7 @@
}
}
+ // cache the dataspace, to be used later to update SDM ColorMetaData
if (dataspace_ != dataspace) {
geometry_changes_ |= kDataspace;
dataspace_ = dataspace;
@@ -573,19 +574,6 @@
DisplayError HWCLayer::SetMetaData(const private_handle_t *pvt_handle, Layer *layer) {
LayerBuffer *layer_buffer = &layer->input_buffer;
- bool use_color_metadata = true;
-
-#ifdef FEATURE_WIDE_COLOR
- // Only use color metadata if Android framework metadata is not set
- use_color_metadata = (dataspace_ == HAL_DATASPACE_UNKNOWN);
-#endif
-
- if (use_color_metadata) {
- if (sdm::SetCSC(pvt_handle, &layer_buffer->color_metadata) != kErrorNone) {
- return kErrorNotSupported;
- }
- }
-
private_handle_t *handle = const_cast<private_handle_t *>(pvt_handle);
IGC_t igc = {};
if (getMetaData(handle, GET_IGC, &igc) == 0) {
@@ -655,84 +643,106 @@
return false;
}
-bool HWCLayer::SupportedDataspace() {
- if (dataspace_ == HAL_DATASPACE_UNKNOWN) {
- // Pick values from metadata
+bool HWCLayer::ValidateAndSetCSC() {
+ if (client_requested_ != HWC2::Composition::Device &&
+ client_requested_ != HWC2::Composition::Cursor) {
+ // Check the layers which are configured to Device
return true;
}
+ // Retrieve ColorMetaData from android_data_space_t (STANDARD|TRANSFER|RANGE)
LayerBuffer *layer_buffer = &layer_->input_buffer;
+ bool use_color_metadata = true;
+#ifdef FEATURE_WIDE_COLOR
GammaTransfer sdm_transfer = {};
ColorPrimaries sdm_primaries = {};
ColorRange sdm_range = {};
+ if (dataspace_ != HAL_DATASPACE_UNKNOWN) {
+ use_color_metadata = false; // avoid using color_metadata
+ auto transfer = dataspace_ & HAL_DATASPACE_TRANSFER_MASK;
+ // Handle transfer
+ switch (transfer) {
+ case HAL_DATASPACE_TRANSFER_SRGB:
+ sdm_transfer = Transfer_sRGB;
+ break;
+ case HAL_DATASPACE_TRANSFER_SMPTE_170M:
+ sdm_transfer = Transfer_SMPTE_170M;
+ break;
+ case HAL_DATASPACE_TRANSFER_ST2084:
+ sdm_transfer = Transfer_SMPTE_ST2084;
+ break;
+ case HAL_DATASPACE_TRANSFER_HLG:
+ sdm_transfer = Transfer_HLG;
+ break;
+ case HAL_DATASPACE_TRANSFER_LINEAR:
+ sdm_transfer = Transfer_Linear;
+ break;
+ case HAL_DATASPACE_TRANSFER_GAMMA2_2:
+ sdm_transfer = Transfer_Gamma2_2;
+ break;
+ default:
+ DLOGV_IF(kTagStrategy, "Unsupported Transfer Request = %d", transfer);
+ return false;
+ }
- auto transfer = dataspace_ & HAL_DATASPACE_TRANSFER_MASK;
- // Handle transfer
- switch (transfer) {
- case HAL_DATASPACE_TRANSFER_SRGB:
- sdm_transfer = Transfer_sRGB;
- break;
- case HAL_DATASPACE_TRANSFER_SMPTE_170M:
- sdm_transfer = Transfer_SMPTE_170M;
- break;
- case HAL_DATASPACE_TRANSFER_ST2084:
- sdm_transfer = Transfer_SMPTE_ST2084;
- break;
- case HAL_DATASPACE_TRANSFER_HLG:
- sdm_transfer = Transfer_HLG;
- break;
- case HAL_DATASPACE_TRANSFER_LINEAR:
- sdm_transfer = Transfer_Linear;
- break;
- case HAL_DATASPACE_TRANSFER_GAMMA2_2:
- sdm_transfer = Transfer_Gamma2_2;
- break;
- default:
+ // Handle standard
+ auto standard = dataspace_ & HAL_DATASPACE_STANDARD_MASK;
+ switch (standard) {
+ case HAL_DATASPACE_STANDARD_BT709:
+ sdm_primaries = ColorPrimaries_BT709_5;
+ break;
+ case HAL_DATASPACE_STANDARD_BT601_525:
+ case HAL_DATASPACE_STANDARD_BT601_525_UNADJUSTED:
+ sdm_primaries = ColorPrimaries_BT601_6_525;
+ break;
+ case HAL_DATASPACE_STANDARD_BT601_625:
+ case HAL_DATASPACE_STANDARD_BT601_625_UNADJUSTED:
+ sdm_primaries = ColorPrimaries_BT601_6_625;
+ break;
+ case HAL_DATASPACE_STANDARD_DCI_P3:
+ sdm_primaries = ColorPrimaries_DCIP3;
+ break;
+ case HAL_DATASPACE_STANDARD_BT2020:
+ sdm_primaries = ColorPrimaries_BT2020;
+ // android_dataspace_t doesnt support mastering display and light levels
+ // so retrieve it from metadata
+ use_color_metadata = true;
+ break;
+ default:
+ DLOGV_IF(kTagStrategy, "Unsupported Standard Request = %d", standard);
+ return false;
+ }
+ // TODO(user): Check transfer + primary combination
+
+ // Handle range
+ auto range = dataspace_ & HAL_DATASPACE_RANGE_MASK;
+ switch (range) {
+ case HAL_DATASPACE_RANGE_FULL:
+ sdm_range = Range_Full;
+ break;
+ case HAL_DATASPACE_RANGE_LIMITED:
+ sdm_range = Range_Limited;
+ break;
+ default:
+ DLOGV_IF(kTagStrategy, "Unsupported Range Request = %d", range);
+ break;
+ }
+ // If we got here, the value is supported, update the layer
+ layer_buffer->color_metadata.transfer = sdm_transfer;
+ layer_buffer->color_metadata.colorPrimaries = sdm_primaries;
+ layer_buffer->color_metadata.range = sdm_range;
+ }
+#endif
+
+ if (use_color_metadata) {
+ const private_handle_t *handle =
+ reinterpret_cast<const private_handle_t *>(layer_buffer->buffer_id);
+ if (sdm::SetCSC(handle, &layer_buffer->color_metadata) != kErrorNone) {
return false;
+ }
}
- // Handle standard
- auto standard = dataspace_ & HAL_DATASPACE_STANDARD_MASK;
- switch (standard) {
- case HAL_DATASPACE_STANDARD_BT709:
- sdm_primaries = ColorPrimaries_BT709_5;
- break;
- case HAL_DATASPACE_STANDARD_BT601_525:
- case HAL_DATASPACE_STANDARD_BT601_525_UNADJUSTED:
- sdm_primaries = ColorPrimaries_BT601_6_525;
- break;
- case HAL_DATASPACE_STANDARD_BT601_625:
- case HAL_DATASPACE_STANDARD_BT601_625_UNADJUSTED:
- sdm_primaries = ColorPrimaries_BT601_6_625;
- break;
- case HAL_DATASPACE_STANDARD_DCI_P3:
- sdm_primaries = ColorPrimaries_DCIP3;
- break;
- case HAL_DATASPACE_STANDARD_BT2020:
- sdm_primaries = ColorPrimaries_BT2020;
- break;
- default:
- return false;
- }
- // TODO(user): Check transfer + primary combination
-
- // Handle range
- auto range = dataspace_ & HAL_DATASPACE_RANGE_MASK;
- switch (range) {
- case HAL_DATASPACE_RANGE_FULL:
- sdm_range = Range_Full;
- break;
- case HAL_DATASPACE_RANGE_LIMITED:
- default:
- sdm_range = Range_Limited;
- break;
- }
-
- // If we got here, the value is supported, update the layer
- layer_buffer->color_metadata.transfer = sdm_transfer;
- layer_buffer->color_metadata.colorPrimaries = sdm_primaries;
- layer_buffer->color_metadata.range = sdm_range;
return true;
}
diff --git a/sdm/libs/hwc2/hwc_layers.h b/sdm/libs/hwc2/hwc_layers.h
index c566655..30fc362 100644
--- a/sdm/libs/hwc2/hwc_layers.h
+++ b/sdm/libs/hwc2/hwc_layers.h
@@ -85,7 +85,7 @@
void ResetGeometryChanges() { geometry_changes_ = GeometryChanges::kNone; }
void PushReleaseFence(int32_t fence);
int32_t PopReleaseFence(void);
- bool SupportedDataspace();
+ bool ValidateAndSetCSC();
bool SupportLocalConversion(ColorPrimaries working_primaries);
private:
diff --git a/sdm/libs/hwc2/hwc_session.cpp b/sdm/libs/hwc2/hwc_session.cpp
index a135be2..df15404 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>(
@@ -104,10 +165,13 @@
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();
DLOGE("Primary display type not recognized. Error = %d", error);
return -EINVAL;
@@ -132,6 +196,7 @@
}
if (status) {
+ g_hwc_uevent_.Register(nullptr);
CoreInterface::DestroyCore();
return status;
}
@@ -146,9 +211,6 @@
}
}
- std::thread uevent_thread(HWCUeventThread, this);
- uevent_thread_.swap(uevent_thread);
-
return 0;
}
@@ -167,10 +229,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) {
@@ -1081,8 +1140,6 @@
}
android::status_t HWCSession::SetColorModeOverride(const android::Parcel *input_parcel) {
- SCOPE_LOCK(locker_);
-
auto display = static_cast<hwc2_display_t >(input_parcel->readInt32());
auto mode = static_cast<android_color_mode_t>(input_parcel->readInt32());
auto device = static_cast<hwc2_device_t *>(this);
@@ -1149,8 +1206,6 @@
android::status_t HWCSession::QdcmCMDHandler(const android::Parcel *input_parcel,
android::Parcel *output_parcel) {
- SCOPE_LOCK(locker_);
-
int ret = 0;
int32_t *brightness_value = NULL;
uint32_t display_id(0);
@@ -1242,52 +1297,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 257296b..a224e8d 100644
--- a/sdm/libs/hwc2/hwc_tonemapper.cpp
+++ b/sdm/libs/hwc2/hwc_tonemapper.cpp
@@ -188,8 +188,8 @@
// then SDM marks them for SDE Composition because the cached FB layer gets displayed.
// GPU count will be 0 in this case. Try to use the existing tone-mapped frame buffer.
// No ToneMap/Blit is required. Just update the buffer & acquire fence fd of FB layer.
- if (!tone_map_sessions_.empty()) {
- ToneMapSession *fb_tone_map_session = tone_map_sessions_.at(fb_session_index_);
+ if (!tone_map_sessions_.empty() && (fb_session_index_ >= 0)) {
+ ToneMapSession *fb_tone_map_session = tone_map_sessions_.at(UINT32(fb_session_index_));
fb_tone_map_session->UpdateBuffer(-1 /* acquire_fence */, &layer->input_buffer);
fb_tone_map_session->layer_index_ = INT(i);
fb_tone_map_session->acquired_ = true;
@@ -197,7 +197,7 @@
}
}
error = AcquireToneMapSession(layer, &session_index);
- fb_session_index_ = session_index;
+ fb_session_index_ = INT(session_index);
break;
default:
error = AcquireToneMapSession(layer, &session_index);
@@ -261,6 +261,13 @@
} else {
delete session;
it = tone_map_sessions_.erase(it);
+ int deleted_session = INT(session_index);
+ // If FB tonemap session gets deleted, reset fb_session_index_, else update it.
+ if (deleted_session == fb_session_index_) {
+ fb_session_index_ = -1;
+ } else if (deleted_session < fb_session_index_) {
+ fb_session_index_--;
+ }
}
}
}
@@ -271,7 +278,7 @@
delete tone_map_sessions_.back();
tone_map_sessions_.pop_back();
}
- fb_session_index_ = 0;
+ fb_session_index_ = -1;
}
}
diff --git a/sdm/libs/hwc2/hwc_tonemapper.h b/sdm/libs/hwc2/hwc_tonemapper.h
index e2c8ef4..8bef3b1 100644
--- a/sdm/libs/hwc2/hwc_tonemapper.h
+++ b/sdm/libs/hwc2/hwc_tonemapper.h
@@ -118,7 +118,7 @@
HWCBufferAllocator *buffer_allocator_ = nullptr;
uint32_t dump_frame_count_ = 0;
uint32_t dump_frame_index_ = 0;
- uint32_t fb_session_index_ = 0;
+ int fb_session_index_ = -1;
};
} // namespace sdm
diff --git a/sdm/libs/utils/debug.cpp b/sdm/libs/utils/debug.cpp
index 60ce0ac..ee881ef 100644
--- a/sdm/libs/utils/debug.cpp
+++ b/sdm/libs/utils/debug.cpp
@@ -177,6 +177,13 @@
return (value == 1);
}
+bool Debug::IsSrcSplitPreferred() {
+ int value = 0;
+ debug_.debug_handler_->GetProperty("sdm.debug.prefersplit", &value);
+
+ return (value == 1);
+}
+
DisplayError Debug::GetMixerResolution(uint32_t *width, uint32_t *height) {
char value[64] = {};