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