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