drm_hwcomposer: Add support for pixel blend mode property
The upstream version of pixel blend mode property will be added
to the DRM core. So added support for pixel blend mode property
to the DrmPlane.
Created ValidatePlane() function in Planner to do the blend check,
and also moved rotation and plane alpha property check there.
Fixed the Emplace() call in platformhisi.cpp as was done with the
other planner implementations.
Change-Id: I7e6714699cf7c222a83de472060d4625e1e6945a
Reviewed-by: Sean Paul <seanpaul@chromium.org>
Reviewed-by: Liviu Dudau <liviu.dudau@arm.com>
Signed-off-by: Lowry Li <lowry.li@arm.com>
Tested-by: John Stultz <john.stultz@linaro.org>
diff --git a/drmdisplaycompositor.cpp b/drmdisplaycompositor.cpp
index f479f10..cd6d4b2 100644
--- a/drmdisplaycompositor.cpp
+++ b/drmdisplaycompositor.cpp
@@ -316,6 +316,7 @@
hwc_frect_t source_crop;
uint64_t rotation = 0;
uint64_t alpha = 0xFFFF;
+ uint64_t blend;
if (comp_plane.type() != DrmCompositionPlane::Type::kDisable) {
if (source_layers.size() > 1) {
@@ -338,8 +339,25 @@
fence_fd = layer.acquire_fence.get();
display_frame = layer.display_frame;
source_crop = layer.source_crop;
- if (layer.blending == DrmHwcBlending::kPreMult)
- alpha = layer.alpha;
+ alpha = layer.alpha;
+
+ if (plane->blend_property().id()) {
+ switch (layer.blending) {
+ case DrmHwcBlending::kPreMult:
+ std::tie(blend, ret) = plane->blend_property().GetEnumValueWithName(
+ "Pre-multiplied");
+ break;
+ case DrmHwcBlending::kCoverage:
+ std::tie(blend, ret) = plane->blend_property().GetEnumValueWithName(
+ "Coverage");
+ break;
+ case DrmHwcBlending::kNone:
+ default:
+ std::tie(blend, ret) = plane->blend_property().GetEnumValueWithName(
+ "None");
+ break;
+ }
+ }
rotation = 0;
if (layer.transform & DrmHwcTransform::kFlipH)
@@ -382,20 +400,6 @@
continue;
}
- // TODO: Once we have atomic test, this should fall back to GL
- if (rotation != DRM_MODE_ROTATE_0 && plane->rotation_property().id() == 0) {
- ALOGV("Rotation is not supported on plane %d", plane->id());
- ret = -EINVAL;
- break;
- }
-
- // TODO: Once we have atomic test, this should fall back to GL
- if (alpha != 0xFFFF && plane->alpha_property().id() == 0) {
- ALOGV("Alpha is not supported on plane %d", plane->id());
- ret = -EINVAL;
- break;
- }
-
ret = drmModeAtomicAddProperty(pset, plane->id(),
plane->crtc_property().id(), crtc->id()) < 0;
ret |= drmModeAtomicAddProperty(pset, plane->id(),
@@ -453,6 +457,16 @@
break;
}
}
+
+ if (plane->blend_property().id()) {
+ ret = drmModeAtomicAddProperty(pset, plane->id(),
+ plane->blend_property().id(), blend) < 0;
+ if (ret) {
+ ALOGE("Failed to add pixel blend mode property %d to plane %d",
+ plane->blend_property().id(), plane->id());
+ break;
+ }
+ }
}
if (!ret) {
diff --git a/drmplane.cpp b/drmplane.cpp
index 2603e16..6747621 100644
--- a/drmplane.cpp
+++ b/drmplane.cpp
@@ -126,6 +126,10 @@
if (ret)
ALOGI("Could not get alpha property");
+ ret = drm_->GetPlaneProperty(*this, "pixel blend mode", &blend_property_);
+ if (ret)
+ ALOGI("Could not get pixel blend mode property");
+
ret = drm_->GetPlaneProperty(*this, "IN_FENCE_FD", &in_fence_fd_property_);
if (ret)
ALOGI("Could not get IN_FENCE_FD property");
@@ -193,6 +197,10 @@
return alpha_property_;
}
+const DrmProperty &DrmPlane::blend_property() const {
+ return blend_property_;
+}
+
const DrmProperty &DrmPlane::in_fence_fd_property() const {
return in_fence_fd_property_;
}
diff --git a/drmplane.h b/drmplane.h
index 46dbc94..b7607ff 100644
--- a/drmplane.h
+++ b/drmplane.h
@@ -54,6 +54,7 @@
const DrmProperty &src_h_property() const;
const DrmProperty &rotation_property() const;
const DrmProperty &alpha_property() const;
+ const DrmProperty &blend_property() const;
const DrmProperty &in_fence_fd_property() const;
private:
@@ -76,6 +77,7 @@
DrmProperty src_h_property_;
DrmProperty rotation_property_;
DrmProperty alpha_property_;
+ DrmProperty blend_property_;
DrmProperty in_fence_fd_property_;
};
} // namespace android
diff --git a/drmproperty.cpp b/drmproperty.cpp
index e71c159..dcab05e 100644
--- a/drmproperty.cpp
+++ b/drmproperty.cpp
@@ -99,4 +99,15 @@
return -EINVAL;
}
}
+
+std::tuple<uint64_t, int> DrmProperty::GetEnumValueWithName(
+ std::string name) const {
+ for (auto it : enums_) {
+ if (it.name_.compare(name) == 0) {
+ return std::make_tuple(it.value_, 0);
+ }
+ }
+
+ return std::make_tuple(UINT64_MAX, -EINVAL);
+}
} // namespace android
diff --git a/drmproperty.h b/drmproperty.h
index dc01c88..5e358be 100644
--- a/drmproperty.h
+++ b/drmproperty.h
@@ -40,6 +40,7 @@
DrmProperty &operator=(const DrmProperty &) = delete;
void Init(drmModePropertyPtr p, uint64_t value);
+ std::tuple<uint64_t, int> GetEnumValueWithName(std::string name) const;
uint32_t id() const;
std::string name() const;
diff --git a/platform.cpp b/platform.cpp
index af18124..9e0eb45 100644
--- a/platform.cpp
+++ b/platform.cpp
@@ -36,6 +36,50 @@
return usable_planes;
}
+int Planner::PlanStage::ValidatePlane(DrmPlane *plane, DrmHwcLayer *layer) {
+ int ret = 0;
+ uint64_t blend;
+
+ if ((plane->rotation_property().id() == 0) &&
+ layer->transform != DrmHwcTransform::kIdentity) {
+ ALOGE("Rotation is not supported on plane %d", plane->id());
+ return -EINVAL;
+ }
+
+ if (plane->alpha_property().id() == 0 && layer->alpha != 0xffff) {
+ ALOGE("Alpha is not supported on plane %d", plane->id());
+ return -EINVAL;
+ }
+
+ if (plane->blend_property().id() == 0) {
+ if ((layer->blending != DrmHwcBlending::kNone) &&
+ (layer->blending != DrmHwcBlending::kPreMult)) {
+ ALOGE("Blending is not supported on plane %d", plane->id());
+ return -EINVAL;
+ }
+ } else {
+ switch (layer->blending) {
+ case DrmHwcBlending::kPreMult:
+ std::tie(blend, ret) = plane->blend_property().GetEnumValueWithName(
+ "Pre-multiplied");
+ break;
+ case DrmHwcBlending::kCoverage:
+ std::tie(blend, ret) = plane->blend_property().GetEnumValueWithName(
+ "Coverage");
+ break;
+ case DrmHwcBlending::kNone:
+ default:
+ std::tie(blend,
+ ret) = plane->blend_property().GetEnumValueWithName("None");
+ break;
+ }
+ if (ret)
+ ALOGE("Expected a valid blend mode on plane %d", plane->id());
+ }
+
+ return ret;
+}
+
std::tuple<int, std::vector<DrmCompositionPlane>> Planner::ProvisionPlanes(
std::map<size_t, DrmHwcLayer *> &layers, DrmCrtc *crtc,
std::vector<DrmPlane *> *primary_planes,
@@ -73,7 +117,7 @@
}
ret = Emplace(composition, planes, DrmCompositionPlane::Type::kLayer, crtc,
- i->first);
+ std::make_pair(i->first, i->second));
if (ret)
ALOGE("Failed to dedicate protected layer! Dropping it.");
@@ -91,7 +135,7 @@
// Fill up the remaining planes
for (auto i = layers.begin(); i != layers.end(); i = layers.erase(i)) {
int ret = Emplace(composition, planes, DrmCompositionPlane::Type::kLayer,
- crtc, i->first);
+ crtc, std::make_pair(i->first, i->second));
// We don't have any planes left
if (ret == -ENOENT)
break;
diff --git a/platform.h b/platform.h
index 37c4647..6c12fe9 100644
--- a/platform.h
+++ b/platform.h
@@ -73,16 +73,23 @@
return plane;
}
+ static int ValidatePlane(DrmPlane *plane, DrmHwcLayer *layer);
+
// Inserts the given layer:plane in the composition at the back
static int Emplace(std::vector<DrmCompositionPlane> *composition,
std::vector<DrmPlane *> *planes,
DrmCompositionPlane::Type type, DrmCrtc *crtc,
- size_t source_layer) {
+ std::pair<size_t, DrmHwcLayer *> layer) {
DrmPlane *plane = PopPlane(planes);
+ int ret;
if (!plane)
return -ENOENT;
- composition->emplace_back(type, plane, crtc, source_layer);
+ ret = ValidatePlane(plane, layer.second);
+ if (ret)
+ return -EINVAL;
+
+ composition->emplace_back(type, plane, crtc, layer.first);
return 0;
}
};
diff --git a/platformhisi.cpp b/platformhisi.cpp
index 68bb5a7..0e12ef1 100644
--- a/platformhisi.cpp
+++ b/platformhisi.cpp
@@ -153,7 +153,7 @@
continue;
int ret = Emplace(composition, planes, DrmCompositionPlane::Type::kLayer,
- crtc, i->first);
+ crtc, std::make_pair(i->first, i->second));
layers_added++;
// We don't have any planes left
if (ret == -ENOENT)