OSDN Git Service

drm_hwcomposer: Add DrmEventListener worker
[android-x86/external-drm_hwcomposer.git] / drmdisplaycomposition.cpp
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 "drmplane.h"
22 #include "drmresources.h"
23
24 #include <stdlib.h>
25
26 #include <algorithm>
27 #include <unordered_set>
28
29 #include <cutils/log.h>
30 #include <sw_sync.h>
31 #include <sync/sync.h>
32 #include <xf86drmMode.h>
33
34 namespace android {
35
36 const size_t DrmCompositionPlane::kSourceNone;
37 const size_t DrmCompositionPlane::kSourcePreComp;
38 const size_t DrmCompositionPlane::kSourceSquash;
39 const size_t DrmCompositionPlane::kSourceLayerMax;
40
41 DrmDisplayComposition::~DrmDisplayComposition() {
42   if (timeline_fd_ >= 0) {
43     SignalCompositionDone();
44     close(timeline_fd_);
45   }
46 }
47
48 int DrmDisplayComposition::Init(DrmResources *drm, DrmCrtc *crtc,
49                                 Importer *importer, uint64_t frame_no) {
50   drm_ = drm;
51   crtc_ = crtc;  // Can be NULL if we haven't modeset yet
52   importer_ = importer;
53   frame_no_ = frame_no;
54
55   int ret = sw_sync_timeline_create();
56   if (ret < 0) {
57     ALOGE("Failed to create sw sync timeline %d", ret);
58     return ret;
59   }
60   timeline_fd_ = ret;
61   return 0;
62 }
63
64 bool DrmDisplayComposition::validate_composition_type(DrmCompositionType des) {
65   return type_ == DRM_COMPOSITION_TYPE_EMPTY || type_ == des;
66 }
67
68 int DrmDisplayComposition::CreateNextTimelineFence() {
69   ++timeline_;
70   return sw_sync_fence_create(timeline_fd_, "hwc drm display composition fence",
71                               timeline_);
72 }
73
74 int DrmDisplayComposition::IncreaseTimelineToPoint(int point) {
75   int timeline_increase = point - timeline_current_;
76   if (timeline_increase <= 0)
77     return 0;
78
79   int ret = sw_sync_timeline_inc(timeline_fd_, timeline_increase);
80   if (ret)
81     ALOGE("Failed to increment sync timeline %d", ret);
82   else
83     timeline_current_ = point;
84
85   return ret;
86 }
87
88 int DrmDisplayComposition::SetLayers(DrmHwcLayer *layers, size_t num_layers,
89                                      bool geometry_changed) {
90   if (!validate_composition_type(DRM_COMPOSITION_TYPE_FRAME))
91     return -EINVAL;
92
93   geometry_changed_ = geometry_changed;
94
95   for (size_t layer_index = 0; layer_index < num_layers; layer_index++) {
96     layers_.emplace_back(std::move(layers[layer_index]));
97   }
98
99   type_ = DRM_COMPOSITION_TYPE_FRAME;
100   return 0;
101 }
102
103 int DrmDisplayComposition::SetDpmsMode(uint32_t dpms_mode) {
104   if (!validate_composition_type(DRM_COMPOSITION_TYPE_DPMS))
105     return -EINVAL;
106   dpms_mode_ = dpms_mode;
107   type_ = DRM_COMPOSITION_TYPE_DPMS;
108   return 0;
109 }
110
111 int DrmDisplayComposition::SetDisplayMode(const DrmMode &display_mode) {
112   if (!validate_composition_type(DRM_COMPOSITION_TYPE_MODESET))
113     return -EINVAL;
114   display_mode_ = display_mode;
115   dpms_mode_ = DRM_MODE_DPMS_ON;
116   type_ = DRM_COMPOSITION_TYPE_MODESET;
117   return 0;
118 }
119
120 int DrmDisplayComposition::AddPlaneDisable(DrmPlane *plane) {
121   composition_planes_.emplace_back(
122       DrmCompositionPlane{plane, crtc_, DrmCompositionPlane::kSourceNone});
123   return 0;
124 }
125
126 static size_t CountUsablePlanes(DrmCrtc *crtc,
127                                 std::vector<DrmPlane *> *primary_planes,
128                                 std::vector<DrmPlane *> *overlay_planes) {
129   return std::count_if(
130              primary_planes->begin(), primary_planes->end(),
131              [=](DrmPlane *plane) { return plane->GetCrtcSupported(*crtc); }) +
132          std::count_if(
133              overlay_planes->begin(), overlay_planes->end(),
134              [=](DrmPlane *plane) { return plane->GetCrtcSupported(*crtc); });
135 }
136
137 static DrmPlane *TakePlane(DrmCrtc *crtc, std::vector<DrmPlane *> *planes) {
138   for (auto iter = planes->begin(); iter != planes->end(); ++iter) {
139     if ((*iter)->GetCrtcSupported(*crtc)) {
140       DrmPlane *plane = *iter;
141       planes->erase(iter);
142       return plane;
143     }
144   }
145   return NULL;
146 }
147
148 static DrmPlane *TakePlane(DrmCrtc *crtc,
149                            std::vector<DrmPlane *> *primary_planes,
150                            std::vector<DrmPlane *> *overlay_planes) {
151   DrmPlane *plane = TakePlane(crtc, primary_planes);
152   if (plane)
153     return plane;
154   return TakePlane(crtc, overlay_planes);
155 }
156
157 void DrmDisplayComposition::EmplaceCompositionPlane(
158     size_t source_layer, std::vector<DrmPlane *> *primary_planes,
159     std::vector<DrmPlane *> *overlay_planes) {
160   DrmPlane *plane = TakePlane(crtc_, primary_planes, overlay_planes);
161   if (plane == NULL) {
162     ALOGE(
163         "Failed to add composition plane because there are no planes "
164         "remaining");
165     return;
166   }
167   composition_planes_.emplace_back(
168       DrmCompositionPlane{plane, crtc_, source_layer});
169 }
170
171 static std::vector<size_t> SetBitsToVector(uint64_t in, size_t *index_map) {
172   std::vector<size_t> out;
173   size_t msb = sizeof(in) * 8 - 1;
174   uint64_t mask = (uint64_t)1 << msb;
175   for (size_t i = msb; mask != (uint64_t)0; i--, mask >>= 1)
176     if (in & mask)
177       out.push_back(index_map[i]);
178   return out;
179 }
180
181 static void SeparateLayers(DrmHwcLayer *layers, size_t *used_layers,
182                            size_t num_used_layers,
183                            DrmHwcRect<int> *exclude_rects,
184                            size_t num_exclude_rects,
185                            std::vector<DrmCompositionRegion> &regions) {
186   if (num_used_layers > 64) {
187     ALOGE("Failed to separate layers because there are more than 64");
188     return;
189   }
190
191   if (num_used_layers + num_exclude_rects > 64) {
192     ALOGW(
193         "Exclusion rectangles are being truncated to make the rectangle count "
194         "fit into 64");
195     num_exclude_rects = 64 - num_used_layers;
196   }
197
198   // We inject all the exclude rects into the rects list. Any resulting rect
199   // that includes ANY of the first num_exclude_rects is rejected.
200   std::vector<DrmHwcRect<int>> layer_rects(num_used_layers + num_exclude_rects);
201   std::copy(exclude_rects, exclude_rects + num_exclude_rects,
202             layer_rects.begin());
203   std::transform(
204       used_layers, used_layers + num_used_layers,
205       layer_rects.begin() + num_exclude_rects,
206       [=](size_t layer_index) { return layers[layer_index].display_frame; });
207
208   std::vector<separate_rects::RectSet<uint64_t, int>> separate_regions;
209   separate_rects::separate_rects_64(layer_rects, &separate_regions);
210   uint64_t exclude_mask = ((uint64_t)1 << num_exclude_rects) - 1;
211
212   for (separate_rects::RectSet<uint64_t, int> &region : separate_regions) {
213     if (region.id_set.getBits() & exclude_mask)
214       continue;
215     regions.emplace_back(DrmCompositionRegion{
216         region.rect,
217         SetBitsToVector(region.id_set.getBits() >> num_exclude_rects,
218                         used_layers)});
219   }
220 }
221
222 int DrmDisplayComposition::CreateAndAssignReleaseFences() {
223   std::unordered_set<DrmHwcLayer *> squash_layers;
224   std::unordered_set<DrmHwcLayer *> pre_comp_layers;
225   std::unordered_set<DrmHwcLayer *> comp_layers;
226
227   for (const DrmCompositionRegion &region : squash_regions_) {
228     for (size_t source_layer_index : region.source_layers) {
229       DrmHwcLayer *source_layer = &layers_[source_layer_index];
230       squash_layers.emplace(source_layer);
231     }
232   }
233
234   for (const DrmCompositionRegion &region : pre_comp_regions_) {
235     for (size_t source_layer_index : region.source_layers) {
236       DrmHwcLayer *source_layer = &layers_[source_layer_index];
237       pre_comp_layers.emplace(source_layer);
238       squash_layers.erase(source_layer);
239     }
240   }
241
242   for (const DrmCompositionPlane &plane : composition_planes_) {
243     if (plane.source_layer <= DrmCompositionPlane::kSourceLayerMax) {
244       DrmHwcLayer *source_layer = &layers_[plane.source_layer];
245       comp_layers.emplace(source_layer);
246       pre_comp_layers.erase(source_layer);
247     }
248   }
249
250   for (DrmHwcLayer *layer : squash_layers) {
251     if (!layer->release_fence)
252       continue;
253     int ret = layer->release_fence.Set(CreateNextTimelineFence());
254     if (ret < 0)
255       return ret;
256   }
257   timeline_squash_done_ = timeline_;
258
259   for (DrmHwcLayer *layer : pre_comp_layers) {
260     if (!layer->release_fence)
261       continue;
262     int ret = layer->release_fence.Set(CreateNextTimelineFence());
263     if (ret < 0)
264       return ret;
265   }
266   timeline_pre_comp_done_ = timeline_;
267
268   for (DrmHwcLayer *layer : comp_layers) {
269     if (!layer->release_fence)
270       continue;
271     int ret = layer->release_fence.Set(CreateNextTimelineFence());
272     if (ret < 0)
273       return ret;
274   }
275
276   return 0;
277 }
278
279 int DrmDisplayComposition::Plan(SquashState *squash,
280                                 std::vector<DrmPlane *> *primary_planes,
281                                 std::vector<DrmPlane *> *overlay_planes) {
282   if (type_ != DRM_COMPOSITION_TYPE_FRAME)
283     return 0;
284
285   size_t planes_can_use =
286       CountUsablePlanes(crtc_, primary_planes, overlay_planes);
287   if (planes_can_use == 0) {
288     ALOGE("Display %d has no usable planes", crtc_->display());
289     return -ENODEV;
290   }
291
292   bool use_squash_framebuffer = false;
293   // Used to determine which layers were entirely squashed
294   std::vector<int> layer_squash_area(layers_.size(), 0);
295   // Used to avoid rerendering regions that were squashed
296   std::vector<DrmHwcRect<int>> exclude_rects;
297   if (squash != NULL && planes_can_use >= 3) {
298     if (geometry_changed_) {
299       squash->Init(layers_.data(), layers_.size());
300     } else {
301       std::vector<bool> changed_regions;
302       squash->GenerateHistory(layers_.data(), layers_.size(), changed_regions);
303
304       std::vector<bool> stable_regions;
305       squash->StableRegionsWithMarginalHistory(changed_regions, stable_regions);
306
307       // Only if SOME region is stable
308       use_squash_framebuffer =
309           std::find(stable_regions.begin(), stable_regions.end(), true) !=
310           stable_regions.end();
311
312       squash->RecordHistory(layers_.data(), layers_.size(), changed_regions);
313
314       // Changes in which regions are squashed triggers a rerender via
315       // squash_regions.
316       bool render_squash = squash->RecordAndCompareSquashed(stable_regions);
317
318       for (size_t region_index = 0; region_index < stable_regions.size();
319            region_index++) {
320         const SquashState::Region &region = squash->regions()[region_index];
321         if (!stable_regions[region_index])
322           continue;
323
324         exclude_rects.emplace_back(region.rect);
325
326         if (render_squash) {
327           squash_regions_.emplace_back();
328           squash_regions_.back().frame = region.rect;
329         }
330
331         int frame_area = region.rect.area();
332         // Source layers are sorted front to back i.e. top layer has lowest
333         // index.
334         for (size_t layer_index = layers_.size();
335              layer_index-- > 0;  // Yes, I double checked this
336              /* See condition */) {
337           if (!region.layer_refs[layer_index])
338             continue;
339           layer_squash_area[layer_index] += frame_area;
340           if (render_squash)
341             squash_regions_.back().source_layers.push_back(layer_index);
342         }
343       }
344     }
345   }
346
347   // All protected layers get first usage of planes
348   std::vector<size_t> layers_remaining;
349   for (size_t layer_index = 0; layer_index < layers_.size(); layer_index++) {
350     if (!layers_[layer_index].protected_usage() || planes_can_use == 0) {
351       layers_remaining.push_back(layer_index);
352       continue;
353     }
354     EmplaceCompositionPlane(layer_index, primary_planes, overlay_planes);
355     planes_can_use--;
356   }
357
358   if (planes_can_use == 0 && layers_remaining.size() > 0) {
359     ALOGE("Protected layers consumed all hardware planes");
360     return CreateAndAssignReleaseFences();
361   }
362
363   std::vector<size_t> layers_remaining_if_squash;
364   for (size_t layer_index : layers_remaining) {
365     if (layer_squash_area[layer_index] <
366         layers_[layer_index].display_frame.area())
367       layers_remaining_if_squash.push_back(layer_index);
368   }
369
370   if (use_squash_framebuffer) {
371     if (planes_can_use > 1 || layers_remaining_if_squash.size() == 0) {
372       layers_remaining = std::move(layers_remaining_if_squash);
373       planes_can_use--;  // Reserve plane for squashing
374     } else {
375       use_squash_framebuffer = false;  // The squash buffer is still rendered
376     }
377   }
378
379   if (layers_remaining.size() > planes_can_use)
380     planes_can_use--;  // Reserve one for pre-compositing
381
382   // Whatever planes that are not reserved get assigned a layer
383   size_t last_composition_layer = 0;
384   for (last_composition_layer = 0;
385        last_composition_layer < layers_remaining.size() && planes_can_use > 0;
386        last_composition_layer++, planes_can_use--) {
387     EmplaceCompositionPlane(layers_remaining[last_composition_layer],
388                             primary_planes, overlay_planes);
389   }
390
391   layers_remaining.erase(layers_remaining.begin(),
392                          layers_remaining.begin() + last_composition_layer);
393
394   if (layers_remaining.size() > 0) {
395     EmplaceCompositionPlane(DrmCompositionPlane::kSourcePreComp, primary_planes,
396                             overlay_planes);
397     SeparateLayers(layers_.data(), layers_remaining.data(),
398                    layers_remaining.size(), exclude_rects.data(),
399                    exclude_rects.size(), pre_comp_regions_);
400   }
401
402   if (use_squash_framebuffer) {
403     EmplaceCompositionPlane(DrmCompositionPlane::kSourceSquash, primary_planes,
404                             overlay_planes);
405   }
406
407   return CreateAndAssignReleaseFences();
408 }
409
410 static const char *DrmCompositionTypeToString(DrmCompositionType type) {
411   switch (type) {
412     case DRM_COMPOSITION_TYPE_EMPTY:
413       return "EMPTY";
414     case DRM_COMPOSITION_TYPE_FRAME:
415       return "FRAME";
416     case DRM_COMPOSITION_TYPE_DPMS:
417       return "DPMS";
418     case DRM_COMPOSITION_TYPE_MODESET:
419       return "MODESET";
420     default:
421       return "<invalid>";
422   }
423 }
424
425 static const char *DPMSModeToString(int dpms_mode) {
426   switch (dpms_mode) {
427     case DRM_MODE_DPMS_ON:
428       return "ON";
429     case DRM_MODE_DPMS_OFF:
430       return "OFF";
431     default:
432       return "<invalid>";
433   }
434 }
435
436 static void DumpBuffer(const DrmHwcBuffer &buffer, std::ostringstream *out) {
437   if (!buffer) {
438     *out << "buffer=<invalid>";
439     return;
440   }
441
442   *out << "buffer[w/h/format]=";
443   *out << buffer->width << "/" << buffer->height << "/" << buffer->format;
444 }
445
446 static void DumpTransform(uint32_t transform, std::ostringstream *out) {
447   *out << "[";
448
449   if (transform == 0)
450     *out << "IDENTITY";
451
452   bool separator = false;
453   if (transform & DrmHwcTransform::kFlipH) {
454     *out << "FLIPH";
455     separator = true;
456   }
457   if (transform & DrmHwcTransform::kFlipV) {
458     if (separator)
459       *out << "|";
460     *out << "FLIPV";
461     separator = true;
462   }
463   if (transform & DrmHwcTransform::kRotate90) {
464     if (separator)
465       *out << "|";
466     *out << "ROTATE90";
467     separator = true;
468   }
469   if (transform & DrmHwcTransform::kRotate180) {
470     if (separator)
471       *out << "|";
472     *out << "ROTATE180";
473     separator = true;
474   }
475   if (transform & DrmHwcTransform::kRotate270) {
476     if (separator)
477       *out << "|";
478     *out << "ROTATE270";
479     separator = true;
480   }
481
482   uint32_t valid_bits = DrmHwcTransform::kFlipH | DrmHwcTransform::kFlipH |
483                         DrmHwcTransform::kRotate90 |
484                         DrmHwcTransform::kRotate180 |
485                         DrmHwcTransform::kRotate270;
486   if (transform & ~valid_bits) {
487     if (separator)
488       *out << "|";
489     *out << "INVALID";
490   }
491   *out << "]";
492 }
493
494 static const char *BlendingToString(DrmHwcBlending blending) {
495   switch (blending) {
496     case DrmHwcBlending::kNone:
497       return "NONE";
498     case DrmHwcBlending::kPreMult:
499       return "PREMULT";
500     case DrmHwcBlending::kCoverage:
501       return "COVERAGE";
502     default:
503       return "<invalid>";
504   }
505 }
506
507 static void DumpRegion(const DrmCompositionRegion &region,
508                        std::ostringstream *out) {
509   *out << "frame";
510   region.frame.Dump(out);
511   *out << " source_layers=(";
512
513   const std::vector<size_t> &source_layers = region.source_layers;
514   for (size_t i = 0; i < source_layers.size(); i++) {
515     *out << source_layers[i];
516     if (i < source_layers.size() - 1) {
517       *out << " ";
518     }
519   }
520
521   *out << ")";
522 }
523
524 void DrmDisplayComposition::Dump(std::ostringstream *out) const {
525   *out << "----DrmDisplayComposition"
526        << " crtc=" << (crtc_ ? crtc_->id() : -1)
527        << " type=" << DrmCompositionTypeToString(type_);
528
529   switch (type_) {
530     case DRM_COMPOSITION_TYPE_DPMS:
531       *out << " dpms_mode=" << DPMSModeToString(dpms_mode_);
532       break;
533     case DRM_COMPOSITION_TYPE_MODESET:
534       *out << " display_mode=" << display_mode_.h_display() << "x"
535            << display_mode_.v_display();
536       break;
537     default:
538       break;
539   }
540
541   *out << " timeline[current/squash/pre-comp/done]=" << timeline_current_ << "/"
542        << timeline_squash_done_ << "/" << timeline_pre_comp_done_ << "/"
543        << timeline_ << "\n";
544
545   *out << "    Layers: count=" << layers_.size() << "\n";
546   for (size_t i = 0; i < layers_.size(); i++) {
547     const DrmHwcLayer &layer = layers_[i];
548     *out << "      [" << i << "] ";
549
550     DumpBuffer(layer.buffer, out);
551
552     if (layer.protected_usage())
553       *out << " protected";
554
555     *out << " transform=";
556     DumpTransform(layer.transform, out);
557     *out << " blending[a=" << (int)layer.alpha
558          << "]=" << BlendingToString(layer.blending) << " source_crop";
559     layer.source_crop.Dump(out);
560     *out << " display_frame";
561     layer.display_frame.Dump(out);
562
563     *out << "\n";
564   }
565
566   *out << "    Planes: count=" << composition_planes_.size() << "\n";
567   for (size_t i = 0; i < composition_planes_.size(); i++) {
568     const DrmCompositionPlane &comp_plane = composition_planes_[i];
569     *out << "      [" << i << "]"
570          << " plane=" << (comp_plane.plane ? comp_plane.plane->id() : -1)
571          << " source_layer=";
572     if (comp_plane.source_layer <= DrmCompositionPlane::kSourceLayerMax) {
573       *out << comp_plane.source_layer;
574     } else {
575       switch (comp_plane.source_layer) {
576         case DrmCompositionPlane::kSourceNone:
577           *out << "NONE";
578           break;
579         case DrmCompositionPlane::kSourcePreComp:
580           *out << "PRECOMP";
581           break;
582         case DrmCompositionPlane::kSourceSquash:
583           *out << "SQUASH";
584           break;
585         default:
586           *out << "<invalid>";
587           break;
588       }
589     }
590
591     *out << "\n";
592   }
593
594   *out << "    Squash Regions: count=" << squash_regions_.size() << "\n";
595   for (size_t i = 0; i < squash_regions_.size(); i++) {
596     *out << "      [" << i << "] ";
597     DumpRegion(squash_regions_[i], out);
598     *out << "\n";
599   }
600
601   *out << "    Pre-Comp Regions: count=" << pre_comp_regions_.size() << "\n";
602   for (size_t i = 0; i < pre_comp_regions_.size(); i++) {
603     *out << "      [" << i << "] ";
604     DumpRegion(pre_comp_regions_[i], out);
605     *out << "\n";
606   }
607 }
608 }