1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "ui/ozone/platform/drm/gpu/hardware_display_plane_atomic.h"
6
7 #include "base/logging.h"
8 #include "ui/ozone/platform/drm/gpu/drm_device.h"
9 #include "ui/ozone/platform/drm/gpu/drm_gpu_util.h"
10
11 namespace ui {
12 namespace {
13
OverlayTransformToDrmRotationPropertyValue(gfx::OverlayTransform transform)14 uint32_t OverlayTransformToDrmRotationPropertyValue(
15 gfx::OverlayTransform transform) {
16 switch (transform) {
17 case gfx::OVERLAY_TRANSFORM_NONE:
18 return DRM_MODE_ROTATE_0;
19 case gfx::OVERLAY_TRANSFORM_FLIP_HORIZONTAL:
20 return DRM_MODE_REFLECT_X | DRM_MODE_ROTATE_0;
21 case gfx::OVERLAY_TRANSFORM_FLIP_VERTICAL:
22 return DRM_MODE_REFLECT_Y | DRM_MODE_ROTATE_0;
23 case gfx::OVERLAY_TRANSFORM_ROTATE_90:
24 return DRM_MODE_ROTATE_90;
25 case gfx::OVERLAY_TRANSFORM_ROTATE_180:
26 return DRM_MODE_ROTATE_180;
27 case gfx::OVERLAY_TRANSFORM_ROTATE_270:
28 return DRM_MODE_ROTATE_270;
29 default:
30 NOTREACHED();
31 }
32 return 0;
33 }
34
35 // Rotations are dependent on modifiers. Tiled formats can be rotated,
36 // linear formats cannot. Atomic tests currently ignore modifiers, so there
37 // isn't a way of determining if the rotation is supported.
38 // TODO(https://crbug/880464): Remove this.
IsRotationTransformSupported(gfx::OverlayTransform transform)39 bool IsRotationTransformSupported(gfx::OverlayTransform transform) {
40 if ((transform == gfx::OVERLAY_TRANSFORM_ROTATE_90) ||
41 (transform == gfx::OVERLAY_TRANSFORM_ROTATE_270) ||
42 (transform == gfx::OVERLAY_TRANSFORM_FLIP_HORIZONTAL)) {
43 return false;
44 }
45
46 return true;
47 }
48
49 } // namespace
50
HardwareDisplayPlaneAtomic(uint32_t id)51 HardwareDisplayPlaneAtomic::HardwareDisplayPlaneAtomic(uint32_t id)
52 : HardwareDisplayPlane(id) {}
53
54 HardwareDisplayPlaneAtomic::~HardwareDisplayPlaneAtomic() = default;
55
Initialize(DrmDevice * drm)56 bool HardwareDisplayPlaneAtomic::Initialize(DrmDevice* drm) {
57 if (!HardwareDisplayPlane::Initialize(drm))
58 return false;
59
60 // Check that all the required properties have been found.
61 bool ret = properties_.crtc_id.id && properties_.crtc_x.id &&
62 properties_.crtc_y.id && properties_.crtc_w.id &&
63 properties_.crtc_h.id && properties_.fb_id.id &&
64 properties_.src_x.id && properties_.src_y.id &&
65 properties_.src_w.id && properties_.src_h.id;
66 LOG_IF(ERROR, !ret) << "Failed to find all required properties for plane="
67 << id_;
68
69 ret &= (properties_.plane_color_encoding.id == 0) ==
70 (properties_.plane_color_range.id == 0);
71 LOG_IF(ERROR, !ret) << "Inconsistent color management properties for plane="
72 << id_;
73
74 return ret;
75 }
76
AssignPlaneProps(uint32_t crtc_id,uint32_t framebuffer,const gfx::Rect & crtc_rect,const gfx::Rect & src_rect,const gfx::OverlayTransform transform,int in_fence_fd)77 bool HardwareDisplayPlaneAtomic::AssignPlaneProps(
78 uint32_t crtc_id,
79 uint32_t framebuffer,
80 const gfx::Rect& crtc_rect,
81 const gfx::Rect& src_rect,
82 const gfx::OverlayTransform transform,
83 int in_fence_fd) {
84 if (transform != gfx::OVERLAY_TRANSFORM_NONE && !properties_.rotation.id)
85 return false;
86
87 if (!IsRotationTransformSupported(transform))
88 return false;
89
90 // Make a copy of properties to get the props IDs for the new intermediate
91 // values.
92 assigned_props_ = properties_;
93
94 assigned_props_.crtc_id.value = crtc_id;
95 assigned_props_.crtc_x.value = crtc_rect.x();
96 assigned_props_.crtc_y.value = crtc_rect.y();
97 assigned_props_.crtc_w.value = crtc_rect.width();
98 assigned_props_.crtc_h.value = crtc_rect.height();
99 assigned_props_.fb_id.value = framebuffer;
100 assigned_props_.src_x.value = src_rect.x();
101 assigned_props_.src_y.value = src_rect.y();
102 assigned_props_.src_w.value = src_rect.width();
103 assigned_props_.src_h.value = src_rect.height();
104
105 if (assigned_props_.rotation.id) {
106 assigned_props_.rotation.value =
107 OverlayTransformToDrmRotationPropertyValue(transform);
108 }
109
110 if (assigned_props_.in_fence_fd.id)
111 assigned_props_.in_fence_fd.value = static_cast<uint64_t>(in_fence_fd);
112
113 return true;
114 }
115
SetPlaneProps(drmModeAtomicReq * property_set)116 bool HardwareDisplayPlaneAtomic::SetPlaneProps(drmModeAtomicReq* property_set) {
117 bool plane_set_succeeded =
118 AddPropertyIfValid(property_set, id_, assigned_props_.crtc_id) &&
119 AddPropertyIfValid(property_set, id_, assigned_props_.crtc_x) &&
120 AddPropertyIfValid(property_set, id_, assigned_props_.crtc_y) &&
121 AddPropertyIfValid(property_set, id_, assigned_props_.crtc_w) &&
122 AddPropertyIfValid(property_set, id_, assigned_props_.crtc_h) &&
123 AddPropertyIfValid(property_set, id_, assigned_props_.fb_id) &&
124 AddPropertyIfValid(property_set, id_, assigned_props_.src_x) &&
125 AddPropertyIfValid(property_set, id_, assigned_props_.src_y) &&
126 AddPropertyIfValid(property_set, id_, assigned_props_.src_w) &&
127 AddPropertyIfValid(property_set, id_, assigned_props_.src_h);
128
129 if (assigned_props_.rotation.id) {
130 plane_set_succeeded &=
131 AddPropertyIfValid(property_set, id_, assigned_props_.rotation);
132 }
133
134 if (assigned_props_.in_fence_fd.id) {
135 plane_set_succeeded &=
136 AddPropertyIfValid(property_set, id_, assigned_props_.in_fence_fd);
137 }
138
139 if (assigned_props_.plane_color_encoding.id) {
140 // TODO(markyacoub): |color_encoding_bt601_| and |color_range_limited_| are
141 // only set in Initialize(). The properties could be set once in there and
142 // these member variables could be removed.
143 assigned_props_.plane_color_encoding.value = color_encoding_bt601_;
144 assigned_props_.plane_color_range.value = color_range_limited_;
145 plane_set_succeeded &= AddPropertyIfValid(
146 property_set, id_, assigned_props_.plane_color_encoding);
147 plane_set_succeeded &= AddPropertyIfValid(
148 property_set, id_, assigned_props_.plane_color_range);
149 }
150
151 if (!plane_set_succeeded) {
152 LOG(ERROR) << "Failed to set plane data";
153 return false;
154 }
155
156 // Update properties_ if the setting the props succeeded.
157 properties_ = assigned_props_;
158 return true;
159 }
160
SetPlaneCtm(drmModeAtomicReq * property_set,uint32_t ctm_blob_id)161 bool HardwareDisplayPlaneAtomic::SetPlaneCtm(drmModeAtomicReq* property_set,
162 uint32_t ctm_blob_id) {
163 if (!properties_.plane_ctm.id)
164 return false;
165
166 properties_.plane_ctm.value = ctm_blob_id;
167 return AddPropertyIfValid(property_set, id_, properties_.plane_ctm);
168 }
169
AssignedCrtcId() const170 uint32_t HardwareDisplayPlaneAtomic::AssignedCrtcId() const {
171 return assigned_props_.crtc_id.value;
172 }
173
174 } // namespace ui
175