2 // Copyright (c) 2017 Intel Corporation
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
8 // http://www.apache.org/licenses/LICENSE-2.0
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
20 #include <drm_fourcc.h>
22 #include <gpudevice.h>
25 #include "overlaylayer.h"
28 namespace hwcomposer {
30 DrmPlane::Property::Property() {
33 bool DrmPlane::Property::Initialize(
34 uint32_t fd, const char* name,
35 const ScopedDrmObjectPropertyPtr& plane_props, uint32_t* rotation) {
36 uint32_t count_props = plane_props->count_props;
37 for (uint32_t i = 0; i < count_props; i++) {
38 ScopedDrmPropertyPtr property(
39 drmModeGetProperty(fd, plane_props->props[i]));
40 if (property && !strcmp(property->name, name)) {
41 id = property->prop_id;
44 for (int enum_index = 0; enum_index < property->count_enums;
46 struct drm_mode_property_enum* penum = &(property->enums[enum_index]);
47 if (!strcmp(penum->name, "rotate-90")) {
48 temp |= DRM_MODE_ROTATE_90;
50 if (!strcmp(penum->name, "rotate-180"))
51 temp |= DRM_MODE_ROTATE_180;
52 else if (!strcmp(penum->name, "rotate-270"))
53 temp |= DRM_MODE_ROTATE_270;
54 else if (!strcmp(penum->name, "rotate-0"))
55 temp |= DRM_MODE_ROTATE_0;
64 ETRACE("Could not find property %s", name);
70 DrmPlane::DrmPlane(uint32_t plane_id, uint32_t possible_crtcs)
72 possible_crtc_mask_(possible_crtcs),
74 last_valid_format_(0),
78 DrmPlane::~DrmPlane() {
82 bool DrmPlane::Initialize(uint32_t gpu_fd,
83 const std::vector<uint32_t>& formats) {
84 supported_formats_ = formats;
85 uint32_t total_size = supported_formats_.size();
86 for (uint32_t j = 0; j < total_size; j++) {
87 uint32_t format = supported_formats_.at(j);
88 if (IsSupportedMediaFormat(format)) {
89 prefered_video_format_ = format;
94 for (uint32_t j = 0; j < total_size; j++) {
95 uint32_t format = supported_formats_.at(j);
97 case DRM_FORMAT_BGRA8888:
98 case DRM_FORMAT_RGBA8888:
99 case DRM_FORMAT_ABGR8888:
100 case DRM_FORMAT_ARGB8888:
101 case DRM_FORMAT_RGB888:
102 case DRM_FORMAT_XRGB8888:
103 case DRM_FORMAT_XBGR8888:
104 case DRM_FORMAT_RGBX8888:
105 prefered_format_ = format;
110 if (type_ == DRM_PLANE_TYPE_PRIMARY) {
111 if (prefered_format_ != DRM_FORMAT_XBGR8888 &&
112 IsSupportedFormat(DRM_FORMAT_XBGR8888)) {
113 prefered_format_ = DRM_FORMAT_XBGR8888;
117 if (prefered_video_format_ == 0) {
118 prefered_video_format_ = prefered_format_;
121 ScopedDrmObjectPropertyPtr plane_props(
122 drmModeObjectGetProperties(gpu_fd, id_, DRM_MODE_OBJECT_PLANE));
124 ETRACE("Unable to get plane properties.");
127 uint32_t count_props = plane_props->count_props;
128 for (uint32_t i = 0; i < count_props; i++) {
129 ScopedDrmPropertyPtr property(
130 drmModeGetProperty(gpu_fd, plane_props->props[i]));
131 if (property && !strcmp(property->name, "type")) {
132 type_ = plane_props->prop_values[i];
137 bool ret = crtc_prop_.Initialize(gpu_fd, "CRTC_ID", plane_props);
141 ret = fb_prop_.Initialize(gpu_fd, "FB_ID", plane_props);
145 ret = crtc_x_prop_.Initialize(gpu_fd, "CRTC_X", plane_props);
149 ret = crtc_y_prop_.Initialize(gpu_fd, "CRTC_Y", plane_props);
153 ret = crtc_w_prop_.Initialize(gpu_fd, "CRTC_W", plane_props);
157 ret = crtc_h_prop_.Initialize(gpu_fd, "CRTC_H", plane_props);
161 ret = src_x_prop_.Initialize(gpu_fd, "SRC_X", plane_props);
165 ret = src_y_prop_.Initialize(gpu_fd, "SRC_Y", plane_props);
169 ret = src_w_prop_.Initialize(gpu_fd, "SRC_W", plane_props);
173 ret = src_h_prop_.Initialize(gpu_fd, "SRC_H", plane_props);
177 ret = rotation_prop_.Initialize(gpu_fd, "rotation", plane_props, &rotation_);
179 ETRACE("Could not get rotation property");
181 ret = alpha_prop_.Initialize(gpu_fd, "alpha", plane_props);
183 ETRACE("Could not get alpha property");
185 ret = in_fence_fd_prop_.Initialize(gpu_fd, "IN_FENCE_FD", plane_props);
187 ETRACE("Could not get IN_FENCE_FD property");
188 in_fence_fd_prop_.id = 0;
194 bool DrmPlane::UpdateProperties(drmModeAtomicReqPtr property_set,
195 uint32_t crtc_id, const OverlayLayer* layer,
196 bool test_commit) const {
197 uint64_t alpha = 0xFF;
198 OverlayBuffer* buffer = layer->GetBuffer();
199 const HwcRect<int>& display_frame = layer->GetDisplayFrame();
200 const HwcRect<float>& source_crop = layer->GetSourceCrop();
201 int fence = kms_fence_;
203 fence = layer->GetAcquireFence();
205 if (layer->GetBlending() == HWCBlending::kBlendingPremult)
206 alpha = layer->GetAlpha();
208 IDISPLAYMANAGERTRACE("buffer->GetFb() ---------------------- STARTS %d",
211 drmModeAtomicAddProperty(property_set, id_, crtc_prop_.id, crtc_id) < 0;
212 success |= drmModeAtomicAddProperty(property_set, id_, fb_prop_.id,
213 buffer->GetFb()) < 0;
214 success |= drmModeAtomicAddProperty(property_set, id_, crtc_x_prop_.id,
215 display_frame.left) < 0;
216 success |= drmModeAtomicAddProperty(property_set, id_, crtc_y_prop_.id,
217 display_frame.top) < 0;
219 if (layer->IsCursorLayer()) {
220 success |= drmModeAtomicAddProperty(property_set, id_, crtc_w_prop_.id,
221 buffer->GetWidth()) < 0;
222 success |= drmModeAtomicAddProperty(property_set, id_, crtc_h_prop_.id,
223 buffer->GetHeight()) < 0;
225 drmModeAtomicAddProperty(property_set, id_, src_x_prop_.id, 0) < 0;
227 drmModeAtomicAddProperty(property_set, id_, src_y_prop_.id, 0) < 0;
229 success |= drmModeAtomicAddProperty(property_set, id_, src_w_prop_.id,
230 buffer->GetWidth() << 16) < 0;
231 success |= drmModeAtomicAddProperty(property_set, id_, src_h_prop_.id,
232 buffer->GetHeight() << 16) < 0;
234 success |= drmModeAtomicAddProperty(property_set, id_, crtc_w_prop_.id,
235 layer->GetDisplayFrameWidth()) < 0;
236 success |= drmModeAtomicAddProperty(property_set, id_, crtc_h_prop_.id,
237 layer->GetDisplayFrameHeight()) < 0;
238 success |= drmModeAtomicAddProperty(
239 property_set, id_, src_x_prop_.id,
240 static_cast<int>(ceilf(source_crop.left)) << 16) < 0;
241 success |= drmModeAtomicAddProperty(
242 property_set, id_, src_y_prop_.id,
243 static_cast<int>(ceilf((source_crop.top))) << 16) < 0;
244 success |= drmModeAtomicAddProperty(property_set, id_, src_w_prop_.id,
245 layer->GetSourceCropWidth() << 16) < 0;
246 success |= drmModeAtomicAddProperty(property_set, id_, src_h_prop_.id,
247 layer->GetSourceCropHeight() << 16) < 0;
250 if (rotation_prop_.id) {
251 uint32_t rotation = 0;
252 uint32_t transform = layer->GetPlaneTransform();
253 if (transform & kTransform90) {
254 rotation |= DRM_MODE_ROTATE_90;
255 if (transform & kReflectX)
256 rotation |= DRM_MODE_REFLECT_X;
257 if (transform & kReflectY)
258 rotation |= DRM_MODE_REFLECT_Y;
259 } else if (transform & kTransform180)
260 rotation |= DRM_MODE_ROTATE_180;
261 else if (transform & kTransform270)
262 rotation |= DRM_MODE_ROTATE_270;
264 rotation |= DRM_MODE_ROTATE_0;
266 success = drmModeAtomicAddProperty(property_set, id_, rotation_prop_.id,
270 if (alpha_prop_.id) {
272 drmModeAtomicAddProperty(property_set, id_, alpha_prop_.id, alpha) < 0;
275 if (fence > 0 && in_fence_fd_prop_.id) {
276 success = drmModeAtomicAddProperty(property_set, id_, in_fence_fd_prop_.id,
281 ETRACE("Could not update properties for plane with id: %d", id_);
284 IDISPLAYMANAGERTRACE("buffer->GetFb() ---------------------- ENDS%d",
289 void DrmPlane::SetNativeFence(int32_t fd) {
290 // Release any existing fence.
291 if (kms_fence_ > 0) {
298 bool DrmPlane::Disable(drmModeAtomicReqPtr property_set) {
301 drmModeAtomicAddProperty(property_set, id_, crtc_prop_.id, 0) < 0;
302 success |= drmModeAtomicAddProperty(property_set, id_, fb_prop_.id, 0) < 0;
304 drmModeAtomicAddProperty(property_set, id_, crtc_x_prop_.id, 0) < 0;
306 drmModeAtomicAddProperty(property_set, id_, crtc_y_prop_.id, 0) < 0;
308 drmModeAtomicAddProperty(property_set, id_, crtc_w_prop_.id, 0) < 0;
310 drmModeAtomicAddProperty(property_set, id_, crtc_h_prop_.id, 0) < 0;
311 success |= drmModeAtomicAddProperty(property_set, id_, src_x_prop_.id, 0) < 0;
312 success |= drmModeAtomicAddProperty(property_set, id_, src_y_prop_.id, 0) < 0;
313 success |= drmModeAtomicAddProperty(property_set, id_, src_w_prop_.id, 0) < 0;
314 success |= drmModeAtomicAddProperty(property_set, id_, src_h_prop_.id, 0) < 0;
317 ETRACE("Could not update properties for plane with id: %d", id_);
326 uint32_t DrmPlane::id() const {
330 bool DrmPlane::GetCrtcSupported(uint32_t pipe_id) const {
331 return !!((1 << pipe_id) & possible_crtc_mask_);
334 uint32_t DrmPlane::type() const {
338 bool DrmPlane::ValidateLayer(const OverlayLayer* layer) {
339 uint64_t alpha = 0xFF;
341 if (layer->GetBlending() == HWCBlending::kBlendingPremult)
342 alpha = layer->GetAlpha();
344 if (type_ == DRM_PLANE_TYPE_OVERLAY && (alpha != 0 && alpha != 0xFF) &&
345 alpha_prop_.id == 0) {
346 IDISPLAYMANAGERTRACE(
347 "Alpha property not supported, Cannot composite layer using Overlay.");
351 bool zero_rotation = false;
352 uint32_t transform = layer->GetPlaneTransform();
353 if (transform == kIdentity) {
354 zero_rotation = true;
357 if (!zero_rotation && rotation_prop_.id == 0) {
358 IDISPLAYMANAGERTRACE(
359 "Rotation property not supported, Cannot composite layer using "
364 if (!IsSupportedFormat(layer->GetBuffer()->GetFormat())) {
365 IDISPLAYMANAGERTRACE(
366 "Layer cannot be supported as format is not supported.");
370 return IsSupportedTransform(transform);
373 bool DrmPlane::IsSupportedFormat(uint32_t format) {
374 if (last_valid_format_ == format)
377 for (auto& element : supported_formats_) {
378 if (element == format) {
379 last_valid_format_ = format;
387 bool DrmPlane::IsSupportedTransform(uint32_t transform) const {
388 if (transform & kTransform90) {
389 if (!(rotation_ & DRM_MODE_ROTATE_90)) {
392 } else if (transform & kTransform180) {
393 if (!(rotation_ & DRM_MODE_ROTATE_180)) {
396 } else if (transform & kTransform270) {
397 if (!(rotation_ & DRM_MODE_ROTATE_270)) {
401 if (!(rotation_ & DRM_MODE_ROTATE_0)) {
409 uint32_t DrmPlane::GetPreferredVideoFormat() const {
410 return prefered_video_format_;
413 uint32_t DrmPlane::GetPreferredFormat() const {
414 return prefered_format_;
417 void DrmPlane::SetInUse(bool in_use) {
421 void DrmPlane::Dump() const {
422 DUMPTRACE("Plane Information Starts. -------------");
423 DUMPTRACE("Plane ID: %d", id_);
425 case DRM_PLANE_TYPE_OVERLAY:
426 DUMPTRACE("Type: Overlay.");
428 case DRM_PLANE_TYPE_PRIMARY:
429 DUMPTRACE("Type: Primary.");
431 case DRM_PLANE_TYPE_CURSOR:
432 DUMPTRACE("Type: Cursor.");
435 ETRACE("Invalid plane type %d", type_);
438 for (uint32_t j = 0; j < supported_formats_.size(); j++)
439 DUMPTRACE("Format: %4.4s", (char*)&supported_formats_[j]);
441 DUMPTRACE("Enabled: %d", in_use_);
443 if (alpha_prop_.id != 0)
444 DUMPTRACE("Alpha property is supported.");
446 if (rotation_prop_.id != 0)
447 DUMPTRACE("Rotation property is supported.");
449 if (crtc_prop_.id != 0)
450 DUMPTRACE("CRTC_ID property is supported.");
452 if (fb_prop_.id != 0)
453 DUMPTRACE("FB_ID property is supported.");
455 if (crtc_x_prop_.id != 0)
456 DUMPTRACE("CRTC_X property is supported.");
458 if (crtc_y_prop_.id != 0)
459 DUMPTRACE("CRTC_Y property is supported.");
461 if (crtc_w_prop_.id != 0)
462 DUMPTRACE("CRTC_W property is supported.");
464 if (crtc_h_prop_.id != 0)
465 DUMPTRACE("CRTC_H property is supported.");
467 if (src_x_prop_.id != 0)
468 DUMPTRACE("SRC_X property is supported.");
470 if (src_y_prop_.id != 0)
471 DUMPTRACE("SRC_Y property is supported.");
473 if (src_w_prop_.id != 0)
474 DUMPTRACE("SRC_W property is supported.");
476 if (src_h_prop_.id != 0)
477 DUMPTRACE("SRC_H property is supported.");
479 if (in_fence_fd_prop_.id != 0)
480 DUMPTRACE("IN_FENCE_FD is supported.");
482 DUMPTRACE("Preferred Video Format: %4.4s", (char*)&(prefered_video_format_));
483 DUMPTRACE("Preferred Video Format: %4.4s", (char*)&(prefered_format_));
485 DUMPTRACE("Plane Information Ends. -------------");
488 } // namespace hwcomposer