OSDN Git Service

drm_hwcomposer: polish for old DRM wrapper code
[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 static std::vector<size_t> SetBitsToVector(uint64_t in, size_t *index_map) {
158   std::vector<size_t> out;
159   size_t msb = sizeof(in) * 8 - 1;
160   uint64_t mask = (uint64_t)1 << msb;
161   for (size_t i = msb; mask != (uint64_t)0; i--, mask >>= 1)
162     if (in & mask)
163       out.push_back(index_map[i]);
164   return out;
165 }
166
167 static void SeparateLayers(DrmHwcLayer *layers, size_t *used_layers,
168                            size_t num_used_layers,
169                            DrmHwcRect<int> *exclude_rects,
170                            size_t num_exclude_rects,
171                            std::vector<DrmCompositionRegion> &regions) {
172   if (num_used_layers > 64) {
173     ALOGE("Failed to separate layers because there are more than 64");
174     return;
175   }
176
177   if (num_used_layers + num_exclude_rects > 64) {
178     ALOGW(
179         "Exclusion rectangles are being truncated to make the rectangle count "
180         "fit into 64");
181     num_exclude_rects = 64 - num_used_layers;
182   }
183
184   // We inject all the exclude rects into the rects list. Any resulting rect
185   // that includes ANY of the first num_exclude_rects is rejected.
186   std::vector<DrmHwcRect<int>> layer_rects(num_used_layers + num_exclude_rects);
187   std::copy(exclude_rects, exclude_rects + num_exclude_rects,
188             layer_rects.begin());
189   std::transform(
190       used_layers, used_layers + num_used_layers,
191       layer_rects.begin() + num_exclude_rects,
192       [=](size_t layer_index) { return layers[layer_index].display_frame; });
193
194   std::vector<seperate_rects::RectSet<uint64_t, int>> seperate_regions;
195   seperate_rects::seperate_rects_64(layer_rects, &seperate_regions);
196   uint64_t exclude_mask = ((uint64_t)1 << num_exclude_rects) - 1;
197
198   for (seperate_rects::RectSet<uint64_t, int> &region : seperate_regions) {
199     if (region.id_set.getBits() & exclude_mask)
200       continue;
201     regions.emplace_back(DrmCompositionRegion{
202         region.rect,
203         SetBitsToVector(region.id_set.getBits() >> num_exclude_rects,
204                         used_layers)});
205   }
206 }
207
208 int DrmDisplayComposition::CreateAndAssignReleaseFences() {
209   std::unordered_set<DrmHwcLayer *> squash_layers;
210   std::unordered_set<DrmHwcLayer *> pre_comp_layers;
211   std::unordered_set<DrmHwcLayer *> comp_layers;
212
213   for (const DrmCompositionRegion &region : squash_regions_) {
214     for (size_t source_layer_index : region.source_layers) {
215       DrmHwcLayer *source_layer = &layers_[source_layer_index];
216       squash_layers.emplace(source_layer);
217     }
218   }
219
220   for (const DrmCompositionRegion &region : pre_comp_regions_) {
221     for (size_t source_layer_index : region.source_layers) {
222       DrmHwcLayer *source_layer = &layers_[source_layer_index];
223       pre_comp_layers.emplace(source_layer);
224       squash_layers.erase(source_layer);
225     }
226   }
227
228   for (const DrmCompositionPlane &plane : composition_planes_) {
229     if (plane.source_layer <= DrmCompositionPlane::kSourceLayerMax) {
230       DrmHwcLayer *source_layer = &layers_[plane.source_layer];
231       comp_layers.emplace(source_layer);
232       pre_comp_layers.erase(source_layer);
233     }
234   }
235
236   for (DrmHwcLayer *layer : squash_layers) {
237     int ret = layer->release_fence.Set(CreateNextTimelineFence());
238     if (ret < 0)
239       return ret;
240   }
241   timeline_squash_done_ = timeline_;
242
243   for (DrmHwcLayer *layer : pre_comp_layers) {
244     int ret = layer->release_fence.Set(CreateNextTimelineFence());
245     if (ret < 0)
246       return ret;
247   }
248   timeline_pre_comp_done_ = timeline_;
249
250   for (DrmHwcLayer *layer : comp_layers) {
251     int ret = layer->release_fence.Set(CreateNextTimelineFence());
252     if (ret < 0)
253       return ret;
254   }
255
256   return 0;
257 }
258
259 int DrmDisplayComposition::Plan(SquashState *squash,
260                                 std::vector<DrmPlane *> *primary_planes,
261                                 std::vector<DrmPlane *> *overlay_planes) {
262   if (type_ != DRM_COMPOSITION_TYPE_FRAME)
263     return 0;
264
265   size_t planes_can_use =
266       CountUsablePlanes(crtc_, primary_planes, overlay_planes);
267   if (planes_can_use == 0) {
268     ALOGE("Display %d has no usable planes", crtc_->display());
269     return -ENODEV;
270   }
271
272   bool use_squash_framebuffer = false;
273   // Used to determine which layers were entirely squashed
274   std::vector<int> layer_squash_area(layers_.size(), 0);
275   // Used to avoid rerendering regions that were squashed
276   std::vector<DrmHwcRect<int>> exclude_rects;
277   if (squash != NULL && planes_can_use >= 3) {
278     if (geometry_changed_) {
279       squash->Init(layers_.data(), layers_.size());
280     } else {
281       std::vector<bool> changed_regions;
282       squash->GenerateHistory(layers_.data(), layers_.size(), changed_regions);
283
284       std::vector<bool> stable_regions;
285       squash->StableRegionsWithMarginalHistory(changed_regions, stable_regions);
286
287       // Only if SOME region is stable
288       use_squash_framebuffer =
289           std::find(stable_regions.begin(), stable_regions.end(), true) !=
290           stable_regions.end();
291
292       squash->RecordHistory(layers_.data(), layers_.size(), changed_regions);
293
294       // Changes in which regions are squashed triggers a rerender via
295       // squash_regions.
296       bool render_squash = squash->RecordAndCompareSquashed(stable_regions);
297
298       for (size_t region_index = 0; region_index < stable_regions.size();
299            region_index++) {
300         const SquashState::Region &region = squash->regions()[region_index];
301         if (!stable_regions[region_index])
302           continue;
303
304         exclude_rects.emplace_back(region.rect);
305
306         if (render_squash) {
307           squash_regions_.emplace_back();
308           squash_regions_.back().frame = region.rect;
309         }
310
311         int frame_area = region.rect.area();
312         // Source layers are sorted front to back i.e. top layer has lowest
313         // index.
314         for (size_t layer_index = layers_.size();
315              layer_index-- > 0;  // Yes, I double checked this
316              /* See condition */) {
317           if (!region.layer_refs[layer_index])
318             continue;
319           layer_squash_area[layer_index] += frame_area;
320           if (render_squash)
321             squash_regions_.back().source_layers.push_back(layer_index);
322         }
323       }
324     }
325   }
326
327   std::vector<size_t> layers_remaining;
328   for (size_t layer_index = 0; layer_index < layers_.size(); layer_index++) {
329     // Skip layers that were completely squashed
330     if (layer_squash_area[layer_index] >=
331         layers_[layer_index].display_frame.area()) {
332       continue;
333     }
334
335     layers_remaining.push_back(layer_index);
336   }
337
338   if (use_squash_framebuffer)
339     planes_can_use--;
340
341   if (layers_remaining.size() > planes_can_use)
342     planes_can_use--;
343
344   size_t last_composition_layer = 0;
345   for (last_composition_layer = 0;
346        last_composition_layer < layers_remaining.size() && planes_can_use > 0;
347        last_composition_layer++, planes_can_use--) {
348     composition_planes_.emplace_back(
349         DrmCompositionPlane{TakePlane(crtc_, primary_planes, overlay_planes),
350                             crtc_, layers_remaining[last_composition_layer]});
351   }
352
353   layers_remaining.erase(layers_remaining.begin(),
354                          layers_remaining.begin() + last_composition_layer);
355
356   if (layers_remaining.size() > 0) {
357     composition_planes_.emplace_back(
358         DrmCompositionPlane{TakePlane(crtc_, primary_planes, overlay_planes),
359                             crtc_, DrmCompositionPlane::kSourcePreComp});
360
361     SeparateLayers(layers_.data(), layers_remaining.data(),
362                    layers_remaining.size(), exclude_rects.data(),
363                    exclude_rects.size(), pre_comp_regions_);
364   }
365
366   if (use_squash_framebuffer) {
367     composition_planes_.emplace_back(
368         DrmCompositionPlane{TakePlane(crtc_, primary_planes, overlay_planes),
369                             crtc_, DrmCompositionPlane::kSourceSquash});
370   }
371
372   return CreateAndAssignReleaseFences();
373 }
374
375 static const char *DrmCompositionTypeToString(DrmCompositionType type) {
376   switch (type) {
377     case DRM_COMPOSITION_TYPE_EMPTY:
378       return "EMPTY";
379     case DRM_COMPOSITION_TYPE_FRAME:
380       return "FRAME";
381     case DRM_COMPOSITION_TYPE_DPMS:
382       return "DPMS";
383     case DRM_COMPOSITION_TYPE_MODESET:
384       return "MODESET";
385     default:
386       return "<invalid>";
387   }
388 }
389
390 static const char *DPMSModeToString(int dpms_mode) {
391   switch (dpms_mode) {
392     case DRM_MODE_DPMS_ON:
393       return "ON";
394     case DRM_MODE_DPMS_OFF:
395       return "OFF";
396     default:
397       return "<invalid>";
398   }
399 }
400
401 static void DumpBuffer(const DrmHwcBuffer &buffer, std::ostringstream *out) {
402   if (!buffer) {
403     *out << "buffer=<invalid>";
404     return;
405   }
406
407   *out << "buffer[w/h/format]=";
408   *out << buffer->width << "/" << buffer->height << "/" << buffer->format;
409 }
410
411 static const char *TransformToString(DrmHwcTransform transform) {
412   switch (transform) {
413     case DrmHwcTransform::kIdentity:
414       return "IDENTITY";
415     case DrmHwcTransform::kFlipH:
416       return "FLIPH";
417     case DrmHwcTransform::kFlipV:
418       return "FLIPV";
419     case DrmHwcTransform::kRotate90:
420       return "ROTATE90";
421     case DrmHwcTransform::kRotate180:
422       return "ROTATE180";
423     case DrmHwcTransform::kRotate270:
424       return "ROTATE270";
425     default:
426       return "<invalid>";
427   }
428 }
429
430 static const char *BlendingToString(DrmHwcBlending blending) {
431   switch (blending) {
432     case DrmHwcBlending::kNone:
433       return "NONE";
434     case DrmHwcBlending::kPreMult:
435       return "PREMULT";
436     case DrmHwcBlending::kCoverage:
437       return "COVERAGE";
438     default:
439       return "<invalid>";
440   }
441 }
442
443 static void DumpRegion(const DrmCompositionRegion &region,
444                        std::ostringstream *out) {
445   *out << "frame";
446   region.frame.Dump(out);
447   *out << " source_layers=(";
448
449   const std::vector<size_t> &source_layers = region.source_layers;
450   for (size_t i = 0; i < source_layers.size(); i++) {
451     *out << source_layers[i];
452     if (i < source_layers.size() - 1) {
453       *out << " ";
454     }
455   }
456
457   *out << ")";
458 }
459
460 void DrmDisplayComposition::Dump(std::ostringstream *out) const {
461   *out << "----DrmDisplayComposition"
462        << " crtc=" << (crtc_ ? crtc_->id() : -1)
463        << " type=" << DrmCompositionTypeToString(type_);
464
465   switch (type_) {
466     case DRM_COMPOSITION_TYPE_DPMS:
467       *out << " dpms_mode=" << DPMSModeToString(dpms_mode_);
468       break;
469     case DRM_COMPOSITION_TYPE_MODESET:
470       *out << " display_mode=" << display_mode_.h_display() << "x"
471            << display_mode_.v_display();
472       break;
473     default:
474       break;
475   }
476
477   *out << " timeline[current/squash/pre-comp/done]=" << timeline_current_ << "/"
478        << timeline_squash_done_ << "/" << timeline_pre_comp_done_ << "/"
479        << timeline_ << "\n";
480
481   *out << "    Layers: count=" << layers_.size() << "\n";
482   for (size_t i = 0; i < layers_.size(); i++) {
483     const DrmHwcLayer &layer = layers_[i];
484     *out << "      [" << i << "] ";
485
486     DumpBuffer(layer.buffer, out);
487
488     *out << " transform=" << TransformToString(layer.transform)
489          << " blending[a=" << (int)layer.alpha
490          << "]=" << BlendingToString(layer.blending) << " source_crop";
491     layer.source_crop.Dump(out);
492     *out << " display_frame";
493     layer.display_frame.Dump(out);
494
495     *out << "\n";
496   }
497
498   *out << "    Planes: count=" << composition_planes_.size() << "\n";
499   for (size_t i = 0; i < composition_planes_.size(); i++) {
500     const DrmCompositionPlane &comp_plane = composition_planes_[i];
501     *out << "      [" << i << "]"
502          << " plane=" << (comp_plane.plane ? comp_plane.plane->id() : -1)
503          << " source_layer=";
504     if (comp_plane.source_layer <= DrmCompositionPlane::kSourceLayerMax) {
505       *out << comp_plane.source_layer;
506     } else {
507       switch (comp_plane.source_layer) {
508         case DrmCompositionPlane::kSourceNone:
509           *out << "NONE";
510           break;
511         case DrmCompositionPlane::kSourcePreComp:
512           *out << "PRECOMP";
513           break;
514         case DrmCompositionPlane::kSourceSquash:
515           *out << "SQUASH";
516           break;
517         default:
518           *out << "<invalid>";
519           break;
520       }
521     }
522
523     *out << "\n";
524   }
525
526   *out << "    Squash Regions: count=" << squash_regions_.size() << "\n";
527   for (size_t i = 0; i < squash_regions_.size(); i++) {
528     *out << "      [" << i << "] ";
529     DumpRegion(squash_regions_[i], out);
530     *out << "\n";
531   }
532
533   *out << "    Pre-Comp Regions: count=" << pre_comp_regions_.size() << "\n";
534   for (size_t i = 0; i < pre_comp_regions_.size(); i++) {
535     *out << "      [" << i << "] ";
536     DumpRegion(pre_comp_regions_[i], out);
537     *out << "\n";
538   }
539 }
540 }