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       ALOGE("Failed to set the release fence (squash) %d", ret);
    263       return ret;
    264     }
    265   }
    266   timeline_squash_done_ = timeline_;
    267 
    268   for (DrmHwcLayer *layer : pre_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   timeline_pre_comp_done_ = timeline_;
    276 
    277   for (DrmHwcLayer *layer : comp_layers) {
    278     if (!layer->release_fence)
    279       continue;
    280     int ret = layer->release_fence.Set(CreateNextTimelineFence());
    281     if (ret < 0) {
    282       ALOGE("Failed to set the release fence (comp) %d", ret);
    283       return ret;
    284     }
    285   }
    286 
    287   return 0;
    288 }
    289 
    290 int DrmDisplayComposition::Plan(SquashState *squash,
    291                                 std::vector<DrmPlane *> *primary_planes,
    292                                 std::vector<DrmPlane *> *overlay_planes) {
    293   if (type_ != DRM_COMPOSITION_TYPE_FRAME)
    294     return 0;
    295 
    296   // Used to track which layers should be sent to the planner. We exclude layers
    297   // that are entirely squashed so the planner can provision a precomposition
    298   // layer as appropriate (ex: if 5 layers are squashed and 1 is not, we don't
    299   // want to plan a precomposition layer that will be comprised of the already
    300   // squashed layers).
    301   std::map<size_t, DrmHwcLayer *> to_composite;
    302 
    303   bool use_squash_framebuffer = false;
    304   // Used to determine which layers were entirely squashed
    305   std::vector<int> layer_squash_area(layers_.size(), 0);
    306   // Used to avoid rerendering regions that were squashed
    307   std::vector<DrmHwcRect<int>> exclude_rects;
    308   if (squash != NULL) {
    309     if (geometry_changed_) {
    310       squash->Init(layers_.data(), layers_.size());
    311     } else {
    312       std::vector<bool> changed_regions;
    313       squash->GenerateHistory(layers_.data(), layers_.size(), changed_regions);
    314 
    315       std::vector<bool> stable_regions;
    316       squash->StableRegionsWithMarginalHistory(changed_regions, stable_regions);
    317 
    318       // Only if SOME region is stable
    319       use_squash_framebuffer =
    320           std::find(stable_regions.begin(), stable_regions.end(), true) !=
    321           stable_regions.end();
    322 
    323       squash->RecordHistory(layers_.data(), layers_.size(), changed_regions);
    324 
    325       // Changes in which regions are squashed triggers a rerender via
    326       // squash_regions.
    327       bool render_squash = squash->RecordAndCompareSquashed(stable_regions);
    328 
    329       for (size_t region_index = 0; region_index < stable_regions.size();
    330            region_index++) {
    331         const SquashState::Region &region = squash->regions()[region_index];
    332         if (!stable_regions[region_index])
    333           continue;
    334 
    335         exclude_rects.emplace_back(region.rect);
    336 
    337         if (render_squash) {
    338           squash_regions_.emplace_back();
    339           squash_regions_.back().frame = region.rect;
    340         }
    341 
    342         int frame_area = region.rect.area();
    343         // Source layers are sorted front to back i.e. top layer has lowest
    344         // index.
    345         for (size_t layer_index = layers_.size();
    346              layer_index-- > 0;  // Yes, I double checked this
    347              /* See condition */) {
    348           if (!region.layer_refs[layer_index])
    349             continue;
    350           layer_squash_area[layer_index] += frame_area;
    351           if (render_squash)
    352             squash_regions_.back().source_layers.push_back(layer_index);
    353         }
    354       }
    355     }
    356 
    357     for (size_t i = 0; i < layers_.size(); ++i) {
    358       if (layer_squash_area[i] < layers_[i].display_frame.area())
    359         to_composite.emplace(std::make_pair(i, &layers_[i]));
    360     }
    361   } else {
    362     for (size_t i = 0; i < layers_.size(); ++i)
    363       to_composite.emplace(std::make_pair(i, &layers_[i]));
    364   }
    365 
    366   int ret;
    367   std::vector<DrmCompositionPlane> plan;
    368   std::tie(ret, composition_planes_) =
    369       planner_->ProvisionPlanes(to_composite, use_squash_framebuffer, crtc_,
    370                                 primary_planes, overlay_planes);
    371   if (ret) {
    372     ALOGE("Planner failed provisioning planes ret=%d", ret);
    373     return ret;
    374   }
    375 
    376   // Remove the planes we used from the pool before returning. This ensures they
    377   // won't be reused by another display in the composition.
    378   for (auto &i : composition_planes_) {
    379     if (!i.plane())
    380       continue;
    381 
    382     // make sure that source layers are ordered based on zorder
    383     std::sort(i.source_layers().begin(), i.source_layers().end());
    384 
    385     std::vector<DrmPlane *> *container;
    386     if (i.plane()->type() == DRM_PLANE_TYPE_PRIMARY)
    387       container = primary_planes;
    388     else
    389       container = overlay_planes;
    390     for (auto j = container->begin(); j != container->end(); ++j) {
    391       if (*j == i.plane()) {
    392         container->erase(j);
    393         break;
    394       }
    395     }
    396   }
    397 
    398   return FinalizeComposition(exclude_rects.data(), exclude_rects.size());
    399 }
    400 
    401 int DrmDisplayComposition::FinalizeComposition() {
    402   return FinalizeComposition(NULL, 0);
    403 }
    404 
    405 int DrmDisplayComposition::FinalizeComposition(DrmHwcRect<int> *exclude_rects,
    406                                                size_t num_exclude_rects) {
    407   SeparateLayers(exclude_rects, num_exclude_rects);
    408   return CreateAndAssignReleaseFences();
    409 }
    410 
    411 static const char *DrmCompositionTypeToString(DrmCompositionType type) {
    412   switch (type) {
    413     case DRM_COMPOSITION_TYPE_EMPTY:
    414       return "EMPTY";
    415     case DRM_COMPOSITION_TYPE_FRAME:
    416       return "FRAME";
    417     case DRM_COMPOSITION_TYPE_DPMS:
    418       return "DPMS";
    419     case DRM_COMPOSITION_TYPE_MODESET:
    420       return "MODESET";
    421     default:
    422       return "<invalid>";
    423   }
    424 }
    425 
    426 static const char *DPMSModeToString(int dpms_mode) {
    427   switch (dpms_mode) {
    428     case DRM_MODE_DPMS_ON:
    429       return "ON";
    430     case DRM_MODE_DPMS_OFF:
    431       return "OFF";
    432     default:
    433       return "<invalid>";
    434   }
    435 }
    436 
    437 static void DumpBuffer(const DrmHwcBuffer &buffer, std::ostringstream *out) {
    438   if (!buffer) {
    439     *out << "buffer=<invalid>";
    440     return;
    441   }
    442 
    443   *out << "buffer[w/h/format]=";
    444   *out << buffer->width << "/" << buffer->height << "/" << buffer->format;
    445 }
    446 
    447 static void DumpTransform(uint32_t transform, std::ostringstream *out) {
    448   *out << "[";
    449 
    450   if (transform == 0)
    451     *out << "IDENTITY";
    452 
    453   bool separator = false;
    454   if (transform & DrmHwcTransform::kFlipH) {
    455     *out << "FLIPH";
    456     separator = true;
    457   }
    458   if (transform & DrmHwcTransform::kFlipV) {
    459     if (separator)
    460       *out << "|";
    461     *out << "FLIPV";
    462     separator = true;
    463   }
    464   if (transform & DrmHwcTransform::kRotate90) {
    465     if (separator)
    466       *out << "|";
    467     *out << "ROTATE90";
    468     separator = true;
    469   }
    470   if (transform & DrmHwcTransform::kRotate180) {
    471     if (separator)
    472       *out << "|";
    473     *out << "ROTATE180";
    474     separator = true;
    475   }
    476   if (transform & DrmHwcTransform::kRotate270) {
    477     if (separator)
    478       *out << "|";
    479     *out << "ROTATE270";
    480     separator = true;
    481   }
    482 
    483   uint32_t valid_bits = DrmHwcTransform::kFlipH | DrmHwcTransform::kFlipH |
    484                         DrmHwcTransform::kRotate90 |
    485                         DrmHwcTransform::kRotate180 |
    486                         DrmHwcTransform::kRotate270;
    487   if (transform & ~valid_bits) {
    488     if (separator)
    489       *out << "|";
    490     *out << "INVALID";
    491   }
    492   *out << "]";
    493 }
    494 
    495 static const char *BlendingToString(DrmHwcBlending blending) {
    496   switch (blending) {
    497     case DrmHwcBlending::kNone:
    498       return "NONE";
    499     case DrmHwcBlending::kPreMult:
    500       return "PREMULT";
    501     case DrmHwcBlending::kCoverage:
    502       return "COVERAGE";
    503     default:
    504       return "<invalid>";
    505   }
    506 }
    507 
    508 static void DumpRegion(const DrmCompositionRegion &region,
    509                        std::ostringstream *out) {
    510   *out << "frame";
    511   region.frame.Dump(out);
    512   *out << " source_layers=(";
    513 
    514   const std::vector<size_t> &source_layers = region.source_layers;
    515   for (size_t i = 0; i < source_layers.size(); i++) {
    516     *out << source_layers[i];
    517     if (i < source_layers.size() - 1) {
    518       *out << " ";
    519     }
    520   }
    521 
    522   *out << ")";
    523 }
    524 
    525 void DrmDisplayComposition::Dump(std::ostringstream *out) const {
    526   *out << "----DrmDisplayComposition"
    527        << " crtc=" << (crtc_ ? crtc_->id() : -1)
    528        << " type=" << DrmCompositionTypeToString(type_);
    529 
    530   switch (type_) {
    531     case DRM_COMPOSITION_TYPE_DPMS:
    532       *out << " dpms_mode=" << DPMSModeToString(dpms_mode_);
    533       break;
    534     case DRM_COMPOSITION_TYPE_MODESET:
    535       *out << " display_mode=" << display_mode_.h_display() << "x"
    536            << display_mode_.v_display();
    537       break;
    538     default:
    539       break;
    540   }
    541 
    542   *out << " timeline[current/squash/pre-comp/done]=" << timeline_current_ << "/"
    543        << timeline_squash_done_ << "/" << timeline_pre_comp_done_ << "/"
    544        << timeline_ << "\n";
    545 
    546   *out << "    Layers: count=" << layers_.size() << "\n";
    547   for (size_t i = 0; i < layers_.size(); i++) {
    548     const DrmHwcLayer &layer = layers_[i];
    549     *out << "      [" << i << "] ";
    550 
    551     DumpBuffer(layer.buffer, out);
    552 
    553     if (layer.protected_usage())
    554       *out << " protected";
    555 
    556     *out << " transform=";
    557     DumpTransform(layer.transform, out);
    558     *out << " blending[a=" << (int)layer.alpha
    559          << "]=" << BlendingToString(layer.blending) << " source_crop";
    560     layer.source_crop.Dump(out);
    561     *out << " display_frame";
    562     layer.display_frame.Dump(out);
    563 
    564     *out << "\n";
    565   }
    566 
    567   *out << "    Planes: count=" << composition_planes_.size() << "\n";
    568   for (size_t i = 0; i < composition_planes_.size(); i++) {
    569     const DrmCompositionPlane &comp_plane = composition_planes_[i];
    570     *out << "      [" << i << "]"
    571          << " plane=" << (comp_plane.plane() ? comp_plane.plane()->id() : -1)
    572          << " type=";
    573     switch (comp_plane.type()) {
    574       case DrmCompositionPlane::Type::kDisable:
    575         *out << "DISABLE";
    576         break;
    577       case DrmCompositionPlane::Type::kLayer:
    578         *out << "LAYER";
    579         break;
    580       case DrmCompositionPlane::Type::kPrecomp:
    581         *out << "PRECOMP";
    582         break;
    583       case DrmCompositionPlane::Type::kSquash:
    584         *out << "SQUASH";
    585         break;
    586       default:
    587         *out << "<invalid>";
    588         break;
    589     }
    590 
    591     *out << " source_layer=";
    592     for (auto i : comp_plane.source_layers()) {
    593       *out << i << " ";
    594     }
    595     *out << "\n";
    596   }
    597 
    598   *out << "    Squash Regions: count=" << squash_regions_.size() << "\n";
    599   for (size_t i = 0; i < squash_regions_.size(); i++) {
    600     *out << "      [" << i << "] ";
    601     DumpRegion(squash_regions_[i], out);
    602     *out << "\n";
    603   }
    604 
    605   *out << "    Pre-Comp Regions: count=" << pre_comp_regions_.size() << "\n";
    606   for (size_t i = 0; i < pre_comp_regions_.size(); i++) {
    607     *out << "      [" << i << "] ";
    608     DumpRegion(pre_comp_regions_[i], out);
    609     *out << "\n";
    610   }
    611 }
    612 }
    613