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