hwc2: Default handling for dataspaces
CRs-Fixed: 2030917
Bug: 35985399
Change-Id: Idb4aa9914da2f843cf76160afb337365c3c39ea2
diff --git a/sdm/libs/hwc2/hwc_display.cpp b/sdm/libs/hwc2/hwc_display.cpp
index 30a1fee..0344199 100644
--- a/sdm/libs/hwc2/hwc_display.cpp
+++ b/sdm/libs/hwc2/hwc_display.cpp
@@ -61,6 +61,24 @@
}
}
+// This weight function is needed because the color primaries are not sorted by gamut size
+static ColorPrimaries WidestPrimaries(ColorPrimaries p1, ColorPrimaries p2) {
+ int weight = 10;
+ int lp1 = p1, lp2 = p2;
+ // TODO(user) add weight to other wide gamut primaries
+ if (lp1 == ColorPrimaries_BT2020) {
+ lp1 *= weight;
+ }
+ if (lp1 == ColorPrimaries_BT2020) {
+ lp2 *= weight;
+ }
+ if (lp1 >= lp2) {
+ return p1;
+ } else {
+ return p2;
+ }
+}
+
HWCColorMode::HWCColorMode(DisplayInterface *display_intf) : display_intf_(display_intf) {}
HWC2::Error HWCColorMode::Init() {
@@ -331,10 +349,12 @@
return HWC2::Error::None;
}
+
void HWCDisplay::BuildLayerStack() {
layer_stack_ = LayerStack();
display_rect_ = LayerRect();
metadata_refresh_rate_ = 0;
+ auto working_primaries = ColorPrimaries_BT709_5;
// Add one layer for fb target
// TODO(user): Add blit target layers
@@ -347,6 +367,14 @@
layer->flags.solid_fill = true;
}
+ if (!hwc_layer->SupportedDataspace()) {
+ layer->flags.skip = true;
+ DLOGW_IF(kTagStrategy, "Unsupported dataspace: 0x%x", hwc_layer->GetLayerDataspace());
+ }
+
+ working_primaries = WidestPrimaries(working_primaries,
+ layer->input_buffer.color_metadata.colorPrimaries);
+
// set default composition as GPU for SDM
layer->composition = kCompositionGPU;
@@ -425,6 +453,19 @@
layer_stack_.layers.push_back(layer);
}
+
+
+ for (auto hwc_layer : layer_set_) {
+ auto layer = hwc_layer->GetSDMLayer();
+ if (layer->input_buffer.color_metadata.colorPrimaries != working_primaries &&
+ !hwc_layer->SupportLocalConversion(working_primaries)) {
+ layer->flags.skip = true;
+ }
+ if (layer->flags.skip) {
+ layer_stack_.flags.skip_present = true;
+ }
+ }
+
// TODO(user): Set correctly when SDM supports geometry_changes as bitmask
layer_stack_.flags.geometry_changed = UINT32(geometry_changes_ > 0);
// Append client target to the layer stack
diff --git a/sdm/libs/hwc2/hwc_layers.cpp b/sdm/libs/hwc2/hwc_layers.cpp
index aec44ad..a710543 100644
--- a/sdm/libs/hwc2/hwc_layers.cpp
+++ b/sdm/libs/hwc2/hwc_layers.cpp
@@ -221,8 +221,10 @@
}
HWC2::Error HWCLayer::SetLayerDataspace(int32_t dataspace) {
- // TODO(user): Implement later
- geometry_changes_ |= kDataspace;
+ if (dataspace_ != dataspace) {
+ geometry_changes_ |= kDataspace;
+ dataspace_ = dataspace;
+ }
return HWC2::Error::None;
}
@@ -491,8 +493,12 @@
DisplayError HWCLayer::SetMetaData(const private_handle_t *pvt_handle, Layer *layer) {
LayerBuffer *layer_buffer = &layer->input_buffer;
- if (sdm::SetCSC(pvt_handle, &layer_buffer->color_metadata) != kErrorNone) {
- return kErrorNotSupported;
+
+ // Only use color metadata if Android framework metadata is not set
+ if (dataspace_ == HAL_DATASPACE_UNKNOWN) {
+ if (sdm::SetCSC(pvt_handle, &layer_buffer->color_metadata) != kErrorNone) {
+ return kErrorNotSupported;
+ }
}
private_handle_t *handle = const_cast<private_handle_t *>(pvt_handle);
@@ -542,6 +548,121 @@
return kErrorNone;
}
+
+
+bool HWCLayer::SupportLocalConversion(ColorPrimaries working_primaries) {
+ if (layer_->input_buffer.color_metadata.colorPrimaries <= ColorPrimaries_BT601_6_525 &&
+ working_primaries <= ColorPrimaries_BT601_6_525) {
+ return true;
+ }
+ return false;
+}
+
+bool HWCLayer::SupportedDataspace() {
+ if (dataspace_ == HAL_DATASPACE_UNKNOWN) {
+ // Pick values from metadata
+ return true;
+ }
+
+ // Map deprecated dataspace values to appropriate
+ // new enums
+ if (dataspace_ & 0xffff) {
+ switch (dataspace_ & 0xffff) {
+ case HAL_DATASPACE_SRGB:
+ dataspace_ = HAL_DATASPACE_V0_SRGB;
+ break;
+ case HAL_DATASPACE_JFIF:
+ dataspace_ = HAL_DATASPACE_V0_JFIF;
+ break;
+ case HAL_DATASPACE_SRGB_LINEAR:
+ dataspace_ = HAL_DATASPACE_V0_SRGB_LINEAR;
+ break;
+ case HAL_DATASPACE_BT601_625:
+ dataspace_ = HAL_DATASPACE_V0_BT601_625;
+ break;
+ case HAL_DATASPACE_BT601_525:
+ dataspace_ = HAL_DATASPACE_V0_BT601_525;
+ break;
+ case HAL_DATASPACE_BT709:
+ dataspace_ = HAL_DATASPACE_V0_BT709;
+ break;
+ default:
+ // unknown legacy dataspace
+ DLOGE("Unsupported dataspace type %d", dataspace_);
+ return false;
+ }
+ }
+
+ LayerBuffer *layer_buffer = &layer_->input_buffer;
+
+ GammaTransfer sdm_transfer = {};
+ ColorPrimaries sdm_primaries = {};
+ ColorRange sdm_range = {};
+
+ auto transfer = (dataspace_ & HAL_DATASPACE_TRANSFER_MASK) >> HAL_DATASPACE_TRANSFER_SHIFT;
+ // 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;
+ default:
+ return false;
+ }
+
+ // Handle standard
+ auto standard = (dataspace_ & HAL_DATASPACE_STANDARD_MASK) >> HAL_DATASPACE_STANDARD_SHIFT;
+ 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_BT2020:
+ sdm_primaries = ColorPrimaries_BT2020;
+ break;
+ default:
+ return false;
+ }
+ // TODO(user): Check transfer + primary combination
+
+ // Handle range
+ auto range = (dataspace_ & HAL_DATASPACE_RANGE_MASK) >> HAL_DATASPACE_RANGE_SHIFT;
+ 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;
+}
+
+
uint32_t HWCLayer::RoundToStandardFPS(float fps) {
static const uint32_t standard_fps[4] = {24, 30, 48, 60};
uint32_t frame_rate = (uint32_t)(fps);
diff --git a/sdm/libs/hwc2/hwc_layers.h b/sdm/libs/hwc2/hwc_layers.h
index 58a45ae..bc3d84d 100644
--- a/sdm/libs/hwc2/hwc_layers.h
+++ b/sdm/libs/hwc2/hwc_layers.h
@@ -78,10 +78,13 @@
HWC2::Composition GetClientRequestedCompositionType() { return client_requested_; }
void UpdateClientCompositionType(HWC2::Composition type) { client_requested_ = type; }
HWC2::Composition GetDeviceSelectedCompositionType() { return device_selected_; }
+ int32_t GetLayerDataspace() { return dataspace_; }
uint32_t GetGeometryChanges() { return geometry_changes_; }
void ResetGeometryChanges() { geometry_changes_ = GeometryChanges::kNone; }
void PushReleaseFence(int32_t fence);
int32_t PopReleaseFence(void);
+ bool SupportedDataspace();
+ bool SupportLocalConversion(ColorPrimaries working_primaries);
private:
Layer *layer_ = nullptr;
@@ -92,6 +95,7 @@
std::queue<int32_t> release_fences_;
int ion_fd_ = -1;
HWCBufferAllocator *buffer_allocator_ = NULL;
+ int32_t dataspace_ = HAL_DATASPACE_UNKNOWN;
// Composition requested by client(SF)
HWC2::Composition client_requested_ = HWC2::Composition::Device;