• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2015 The Android Open Source Project
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 #define LOG_TAG "hwc-drm-display-composition"
18 
19 #include "DrmDisplayComposition.h"
20 
21 #include <log/log.h>
22 #include <stdlib.h>
23 #include <sync/sync.h>
24 #include <xf86drmMode.h>
25 
26 #include <algorithm>
27 #include <unordered_set>
28 
29 #include "DrmDisplayCompositor.h"
30 #include "Planner.h"
31 #include "drm/DrmDevice.h"
32 
33 namespace android {
34 
~DrmDisplayComposition()35 DrmDisplayComposition::~DrmDisplayComposition() {
36 }
37 
Init(DrmDevice * drm,DrmCrtc * crtc,Importer * importer,Planner * planner,uint64_t frame_no)38 int DrmDisplayComposition::Init(DrmDevice *drm, DrmCrtc *crtc,
39                                 Importer *importer, Planner *planner,
40                                 uint64_t frame_no) {
41   drm_ = drm;
42   crtc_ = crtc;  // Can be NULL if we haven't modeset yet
43   importer_ = importer;
44   planner_ = planner;
45   frame_no_ = frame_no;
46 
47   return 0;
48 }
49 
validate_composition_type(DrmCompositionType des)50 bool DrmDisplayComposition::validate_composition_type(DrmCompositionType des) {
51   return type_ == DRM_COMPOSITION_TYPE_EMPTY || type_ == des;
52 }
53 
SetLayers(DrmHwcLayer * layers,size_t num_layers,bool geometry_changed)54 int DrmDisplayComposition::SetLayers(DrmHwcLayer *layers, size_t num_layers,
55                                      bool geometry_changed) {
56   if (!validate_composition_type(DRM_COMPOSITION_TYPE_FRAME))
57     return -EINVAL;
58 
59   geometry_changed_ = geometry_changed;
60 
61   for (size_t layer_index = 0; layer_index < num_layers; layer_index++) {
62     layers_.emplace_back(std::move(layers[layer_index]));
63   }
64 
65   type_ = DRM_COMPOSITION_TYPE_FRAME;
66   return 0;
67 }
68 
SetDpmsMode(uint32_t dpms_mode)69 int DrmDisplayComposition::SetDpmsMode(uint32_t dpms_mode) {
70   if (!validate_composition_type(DRM_COMPOSITION_TYPE_DPMS))
71     return -EINVAL;
72   dpms_mode_ = dpms_mode;
73   type_ = DRM_COMPOSITION_TYPE_DPMS;
74   return 0;
75 }
76 
SetDisplayMode(const DrmMode & display_mode)77 int DrmDisplayComposition::SetDisplayMode(const DrmMode &display_mode) {
78   if (!validate_composition_type(DRM_COMPOSITION_TYPE_MODESET))
79     return -EINVAL;
80   display_mode_ = display_mode;
81   dpms_mode_ = DRM_MODE_DPMS_ON;
82   type_ = DRM_COMPOSITION_TYPE_MODESET;
83   return 0;
84 }
85 
AddPlaneDisable(DrmPlane * plane)86 int DrmDisplayComposition::AddPlaneDisable(DrmPlane *plane) {
87   composition_planes_.emplace_back(DrmCompositionPlane::Type::kDisable, plane,
88                                    crtc_);
89   return 0;
90 }
91 
AddPlaneComposition(DrmCompositionPlane plane)92 int DrmDisplayComposition::AddPlaneComposition(DrmCompositionPlane plane) {
93   composition_planes_.emplace_back(std::move(plane));
94   return 0;
95 }
96 
Plan(std::vector<DrmPlane * > * primary_planes,std::vector<DrmPlane * > * overlay_planes)97 int DrmDisplayComposition::Plan(std::vector<DrmPlane *> *primary_planes,
98                                 std::vector<DrmPlane *> *overlay_planes) {
99   if (type_ != DRM_COMPOSITION_TYPE_FRAME)
100     return 0;
101 
102   std::map<size_t, DrmHwcLayer *> to_composite;
103 
104   for (size_t i = 0; i < layers_.size(); ++i)
105     to_composite.emplace(std::make_pair(i, &layers_[i]));
106 
107   int ret;
108   std::tie(ret,
109            composition_planes_) = planner_->ProvisionPlanes(to_composite, crtc_,
110                                                             primary_planes,
111                                                             overlay_planes);
112   if (ret) {
113     ALOGE("Planner failed provisioning planes ret=%d", ret);
114     return ret;
115   }
116 
117   // Remove the planes we used from the pool before returning. This ensures they
118   // won't be reused by another display in the composition.
119   for (auto &i : composition_planes_) {
120     if (!i.plane())
121       continue;
122 
123     // make sure that source layers are ordered based on zorder
124     std::sort(i.source_layers().begin(), i.source_layers().end());
125 
126     std::vector<DrmPlane *> *container;
127     if (i.plane()->type() == DRM_PLANE_TYPE_PRIMARY)
128       container = primary_planes;
129     else
130       container = overlay_planes;
131     for (auto j = container->begin(); j != container->end(); ++j) {
132       if (*j == i.plane()) {
133         container->erase(j);
134         break;
135       }
136     }
137   }
138 
139   return 0;
140 }
141 
DrmCompositionTypeToString(DrmCompositionType type)142 static const char *DrmCompositionTypeToString(DrmCompositionType type) {
143   switch (type) {
144     case DRM_COMPOSITION_TYPE_EMPTY:
145       return "EMPTY";
146     case DRM_COMPOSITION_TYPE_FRAME:
147       return "FRAME";
148     case DRM_COMPOSITION_TYPE_DPMS:
149       return "DPMS";
150     case DRM_COMPOSITION_TYPE_MODESET:
151       return "MODESET";
152     default:
153       return "<invalid>";
154   }
155 }
156 
DPMSModeToString(int dpms_mode)157 static const char *DPMSModeToString(int dpms_mode) {
158   switch (dpms_mode) {
159     case DRM_MODE_DPMS_ON:
160       return "ON";
161     case DRM_MODE_DPMS_OFF:
162       return "OFF";
163     default:
164       return "<invalid>";
165   }
166 }
167 
DumpBuffer(const DrmHwcBuffer & buffer,std::ostringstream * out)168 static void DumpBuffer(const DrmHwcBuffer &buffer, std::ostringstream *out) {
169   if (!buffer) {
170     *out << "buffer=<invalid>";
171     return;
172   }
173 
174   *out << "buffer[w/h/format]=";
175   *out << buffer->width << "/" << buffer->height << "/" << buffer->format;
176 }
177 
DumpTransform(uint32_t transform,std::ostringstream * out)178 static void DumpTransform(uint32_t transform, std::ostringstream *out) {
179   *out << "[";
180 
181   if (transform == 0)
182     *out << "IDENTITY";
183 
184   bool separator = false;
185   if (transform & DrmHwcTransform::kFlipH) {
186     *out << "FLIPH";
187     separator = true;
188   }
189   if (transform & DrmHwcTransform::kFlipV) {
190     if (separator)
191       *out << "|";
192     *out << "FLIPV";
193     separator = true;
194   }
195   if (transform & DrmHwcTransform::kRotate90) {
196     if (separator)
197       *out << "|";
198     *out << "ROTATE90";
199     separator = true;
200   }
201   if (transform & DrmHwcTransform::kRotate180) {
202     if (separator)
203       *out << "|";
204     *out << "ROTATE180";
205     separator = true;
206   }
207   if (transform & DrmHwcTransform::kRotate270) {
208     if (separator)
209       *out << "|";
210     *out << "ROTATE270";
211     separator = true;
212   }
213 
214   uint32_t valid_bits = DrmHwcTransform::kFlipH | DrmHwcTransform::kFlipH |
215                         DrmHwcTransform::kRotate90 |
216                         DrmHwcTransform::kRotate180 |
217                         DrmHwcTransform::kRotate270;
218   if (transform & ~valid_bits) {
219     if (separator)
220       *out << "|";
221     *out << "INVALID";
222   }
223   *out << "]";
224 }
225 
BlendingToString(DrmHwcBlending blending)226 static const char *BlendingToString(DrmHwcBlending blending) {
227   switch (blending) {
228     case DrmHwcBlending::kNone:
229       return "NONE";
230     case DrmHwcBlending::kPreMult:
231       return "PREMULT";
232     case DrmHwcBlending::kCoverage:
233       return "COVERAGE";
234     default:
235       return "<invalid>";
236   }
237 }
238 
Dump(std::ostringstream * out) const239 void DrmDisplayComposition::Dump(std::ostringstream *out) const {
240   *out << "----DrmDisplayComposition"
241        << " crtc=" << (crtc_ ? crtc_->id() : -1)
242        << " type=" << DrmCompositionTypeToString(type_);
243 
244   switch (type_) {
245     case DRM_COMPOSITION_TYPE_DPMS:
246       *out << " dpms_mode=" << DPMSModeToString(dpms_mode_);
247       break;
248     case DRM_COMPOSITION_TYPE_MODESET:
249       *out << " display_mode=" << display_mode_.h_display() << "x"
250            << display_mode_.v_display();
251       break;
252     default:
253       break;
254   }
255 
256   *out << "    Layers: count=" << layers_.size() << "\n";
257   for (size_t i = 0; i < layers_.size(); i++) {
258     const DrmHwcLayer &layer = layers_[i];
259     *out << "      [" << i << "] ";
260 
261     DumpBuffer(layer.buffer, out);
262 
263     if (layer.protected_usage())
264       *out << " protected";
265 
266     *out << " transform=";
267     DumpTransform(layer.transform, out);
268     *out << " blending[a=" << (int)layer.alpha
269          << "]=" << BlendingToString(layer.blending) << "\n";
270   }
271 
272   *out << "    Planes: count=" << composition_planes_.size() << "\n";
273   for (size_t i = 0; i < composition_planes_.size(); i++) {
274     const DrmCompositionPlane &comp_plane = composition_planes_[i];
275     *out << "      [" << i << "]"
276          << " plane=" << (comp_plane.plane() ? comp_plane.plane()->id() : -1)
277          << " type=";
278     switch (comp_plane.type()) {
279       case DrmCompositionPlane::Type::kDisable:
280         *out << "DISABLE";
281         break;
282       case DrmCompositionPlane::Type::kLayer:
283         *out << "LAYER";
284         break;
285       default:
286         *out << "<invalid>";
287         break;
288     }
289 
290     *out << " source_layer=";
291     for (auto i : comp_plane.source_layers()) {
292       *out << i << " ";
293     }
294     *out << "\n";
295   }
296 }
297 }  // namespace android
298