OSDN Git Service

Move all display transform checks to PlaneState.
[android-x86/external-IA-Hardware-Composer.git] / wsi / drm / drmplane.cpp
1 /*
2 // Copyright (c) 2017 Intel Corporation
3 //
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
7 //
8 //      http://www.apache.org/licenses/LICENSE-2.0
9 //
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.
15 */
16
17 #include "drmplane.h"
18
19 #include <cmath>
20 #include <drm_fourcc.h>
21
22 #include <gpudevice.h>
23
24 #include "hwctrace.h"
25 #include "overlaylayer.h"
26 #include "hwcutils.h"
27
28 namespace hwcomposer {
29
30 DrmPlane::Property::Property() {
31 }
32
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;
42       if (rotation) {
43         uint32_t temp = 0;
44         for (int enum_index = 0; enum_index < property->count_enums;
45              enum_index++) {
46           struct drm_mode_property_enum* penum = &(property->enums[enum_index]);
47           if (!strcmp(penum->name, "rotate-90")) {
48             temp |= DRM_MODE_ROTATE_90;
49           }
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;
56         }
57
58         *rotation = temp;
59       }
60       break;
61     }
62   }
63   if (!id) {
64     ETRACE("Could not find property %s", name);
65     return false;
66   }
67   return true;
68 }
69
70 DrmPlane::DrmPlane(uint32_t plane_id, uint32_t possible_crtcs)
71     : id_(plane_id),
72       possible_crtc_mask_(possible_crtcs),
73       type_(0),
74       last_valid_format_(0),
75       in_use_(false) {
76 }
77
78 DrmPlane::~DrmPlane() {
79   SetNativeFence(-1);
80 }
81
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;
90       break;
91     }
92   }
93
94   for (uint32_t j = 0; j < total_size; j++) {
95     uint32_t format = supported_formats_.at(j);
96     switch (format) {
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;
106         break;
107     }
108   }
109
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;
114     }
115   }
116
117   if (prefered_video_format_ == 0) {
118     prefered_video_format_ = prefered_format_;
119   }
120
121   ScopedDrmObjectPropertyPtr plane_props(
122       drmModeObjectGetProperties(gpu_fd, id_, DRM_MODE_OBJECT_PLANE));
123   if (!plane_props) {
124     ETRACE("Unable to get plane properties.");
125     return false;
126   }
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];
133       break;
134     }
135   }
136
137   bool ret = crtc_prop_.Initialize(gpu_fd, "CRTC_ID", plane_props);
138   if (!ret)
139     return false;
140
141   ret = fb_prop_.Initialize(gpu_fd, "FB_ID", plane_props);
142   if (!ret)
143     return false;
144
145   ret = crtc_x_prop_.Initialize(gpu_fd, "CRTC_X", plane_props);
146   if (!ret)
147     return false;
148
149   ret = crtc_y_prop_.Initialize(gpu_fd, "CRTC_Y", plane_props);
150   if (!ret)
151     return false;
152
153   ret = crtc_w_prop_.Initialize(gpu_fd, "CRTC_W", plane_props);
154   if (!ret)
155     return false;
156
157   ret = crtc_h_prop_.Initialize(gpu_fd, "CRTC_H", plane_props);
158   if (!ret)
159     return false;
160
161   ret = src_x_prop_.Initialize(gpu_fd, "SRC_X", plane_props);
162   if (!ret)
163     return false;
164
165   ret = src_y_prop_.Initialize(gpu_fd, "SRC_Y", plane_props);
166   if (!ret)
167     return false;
168
169   ret = src_w_prop_.Initialize(gpu_fd, "SRC_W", plane_props);
170   if (!ret)
171     return false;
172
173   ret = src_h_prop_.Initialize(gpu_fd, "SRC_H", plane_props);
174   if (!ret)
175     return false;
176
177   ret = rotation_prop_.Initialize(gpu_fd, "rotation", plane_props, &rotation_);
178   if (!ret)
179     ETRACE("Could not get rotation property");
180
181   ret = alpha_prop_.Initialize(gpu_fd, "alpha", plane_props);
182   if (!ret)
183     ETRACE("Could not get alpha property");
184
185   ret = in_fence_fd_prop_.Initialize(gpu_fd, "IN_FENCE_FD", plane_props);
186   if (!ret) {
187     ETRACE("Could not get IN_FENCE_FD property");
188     in_fence_fd_prop_.id = 0;
189   }
190
191   return true;
192 }
193
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_;
202   if (test_commit)
203     fence = layer->GetAcquireFence();
204
205   if (layer->GetBlending() == HWCBlending::kBlendingPremult)
206     alpha = layer->GetAlpha();
207
208   IDISPLAYMANAGERTRACE("buffer->GetFb() ---------------------- STARTS %d",
209                        buffer->GetFb());
210   int success =
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;
218
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;
224     success |=
225         drmModeAtomicAddProperty(property_set, id_, src_x_prop_.id, 0) < 0;
226     success |=
227         drmModeAtomicAddProperty(property_set, id_, src_y_prop_.id, 0) < 0;
228
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;
233   } else {
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;
248   }
249
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;
263     else
264       rotation |= DRM_MODE_ROTATE_0;
265
266     success = drmModeAtomicAddProperty(property_set, id_, rotation_prop_.id,
267                                        rotation) < 0;
268   }
269
270   if (alpha_prop_.id) {
271     success =
272         drmModeAtomicAddProperty(property_set, id_, alpha_prop_.id, alpha) < 0;
273   }
274
275   if (fence > 0 && in_fence_fd_prop_.id) {
276     success = drmModeAtomicAddProperty(property_set, id_, in_fence_fd_prop_.id,
277                                        fence) < 0;
278   }
279
280   if (success) {
281     ETRACE("Could not update properties for plane with id: %d", id_);
282     return false;
283   }
284   IDISPLAYMANAGERTRACE("buffer->GetFb() ---------------------- ENDS%d",
285                        buffer->GetFb());
286   return true;
287 }
288
289 void DrmPlane::SetNativeFence(int32_t fd) {
290   // Release any existing fence.
291   if (kms_fence_ > 0) {
292     close(kms_fence_);
293   }
294
295   kms_fence_ = fd;
296 }
297
298 bool DrmPlane::Disable(drmModeAtomicReqPtr property_set) {
299   in_use_ = false;
300   int success =
301       drmModeAtomicAddProperty(property_set, id_, crtc_prop_.id, 0) < 0;
302   success |= drmModeAtomicAddProperty(property_set, id_, fb_prop_.id, 0) < 0;
303   success |=
304       drmModeAtomicAddProperty(property_set, id_, crtc_x_prop_.id, 0) < 0;
305   success |=
306       drmModeAtomicAddProperty(property_set, id_, crtc_y_prop_.id, 0) < 0;
307   success |=
308       drmModeAtomicAddProperty(property_set, id_, crtc_w_prop_.id, 0) < 0;
309   success |=
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;
315
316   if (success) {
317     ETRACE("Could not update properties for plane with id: %d", id_);
318     return false;
319   }
320
321   SetNativeFence(-1);
322
323   return true;
324 }
325
326 uint32_t DrmPlane::id() const {
327   return id_;
328 }
329
330 bool DrmPlane::GetCrtcSupported(uint32_t pipe_id) const {
331   return !!((1 << pipe_id) & possible_crtc_mask_);
332 }
333
334 uint32_t DrmPlane::type() const {
335   return type_;
336 }
337
338 bool DrmPlane::ValidateLayer(const OverlayLayer* layer) {
339   uint64_t alpha = 0xFF;
340
341   if (layer->GetBlending() == HWCBlending::kBlendingPremult)
342     alpha = layer->GetAlpha();
343
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.");
348     return false;
349   }
350
351   bool zero_rotation = false;
352   uint32_t transform = layer->GetPlaneTransform();
353   if (transform == kIdentity) {
354     zero_rotation = true;
355   }
356
357   if (!zero_rotation && rotation_prop_.id == 0) {
358     IDISPLAYMANAGERTRACE(
359         "Rotation property not supported, Cannot composite layer using "
360         "Overlay.");
361     return false;
362   }
363
364   if (!IsSupportedFormat(layer->GetBuffer()->GetFormat())) {
365     IDISPLAYMANAGERTRACE(
366         "Layer cannot be supported as format is not supported.");
367     return false;
368   }
369
370   return IsSupportedTransform(transform);
371 }
372
373 bool DrmPlane::IsSupportedFormat(uint32_t format) {
374   if (last_valid_format_ == format)
375     return true;
376
377   for (auto& element : supported_formats_) {
378     if (element == format) {
379       last_valid_format_ = format;
380       return true;
381     }
382   }
383
384   return false;
385 }
386
387 bool DrmPlane::IsSupportedTransform(uint32_t transform) const {
388   if (transform & kTransform90) {
389     if (!(rotation_ & DRM_MODE_ROTATE_90)) {
390       return false;
391     }
392   } else if (transform & kTransform180) {
393     if (!(rotation_ & DRM_MODE_ROTATE_180)) {
394       return false;
395     }
396   } else if (transform & kTransform270) {
397     if (!(rotation_ & DRM_MODE_ROTATE_270)) {
398       return false;
399     }
400   } else {
401     if (!(rotation_ & DRM_MODE_ROTATE_0)) {
402       return false;
403     }
404   }
405
406   return true;
407 }
408
409 uint32_t DrmPlane::GetPreferredVideoFormat() const {
410   return prefered_video_format_;
411 }
412
413 uint32_t DrmPlane::GetPreferredFormat() const {
414   return prefered_format_;
415 }
416
417 void DrmPlane::SetInUse(bool in_use) {
418   in_use_ = in_use;
419 }
420
421 void DrmPlane::Dump() const {
422   DUMPTRACE("Plane Information Starts. -------------");
423   DUMPTRACE("Plane ID: %d", id_);
424   switch (type_) {
425     case DRM_PLANE_TYPE_OVERLAY:
426       DUMPTRACE("Type: Overlay.");
427       break;
428     case DRM_PLANE_TYPE_PRIMARY:
429       DUMPTRACE("Type: Primary.");
430       break;
431     case DRM_PLANE_TYPE_CURSOR:
432       DUMPTRACE("Type: Cursor.");
433       break;
434     default:
435       ETRACE("Invalid plane type %d", type_);
436   }
437
438   for (uint32_t j = 0; j < supported_formats_.size(); j++)
439     DUMPTRACE("Format: %4.4s", (char*)&supported_formats_[j]);
440
441   DUMPTRACE("Enabled: %d", in_use_);
442
443   if (alpha_prop_.id != 0)
444     DUMPTRACE("Alpha property is supported.");
445
446   if (rotation_prop_.id != 0)
447     DUMPTRACE("Rotation property is supported.");
448
449   if (crtc_prop_.id != 0)
450     DUMPTRACE("CRTC_ID property is supported.");
451
452   if (fb_prop_.id != 0)
453     DUMPTRACE("FB_ID property is supported.");
454
455   if (crtc_x_prop_.id != 0)
456     DUMPTRACE("CRTC_X property is supported.");
457
458   if (crtc_y_prop_.id != 0)
459     DUMPTRACE("CRTC_Y property is supported.");
460
461   if (crtc_w_prop_.id != 0)
462     DUMPTRACE("CRTC_W property is supported.");
463
464   if (crtc_h_prop_.id != 0)
465     DUMPTRACE("CRTC_H property is supported.");
466
467   if (src_x_prop_.id != 0)
468     DUMPTRACE("SRC_X property is supported.");
469
470   if (src_y_prop_.id != 0)
471     DUMPTRACE("SRC_Y property is supported.");
472
473   if (src_w_prop_.id != 0)
474     DUMPTRACE("SRC_W property is supported.");
475
476   if (src_h_prop_.id != 0)
477     DUMPTRACE("SRC_H property is supported.");
478
479   if (in_fence_fd_prop_.id != 0)
480     DUMPTRACE("IN_FENCE_FD is supported.");
481
482   DUMPTRACE("Preferred Video Format: %4.4s", (char*)&(prefered_video_format_));
483   DUMPTRACE("Preferred Video Format: %4.4s", (char*)&(prefered_format_));
484
485   DUMPTRACE("Plane Information Ends. -------------");
486 }
487
488 }  // namespace hwcomposer