Merge branch drm-hwcomposer:main into hdr-upstream
diff --git a/compositor/ColorInfo.h b/compositor/ColorInfo.h
new file mode 100644
index 0000000..1afda07
--- /dev/null
+++ b/compositor/ColorInfo.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <cstdint>
+
+enum class Colorspace : int32_t {
+ kDefault,
+ kSmpte170MYcc,
+ kBt709Ycc,
+ kXvycc601,
+ kXvycc709,
+ kSycc601,
+ kOpycc601,
+ kOprgb,
+ kBt2020Cycc,
+ kBt2020Rgb,
+ kBt2020Ycc,
+ kDciP3RgbD65,
+ kDciP3RgbTheater,
+ kRgbWideFixed,
+ kRgbWideFloat,
+ kBt601Ycc,
+};
diff --git a/drm/DrmAtomicStateManager.cpp b/drm/DrmAtomicStateManager.cpp
index 537f819..bb26189 100644
--- a/drm/DrmAtomicStateManager.cpp
+++ b/drm/DrmAtomicStateManager.cpp
@@ -139,6 +139,17 @@
return -EINVAL;
}
+ if (args.colorspace && connector->GetColorspaceProperty()) {
+ if (!connector->GetColorspaceProperty()
+ .AtomicSet(*pset, connector->GetColorspacePropertyValue(*args.colorspace)))
+ return -EINVAL;
+ }
+
+ if (args.content_type && connector->GetContentTypeProperty()) {
+ if (!connector->GetContentTypeProperty().AtomicSet(*pset, *args.content_type))
+ return -EINVAL;
+ }
+
auto unused_planes = new_frame_state.used_planes;
if (args.composition) {
diff --git a/drm/DrmAtomicStateManager.h b/drm/DrmAtomicStateManager.h
index 923927d..c8736f2 100644
--- a/drm/DrmAtomicStateManager.h
+++ b/drm/DrmAtomicStateManager.h
@@ -21,6 +21,7 @@
#include <memory>
#include <optional>
+#include "compositor/ColorInfo.h"
#include "compositor/DrmKmsPlan.h"
#include "compositor/LayerData.h"
#include "drm/DrmPlane.h"
@@ -36,6 +37,8 @@
std::optional<bool> active;
std::shared_ptr<DrmKmsPlan> composition;
std::shared_ptr<drm_color_ctm> color_matrix;
+ std::optional<Colorspace> colorspace;
+ std::optional<int32_t> content_type;
std::shared_ptr<DrmFbIdHandle> writeback_fb;
SharedFd writeback_release_fence;
diff --git a/drm/DrmConnector.cpp b/drm/DrmConnector.cpp
index e459fe7..8b92407 100644
--- a/drm/DrmConnector.cpp
+++ b/drm/DrmConnector.cpp
@@ -42,22 +42,21 @@
constexpr size_t kTypesCount = 21;
-static bool GetOptionalConnectorProperty(const DrmDevice &dev,
- const DrmConnector &connector,
- const char *prop_name,
- DrmProperty *property) {
- return dev.GetProperty(connector.GetId(), DRM_MODE_OBJECT_CONNECTOR,
- prop_name, property) == 0;
-}
+auto DrmConnector::GetConnectorProperty(const char *prop_name,
+ DrmProperty *property,
+ bool is_optional) -> bool {
+ auto err = drm_->GetProperty(GetId(), DRM_MODE_OBJECT_CONNECTOR, prop_name,
+ property);
+ if (err == 0)
+ return true;
-static bool GetConnectorProperty(const DrmDevice &dev,
- const DrmConnector &connector,
- const char *prop_name, DrmProperty *property) {
- if (!GetOptionalConnectorProperty(dev, connector, prop_name, property)) {
- ALOGE("Could not get %s property\n", prop_name);
- return false;
+ if (is_optional) {
+ ALOGV("Could not get optional %s property from connector %d", prop_name,
+ GetId());
+ } else {
+ ALOGE("Could not get %s property from connector %d", prop_name, GetId());
}
- return true;
+ return false;
}
auto DrmConnector::CreateInstance(DrmDevice &dev, uint32_t connector_id,
@@ -72,28 +71,75 @@
auto c = std::unique_ptr<DrmConnector>(
new DrmConnector(std::move(conn), &dev, index));
- if (!GetConnectorProperty(dev, *c, "DPMS", &c->dpms_property_) ||
- !GetConnectorProperty(dev, *c, "CRTC_ID", &c->crtc_id_property_)) {
- return {};
- }
-
- c->UpdateEdidProperty();
-
- if (c->IsWriteback() &&
- (!GetConnectorProperty(dev, *c, "WRITEBACK_PIXEL_FORMATS",
- &c->writeback_pixel_formats_) ||
- !GetConnectorProperty(dev, *c, "WRITEBACK_FB_ID",
- &c->writeback_fb_id_) ||
- !GetConnectorProperty(dev, *c, "WRITEBACK_OUT_FENCE_PTR",
- &c->writeback_out_fence_))) {
+ if (!c->Init()) {
+ ALOGE("Failed to initialize connector %d", connector_id);
return {};
}
return c;
}
+auto DrmConnector::Init()-> bool {
+ if (!GetConnectorProperty("DPMS", &dpms_property_) ||
+ !GetConnectorProperty("CRTC_ID", &crtc_id_property_)) {
+ return false;
+ }
+
+ UpdateEdidProperty();
+
+ if (IsWriteback() &&
+ (!GetConnectorProperty("WRITEBACK_PIXEL_FORMATS",
+ &writeback_pixel_formats_) ||
+ !GetConnectorProperty("WRITEBACK_FB_ID", &writeback_fb_id_) ||
+ !GetConnectorProperty("WRITEBACK_OUT_FENCE_PTR",
+ &writeback_out_fence_))) {
+ return false;
+ }
+
+ if (GetConnectorProperty("Colorspace", &colorspace_property_,
+ /*is_optional=*/true)) {
+ colorspace_property_.AddEnumToMap("Default", Colorspace::kDefault,
+ colorspace_enum_map_);
+ colorspace_property_.AddEnumToMap("SMPTE_170M_YCC", Colorspace::kSmpte170MYcc,
+ colorspace_enum_map_);
+ colorspace_property_.AddEnumToMap("BT709_YCC", Colorspace::kBt709Ycc,
+ colorspace_enum_map_);
+ colorspace_property_.AddEnumToMap("XVYCC_601", Colorspace::kXvycc601,
+ colorspace_enum_map_);
+ colorspace_property_.AddEnumToMap("XVYCC_709", Colorspace::kXvycc709,
+ colorspace_enum_map_);
+ colorspace_property_.AddEnumToMap("SYCC_601", Colorspace::kSycc601,
+ colorspace_enum_map_);
+ colorspace_property_.AddEnumToMap("opYCC_601", Colorspace::kOpycc601,
+ colorspace_enum_map_);
+ colorspace_property_.AddEnumToMap("opRGB", Colorspace::kOprgb,
+ colorspace_enum_map_);
+ colorspace_property_.AddEnumToMap("BT2020_CYCC", Colorspace::kBt2020Cycc,
+ colorspace_enum_map_);
+ colorspace_property_.AddEnumToMap("BT2020_RGB", Colorspace::kBt2020Rgb,
+ colorspace_enum_map_);
+ colorspace_property_.AddEnumToMap("BT2020_YCC", Colorspace::kBt2020Ycc,
+ colorspace_enum_map_);
+ colorspace_property_.AddEnumToMap("DCI-P3_RGB_D65", Colorspace::kDciP3RgbD65,
+ colorspace_enum_map_);
+ colorspace_property_.AddEnumToMap("DCI-P3_RGB_Theater", Colorspace::kDciP3RgbTheater,
+ colorspace_enum_map_);
+ colorspace_property_.AddEnumToMap("RGB_WIDE_FIXED", Colorspace::kRgbWideFixed,
+ colorspace_enum_map_);
+ colorspace_property_.AddEnumToMap("RGB_WIDE_FLOAT", Colorspace::kRgbWideFloat,
+ colorspace_enum_map_);
+ colorspace_property_.AddEnumToMap("BT601_YCC", Colorspace::kBt601Ycc,
+ colorspace_enum_map_);
+ }
+
+ GetConnectorProperty("content type", &content_type_property_,
+ /*is_optional=*/true);
+
+ return true;
+}
+
int DrmConnector::UpdateEdidProperty() {
- return GetOptionalConnectorProperty(*drm_, *this, "EDID", &edid_property_)
+ return GetConnectorProperty("EDID", &edid_property_, /*is_optional=*/true)
? 0
: -EINVAL;
}
diff --git a/drm/DrmConnector.h b/drm/DrmConnector.h
index 018c615..8063fd8 100644
--- a/drm/DrmConnector.h
+++ b/drm/DrmConnector.h
@@ -27,6 +27,8 @@
#include "DrmProperty.h"
#include "DrmUnique.h"
+#include "compositor/ColorInfo.h"
+
namespace android {
class DrmDevice;
@@ -94,6 +96,18 @@
return edid_property_;
}
+ auto &GetColorspaceProperty() const {
+ return colorspace_property_;
+ }
+
+ auto GetColorspacePropertyValue(Colorspace c) {
+ return colorspace_enum_map_[c];
+ }
+
+ auto &GetContentTypeProperty() const {
+ return content_type_property_;
+ }
+
auto &GetWritebackFbIdProperty() const {
return writeback_fb_id_;
}
@@ -123,6 +137,10 @@
DrmModeConnectorUnique connector_;
DrmDevice *const drm_;
+ auto Init() -> bool;
+ auto GetConnectorProperty(const char *prop_name, DrmProperty *property,
+ bool is_optional = false) -> bool;
+
const uint32_t index_in_res_array_;
std::vector<DrmMode> modes_;
@@ -130,8 +148,13 @@
DrmProperty dpms_property_;
DrmProperty crtc_id_property_;
DrmProperty edid_property_;
+ DrmProperty colorspace_property_;
+ DrmProperty content_type_property_;
+
DrmProperty writeback_pixel_formats_;
DrmProperty writeback_fb_id_;
DrmProperty writeback_out_fence_;
+
+ std::map<Colorspace, uint64_t> colorspace_enum_map_;
};
} // namespace android
diff --git a/hwc2_device/HwcDisplay.cpp b/hwc2_device/HwcDisplay.cpp
index 9a9761b..7772175 100644
--- a/hwc2_device/HwcDisplay.cpp
+++ b/hwc2_device/HwcDisplay.cpp
@@ -73,7 +73,7 @@
}
}
-void HwcDisplay::SetColorMarixToIdentity() {
+void HwcDisplay::SetColorMatrixToIdentity() {
color_matrix_ = std::make_shared<drm_color_ctm>();
for (int i = 0; i < kCtmCols; i++) {
for (int j = 0; j < kCtmRows; j++) {
@@ -189,7 +189,7 @@
client_layer_.SetLayerBlendMode(HWC2_BLEND_MODE_PREMULTIPLIED);
- SetColorMarixToIdentity();
+ SetColorMatrixToIdentity();
return HWC2::Error::None;
}
@@ -462,6 +462,8 @@
}
a_args.color_matrix = color_matrix_;
+ a_args.content_type = content_type_;
+ a_args.colorspace = colorspace_;
uint32_t prev_vperiod_ns = 0;
GetDisplayVsyncPeriod(&prev_vperiod_ns);
@@ -671,11 +673,35 @@
}
HWC2::Error HwcDisplay::SetColorMode(int32_t mode) {
- if (mode < HAL_COLOR_MODE_NATIVE || mode > HAL_COLOR_MODE_BT2100_HLG)
+ /* Maps to the Colorspace DRM connector property:
+ * https://elixir.bootlin.com/linux/v6.11/source/include/drm/drm_connector.h#L538
+ */
+ if (mode < HAL_COLOR_MODE_NATIVE || mode > HAL_COLOR_MODE_DISPLAY_P3)
return HWC2::Error::BadParameter;
- if (mode != HAL_COLOR_MODE_NATIVE)
- return HWC2::Error::Unsupported;
+ switch (mode) {
+ case HAL_COLOR_MODE_NATIVE:
+ colorspace_ = Colorspace::kDefault;
+ break;
+ case HAL_COLOR_MODE_STANDARD_BT601_625:
+ case HAL_COLOR_MODE_STANDARD_BT601_625_UNADJUSTED:
+ case HAL_COLOR_MODE_STANDARD_BT601_525:
+ case HAL_COLOR_MODE_STANDARD_BT601_525_UNADJUSTED:
+ // The DP spec does not say whether this is the 525 or the 625 line version.
+ colorspace_ = Colorspace::kBt601Ycc;
+ break;
+ case HAL_COLOR_MODE_STANDARD_BT709:
+ case HAL_COLOR_MODE_SRGB:
+ colorspace_ = Colorspace::kBt709Ycc;
+ break;
+ case HAL_COLOR_MODE_DCI_P3:
+ case HAL_COLOR_MODE_DISPLAY_P3:
+ colorspace_ = Colorspace::kDciP3RgbD65;
+ break;
+ case HAL_COLOR_MODE_ADOBE_RGB:
+ default:
+ return HWC2::Error::Unsupported;
+ }
color_mode_ = mode;
return HWC2::Error::None;
@@ -683,6 +709,15 @@
#include <xf86drmMode.h>
+static uint64_t To3132FixPt(float in) {
+ constexpr uint64_t kSignMask = (1ULL << 63);
+ constexpr uint64_t kValueMask = ~(1ULL << 63);
+ constexpr auto kValueScale = static_cast<float>(1ULL << 32);
+ if (in < 0)
+ return (static_cast<uint64_t>(-in * kValueScale) & kValueMask) | kSignMask;
+ return static_cast<uint64_t>(in * kValueScale) & kValueMask;
+}
+
HWC2::Error HwcDisplay::SetColorTransform(const float *matrix, int32_t hint) {
if (hint < HAL_COLOR_TRANSFORM_IDENTITY ||
hint > HAL_COLOR_TRANSFORM_CORRECT_TRITANOPIA)
@@ -701,17 +736,40 @@
switch (color_transform_hint_) {
case HAL_COLOR_TRANSFORM_IDENTITY:
- SetColorMarixToIdentity();
+ SetColorMatrixToIdentity();
break;
case HAL_COLOR_TRANSFORM_ARBITRARY_MATRIX:
+ // Without HW support, we cannot correctly process matrices with an offset.
+ for (int i = 12; i < 14; i++) {
+ if (matrix[i] != 0.F)
+ return HWC2::Error::Unsupported;
+ }
+
+ /* HAL provides a 4x4 float type matrix:
+ * | 0 1 2 3|
+ * | 4 5 6 7|
+ * | 8 9 10 11|
+ * |12 13 14 15|
+ *
+ * R_out = R*0 + G*4 + B*8 + 12
+ * G_out = R*1 + G*5 + B*9 + 13
+ * B_out = R*2 + G*6 + B*10 + 14
+ *
+ * DRM expects a 3x3 s31.32 fixed point matrix:
+ * out matrix in
+ * |R| |0 1 2| |R|
+ * |G| = |3 4 5| x |G|
+ * |B| |6 7 8| |B|
+ *
+ * R_out = R*0 + G*1 + B*2
+ * G_out = R*3 + G*4 + B*5
+ * B_out = R*6 + G*7 + B*8
+ */
color_matrix_ = std::make_shared<drm_color_ctm>();
- /* DRM expects a 3x3 matrix, but the HAL provides a 4x4 matrix. */
for (int i = 0; i < kCtmCols; i++) {
for (int j = 0; j < kCtmRows; j++) {
constexpr int kInCtmRows = 4;
- /* HAL matrix type is float, but DRM expects a s31.32 fix point */
- auto value = uint64_t(matrix[i * kInCtmRows + j] * float(1ULL << 32));
- color_matrix_->matrix[i * kCtmRows + j] = value;
+ color_matrix_->matrix[i * kCtmRows + j] = To3132FixPt(matrix[j * kInCtmRows + i]);
}
}
break;
@@ -916,12 +974,13 @@
}
HWC2::Error HwcDisplay::SetContentType(int32_t contentType) {
- if (contentType != HWC2_CONTENT_TYPE_NONE)
- return HWC2::Error::Unsupported;
-
- /* TODO: Map to the DRM Connector property:
- * https://elixir.bootlin.com/linux/v5.4-rc5/source/drivers/gpu/drm/drm_connector.c#L809
+ /* Maps exactly to the content_type DRM connector property:
+ * https://elixir.bootlin.com/linux/v6.11/source/include/uapi/drm/drm_mode.h#L107
*/
+ if (contentType < HWC2_CONTENT_TYPE_NONE || contentType > HWC2_CONTENT_TYPE_GAME)
+ return HWC2::Error::BadParameter;
+
+ content_type_ = contentType;
return HWC2::Error::None;
}
@@ -1016,16 +1075,12 @@
intent > HAL_RENDER_INTENT_TONE_MAP_ENHANCE)
return HWC2::Error::BadParameter;
- if (mode < HAL_COLOR_MODE_NATIVE || mode > HAL_COLOR_MODE_BT2100_HLG)
- return HWC2::Error::BadParameter;
-
- if (mode != HAL_COLOR_MODE_NATIVE)
- return HWC2::Error::Unsupported;
-
if (intent != HAL_RENDER_INTENT_COLORIMETRIC)
return HWC2::Error::Unsupported;
- color_mode_ = mode;
+ auto err = SetColorMode(mode);
+ if (err != HWC2::Error::None) return err;
+
return HWC2::Error::None;
}
diff --git a/hwc2_device/HwcDisplay.h b/hwc2_device/HwcDisplay.h
index 6bc3b6b..c568a73 100644
--- a/hwc2_device/HwcDisplay.h
+++ b/hwc2_device/HwcDisplay.h
@@ -23,6 +23,7 @@
#include <sstream>
#include "HwcDisplayConfigs.h"
+#include "compositor/ColorInfo.h"
#include "compositor/FlatteningController.h"
#include "compositor/LayerData.h"
#include "drm/DrmAtomicStateManager.h"
@@ -233,6 +234,8 @@
static constexpr int kCtmCols = 3;
std::shared_ptr<drm_color_ctm> color_matrix_;
android_color_transform_t color_transform_hint_{};
+ int32_t content_type_{};
+ Colorspace colorspace_{};
std::shared_ptr<DrmKmsPlan> current_plan_;
@@ -241,7 +244,7 @@
Stats prev_stats_;
std::string DumpDelta(HwcDisplay::Stats delta);
- void SetColorMarixToIdentity();
+ void SetColorMatrixToIdentity();
HWC2::Error Init();