drm_hwcomposer: Add support for color encoding and range properties
Starting from the linux-v4.17, the DRM module has support for different
non-RGB color encodings that are controlled through plane-specific
COLOR_ENCODING and COLOR_RANGE properties.
This patch creates a matching between the HWC layer dataspace which is
supported by DRM driver and DRM plane properties.
Signed-off-by: Matvii Zorin <matvii.zorin@globallogic.com>
diff --git a/DrmHwcTwo.cpp b/DrmHwcTwo.cpp
index 93b6fa7..b5b460e 100644
--- a/DrmHwcTwo.cpp
+++ b/DrmHwcTwo.cpp
@@ -1099,6 +1099,7 @@
layer->alpha = static_cast<uint16_t>(65535.0f * alpha_ + 0.5f);
layer->SetSourceCrop(source_crop_);
layer->SetTransform(static_cast<int32_t>(transform_));
+ layer->dataspace = dataspace_;
}
void DrmHwcTwo::HandleDisplayHotplug(hwc2_display_t displayid, int state) {
diff --git a/compositor/DrmDisplayCompositor.cpp b/compositor/DrmDisplayCompositor.cpp
index ba0d56b..3ae42ef 100644
--- a/compositor/DrmDisplayCompositor.cpp
+++ b/compositor/DrmDisplayCompositor.cpp
@@ -342,6 +342,8 @@
uint64_t rotation = 0;
uint64_t alpha = 0xFFFF;
uint64_t blend;
+ uint64_t color_encoding = UINT64_MAX;
+ uint64_t color_range = UINT64_MAX;
if (comp_plane.type() != DrmCompositionPlane::Type::kDisable) {
if (source_layers.size() > 1) {
@@ -427,6 +429,45 @@
break;
}
}
+
+ if (plane->color_encoding_propery().id()) {
+ switch (layer.dataspace & HAL_DATASPACE_STANDARD_MASK) {
+ case HAL_DATASPACE_STANDARD_BT709:
+ std::tie(color_encoding,
+ ret) = plane->color_encoding_propery()
+ .GetEnumValueWithName("ITU-R BT.709 YCbCr");
+ break;
+ case HAL_DATASPACE_STANDARD_BT601_625:
+ case HAL_DATASPACE_STANDARD_BT601_625_UNADJUSTED:
+ case HAL_DATASPACE_STANDARD_BT601_525:
+ case HAL_DATASPACE_STANDARD_BT601_525_UNADJUSTED:
+ std::tie(color_encoding,
+ ret) = plane->color_encoding_propery()
+ .GetEnumValueWithName("ITU-R BT.601 YCbCr");
+ break;
+ case HAL_DATASPACE_STANDARD_BT2020:
+ case HAL_DATASPACE_STANDARD_BT2020_CONSTANT_LUMINANCE:
+ std::tie(color_encoding,
+ ret) = plane->color_encoding_propery()
+ .GetEnumValueWithName("ITU-R BT.2020 YCbCr");
+ break;
+ }
+ }
+
+ if (plane->color_range_property().id()) {
+ switch (layer.dataspace & HAL_DATASPACE_RANGE_MASK) {
+ case HAL_DATASPACE_RANGE_FULL:
+ std::tie(color_range,
+ ret) = plane->color_range_property()
+ .GetEnumValueWithName("YCbCr full range");
+ break;
+ case HAL_DATASPACE_RANGE_LIMITED:
+ std::tie(color_range,
+ ret) = plane->color_range_property()
+ .GetEnumValueWithName("YCbCr limited range");
+ break;
+ }
+ }
}
// Disable the plane if there's no framebuffer
@@ -509,6 +550,28 @@
break;
}
}
+
+ if (plane->color_encoding_propery().id() && color_encoding != UINT64_MAX) {
+ ret = drmModeAtomicAddProperty(pset, plane->id(),
+ plane->color_encoding_propery().id(),
+ color_encoding) < 0;
+ if (ret) {
+ ALOGE("Failed to add COLOR_ENCODING property %d to plane %d",
+ plane->color_encoding_propery().id(), plane->id());
+ break;
+ }
+ }
+
+ if (plane->color_range_property().id() && color_range != UINT64_MAX) {
+ ret = drmModeAtomicAddProperty(pset, plane->id(),
+ plane->color_range_property().id(),
+ color_range) < 0;
+ if (ret) {
+ ALOGE("Failed to add COLOR_RANGE property %d to plane %d",
+ plane->color_range_property().id(), plane->id());
+ break;
+ }
+ }
}
if (!ret) {
diff --git a/drm/DrmPlane.cpp b/drm/DrmPlane.cpp
index f994252..65bd8be 100644
--- a/drm/DrmPlane.cpp
+++ b/drm/DrmPlane.cpp
@@ -17,6 +17,7 @@
#define LOG_TAG "hwc-drm-plane"
#include "DrmPlane.h"
+#include "bufferinfo/BufferInfoGetter.h"
#include <errno.h>
#include <log/log.h>
@@ -141,6 +142,17 @@
if (ret)
ALOGI("Could not get IN_FENCE_FD property");
+ if (HasNonRgbFormat()) {
+ ret = drm_->GetPlaneProperty(*this, "COLOR_ENCODING",
+ &color_encoding_propery_);
+ if (ret)
+ ALOGI("Could not get COLOR_ENCODING property");
+
+ ret = drm_->GetPlaneProperty(*this, "COLOR_RANGE", &color_range_property_);
+ if (ret)
+ ALOGI("Could not get COLOR_RANGE property");
+ }
+
return 0;
}
@@ -161,6 +173,13 @@
std::end(formats_);
}
+bool DrmPlane::HasNonRgbFormat() const {
+ return std::find_if_not(std::begin(formats_), std::end(formats_),
+ [](uint32_t format) {
+ return BufferInfoGetter::IsDrmFormatRgb(format);
+ }) != std::end(formats_);
+}
+
const DrmProperty &DrmPlane::crtc_property() const {
return crtc_property_;
}
@@ -220,4 +239,12 @@
const DrmProperty &DrmPlane::in_fence_fd_property() const {
return in_fence_fd_property_;
}
+
+const DrmProperty &DrmPlane::color_encoding_propery() const {
+ return color_encoding_propery_;
+}
+
+const DrmProperty &DrmPlane::color_range_property() const {
+ return color_range_property_;
+}
} // namespace android
diff --git a/drm/DrmPlane.h b/drm/DrmPlane.h
index 16731a8..7a915cc 100644
--- a/drm/DrmPlane.h
+++ b/drm/DrmPlane.h
@@ -44,6 +44,7 @@
uint32_t type() const;
bool IsFormatSupported(uint32_t format) const;
+ bool HasNonRgbFormat() const;
const DrmProperty &crtc_property() const;
const DrmProperty &fb_property() const;
@@ -60,6 +61,8 @@
const DrmProperty &alpha_property() const;
const DrmProperty &blend_property() const;
const DrmProperty &in_fence_fd_property() const;
+ const DrmProperty &color_encoding_propery() const;
+ const DrmProperty &color_range_property() const;
private:
DrmDevice *drm_;
@@ -86,6 +89,8 @@
DrmProperty alpha_property_;
DrmProperty blend_property_;
DrmProperty in_fence_fd_property_;
+ DrmProperty color_encoding_propery_;
+ DrmProperty color_range_property_;
};
} // namespace android
diff --git a/include/drmhwcomposer.h b/include/drmhwcomposer.h
index 0706ae5..1007144 100644
--- a/include/drmhwcomposer.h
+++ b/include/drmhwcomposer.h
@@ -136,6 +136,7 @@
uint16_t alpha = 0xffff;
hwc_frect_t source_crop;
hwc_rect_t display_frame;
+ android_dataspace_t dataspace;
UniqueFd acquire_fence;
OutputFd release_fence;