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 ATRACE_TAG ATRACE_TAG_GRAPHICS
     18 #define LOG_TAG "hwc-drm-display-compositor"
     19 
     20 #include "drmdisplaycompositor.h"
     21 
     22 #include <pthread.h>
     23 #include <sched.h>
     24 #include <stdlib.h>
     25 #include <time.h>
     26 #include <sstream>
     27 #include <vector>
     28 
     29 #include <cutils/log.h>
     30 #include <drm/drm_mode.h>
     31 #include <sync/sync.h>
     32 #include <utils/Trace.h>
     33 
     34 #include "autolock.h"
     35 #include "drmcrtc.h"
     36 #include "drmplane.h"
     37 #include "drmresources.h"
     38 #include "glworker.h"
     39 
     40 #define DRM_DISPLAY_COMPOSITOR_MAX_QUEUE_DEPTH 2
     41 
     42 namespace android {
     43 
     44 void SquashState::Init(DrmHwcLayer *layers, size_t num_layers) {
     45   generation_number_++;
     46   valid_history_ = 0;
     47   regions_.clear();
     48   last_handles_.clear();
     49 
     50   std::vector<DrmHwcRect<int>> in_rects;
     51   for (size_t i = 0; i < num_layers; i++) {
     52     DrmHwcLayer *layer = &layers[i];
     53     in_rects.emplace_back(layer->display_frame);
     54     last_handles_.push_back(layer->sf_handle);
     55   }
     56 
     57   std::vector<separate_rects::RectSet<uint64_t, int>> out_regions;
     58   separate_rects::separate_rects_64(in_rects, &out_regions);
     59 
     60   for (const separate_rects::RectSet<uint64_t, int> &out_region : out_regions) {
     61     regions_.emplace_back();
     62     Region &region = regions_.back();
     63     region.rect = out_region.rect;
     64     region.layer_refs = out_region.id_set.getBits();
     65   }
     66 }
     67 
     68 void SquashState::GenerateHistory(DrmHwcLayer *layers, size_t num_layers,
     69                                   std::vector<bool> &changed_regions) const {
     70   changed_regions.resize(regions_.size());
     71   if (num_layers != last_handles_.size()) {
     72     ALOGE("SquashState::GenerateHistory expected %zu layers but got %zu layers",
     73           last_handles_.size(), num_layers);
     74     return;
     75   }
     76   std::bitset<kMaxLayers> changed_layers;
     77   for (size_t i = 0; i < last_handles_.size(); i++) {
     78     DrmHwcLayer *layer = &layers[i];
     79     // Protected layers can't be squashed so we treat them as constantly
     80     // changing.
     81     if (layer->protected_usage() || last_handles_[i] != layer->sf_handle)
     82       changed_layers.set(i);
     83   }
     84 
     85   for (size_t i = 0; i < regions_.size(); i++) {
     86     changed_regions[i] = (regions_[i].layer_refs & changed_layers).any();
     87   }
     88 }
     89 
     90 void SquashState::StableRegionsWithMarginalHistory(
     91     const std::vector<bool> &changed_regions,
     92     std::vector<bool> &stable_regions) const {
     93   stable_regions.resize(regions_.size());
     94   for (size_t i = 0; i < regions_.size(); i++) {
     95     stable_regions[i] = !changed_regions[i] && is_stable(i);
     96   }
     97 }
     98 
     99 void SquashState::RecordHistory(DrmHwcLayer *layers, size_t num_layers,
    100                                 const std::vector<bool> &changed_regions) {
    101   if (num_layers != last_handles_.size()) {
    102     ALOGE("SquashState::RecordHistory expected %zu layers but got %zu layers",
    103           last_handles_.size(), num_layers);
    104     return;
    105   }
    106   if (changed_regions.size() != regions_.size()) {
    107     ALOGE("SquashState::RecordHistory expected %zu regions but got %zu regions",
    108           regions_.size(), changed_regions.size());
    109     return;
    110   }
    111 
    112   for (size_t i = 0; i < last_handles_.size(); i++) {
    113     DrmHwcLayer *layer = &layers[i];
    114     last_handles_[i] = layer->sf_handle;
    115   }
    116 
    117   for (size_t i = 0; i < regions_.size(); i++) {
    118     regions_[i].change_history <<= 1;
    119     regions_[i].change_history.set(/* LSB */ 0, changed_regions[i]);
    120   }
    121 
    122   valid_history_++;
    123 }
    124 
    125 bool SquashState::RecordAndCompareSquashed(
    126     const std::vector<bool> &squashed_regions) {
    127   if (squashed_regions.size() != regions_.size()) {
    128     ALOGE(
    129         "SquashState::RecordAndCompareSquashed expected %zu regions but got "
    130         "%zu regions",
    131         regions_.size(), squashed_regions.size());
    132     return false;
    133   }
    134   bool changed = false;
    135   for (size_t i = 0; i < regions_.size(); i++) {
    136     if (regions_[i].squashed != squashed_regions[i]) {
    137       regions_[i].squashed = squashed_regions[i];
    138       changed = true;
    139     }
    140   }
    141   return changed;
    142 }
    143 
    144 void SquashState::Dump(std::ostringstream *out) const {
    145   *out << "----SquashState generation=" << generation_number_
    146        << " history=" << valid_history_ << "\n"
    147        << "    Regions: count=" << regions_.size() << "\n";
    148   for (size_t i = 0; i < regions_.size(); i++) {
    149     const Region &region = regions_[i];
    150     *out << "      [" << i << "]"
    151          << " history=" << region.change_history << " rect";
    152     region.rect.Dump(out);
    153     *out << " layers=(";
    154     bool first = true;
    155     for (size_t layer_index = 0; layer_index < kMaxLayers; layer_index++) {
    156       if ((region.layer_refs &
    157            std::bitset<kMaxLayers>((size_t)1 << layer_index))
    158               .any()) {
    159         if (!first)
    160           *out << " ";
    161         first = false;
    162         *out << layer_index;
    163       }
    164     }
    165     *out << ")";
    166     if (region.squashed)
    167       *out << " squashed";
    168     *out << "\n";
    169   }
    170 }
    171 
    172 static bool UsesSquash(const std::vector<DrmCompositionPlane> &comp_planes) {
    173   return std::any_of(comp_planes.begin(), comp_planes.end(),
    174                      [](const DrmCompositionPlane &plane) {
    175     return plane.type() == DrmCompositionPlane::Type::kSquash;
    176   });
    177 }
    178 
    179 DrmDisplayCompositor::FrameWorker::FrameWorker(DrmDisplayCompositor *compositor)
    180     : Worker("frame-worker", HAL_PRIORITY_URGENT_DISPLAY),
    181       compositor_(compositor) {
    182 }
    183 
    184 DrmDisplayCompositor::FrameWorker::~FrameWorker() {
    185 }
    186 
    187 int DrmDisplayCompositor::FrameWorker::Init() {
    188   return InitWorker();
    189 }
    190 
    191 void DrmDisplayCompositor::FrameWorker::QueueFrame(
    192     std::unique_ptr<DrmDisplayComposition> composition, int status) {
    193   Lock();
    194   FrameState frame;
    195   frame.composition = std::move(composition);
    196   frame.status = status;
    197   frame_queue_.push(std::move(frame));
    198   SignalLocked();
    199   Unlock();
    200 }
    201 
    202 void DrmDisplayCompositor::FrameWorker::Routine() {
    203   int ret = Lock();
    204   if (ret) {
    205     ALOGE("Failed to lock worker, %d", ret);
    206     return;
    207   }
    208 
    209   int wait_ret = 0;
    210   if (frame_queue_.empty()) {
    211     wait_ret = WaitForSignalOrExitLocked();
    212   }
    213 
    214   FrameState frame;
    215   if (!frame_queue_.empty()) {
    216     frame = std::move(frame_queue_.front());
    217     frame_queue_.pop();
    218   }
    219 
    220   ret = Unlock();
    221   if (ret) {
    222     ALOGE("Failed to unlock worker, %d", ret);
    223     return;
    224   }
    225 
    226   if (wait_ret == -EINTR) {
    227     return;
    228   } else if (wait_ret) {
    229     ALOGE("Failed to wait for signal, %d", wait_ret);
    230     return;
    231   }
    232 
    233   compositor_->ApplyFrame(std::move(frame.composition), frame.status);
    234 }
    235 
    236 DrmDisplayCompositor::DrmDisplayCompositor()
    237     : drm_(NULL),
    238       display_(-1),
    239       worker_(this),
    240       frame_worker_(this),
    241       initialized_(false),
    242       active_(false),
    243       use_hw_overlays_(true),
    244       framebuffer_index_(0),
    245       squash_framebuffer_index_(0),
    246       dump_frames_composited_(0),
    247       dump_last_timestamp_ns_(0) {
    248   struct timespec ts;
    249   if (clock_gettime(CLOCK_MONOTONIC, &ts))
    250     return;
    251   dump_last_timestamp_ns_ = ts.tv_sec * 1000 * 1000 * 1000 + ts.tv_nsec;
    252 }
    253 
    254 DrmDisplayCompositor::~DrmDisplayCompositor() {
    255   if (!initialized_)
    256     return;
    257 
    258   worker_.Exit();
    259   frame_worker_.Exit();
    260 
    261   int ret = pthread_mutex_lock(&lock_);
    262   if (ret)
    263     ALOGE("Failed to acquire compositor lock %d", ret);
    264 
    265   if (mode_.blob_id)
    266     drm_->DestroyPropertyBlob(mode_.blob_id);
    267   if (mode_.old_blob_id)
    268     drm_->DestroyPropertyBlob(mode_.old_blob_id);
    269 
    270   while (!composite_queue_.empty()) {
    271     composite_queue_.front().reset();
    272     composite_queue_.pop();
    273   }
    274   active_composition_.reset();
    275 
    276   ret = pthread_mutex_unlock(&lock_);
    277   if (ret)
    278     ALOGE("Failed to acquire compositor lock %d", ret);
    279 
    280   pthread_mutex_destroy(&lock_);
    281 }
    282 
    283 int DrmDisplayCompositor::Init(DrmResources *drm, int display) {
    284   drm_ = drm;
    285   display_ = display;
    286 
    287   int ret = pthread_mutex_init(&lock_, NULL);
    288   if (ret) {
    289     ALOGE("Failed to initialize drm compositor lock %d\n", ret);
    290     return ret;
    291   }
    292   ret = worker_.Init();
    293   if (ret) {
    294     pthread_mutex_destroy(&lock_);
    295     ALOGE("Failed to initialize compositor worker %d\n", ret);
    296     return ret;
    297   }
    298   ret = frame_worker_.Init();
    299   if (ret) {
    300     pthread_mutex_destroy(&lock_);
    301     ALOGE("Failed to initialize frame worker %d\n", ret);
    302     return ret;
    303   }
    304 
    305   initialized_ = true;
    306   return 0;
    307 }
    308 
    309 std::unique_ptr<DrmDisplayComposition> DrmDisplayCompositor::CreateComposition()
    310     const {
    311   return std::unique_ptr<DrmDisplayComposition>(new DrmDisplayComposition());
    312 }
    313 
    314 int DrmDisplayCompositor::QueueComposition(
    315     std::unique_ptr<DrmDisplayComposition> composition) {
    316   switch (composition->type()) {
    317     case DRM_COMPOSITION_TYPE_FRAME:
    318       if (!active_)
    319         return -ENODEV;
    320       break;
    321     case DRM_COMPOSITION_TYPE_DPMS:
    322       /*
    323        * Update the state as soon as we get it so we can start/stop queuing
    324        * frames asap.
    325        */
    326       active_ = (composition->dpms_mode() == DRM_MODE_DPMS_ON);
    327       break;
    328     case DRM_COMPOSITION_TYPE_MODESET:
    329       break;
    330     case DRM_COMPOSITION_TYPE_EMPTY:
    331       return 0;
    332     default:
    333       ALOGE("Unknown composition type %d/%d", composition->type(), display_);
    334       return -ENOENT;
    335   }
    336 
    337   int ret = pthread_mutex_lock(&lock_);
    338   if (ret) {
    339     ALOGE("Failed to acquire compositor lock %d", ret);
    340     return ret;
    341   }
    342 
    343   // Block the queue if it gets too large. Otherwise, SurfaceFlinger will start
    344   // to eat our buffer handles when we get about 1 second behind.
    345   while (composite_queue_.size() >= DRM_DISPLAY_COMPOSITOR_MAX_QUEUE_DEPTH) {
    346     pthread_mutex_unlock(&lock_);
    347     sched_yield();
    348     pthread_mutex_lock(&lock_);
    349   }
    350 
    351   composite_queue_.push(std::move(composition));
    352 
    353   ret = pthread_mutex_unlock(&lock_);
    354   if (ret) {
    355     ALOGE("Failed to release compositor lock %d", ret);
    356     return ret;
    357   }
    358 
    359   worker_.Signal();
    360   return 0;
    361 }
    362 
    363 std::tuple<uint32_t, uint32_t, int>
    364 DrmDisplayCompositor::GetActiveModeResolution() {
    365   DrmConnector *connector = drm_->GetConnectorForDisplay(display_);
    366   if (connector == NULL) {
    367     ALOGE("Failed to determine display mode: no connector for display %d",
    368           display_);
    369     return std::make_tuple(0, 0, -ENODEV);
    370   }
    371 
    372   const DrmMode &mode = connector->active_mode();
    373   return std::make_tuple(mode.h_display(), mode.v_display(), 0);
    374 }
    375 
    376 int DrmDisplayCompositor::PrepareFramebuffer(
    377     DrmFramebuffer &fb, DrmDisplayComposition *display_comp) {
    378   int ret = fb.WaitReleased(-1);
    379   if (ret) {
    380     ALOGE("Failed to wait for framebuffer release %d", ret);
    381     return ret;
    382   }
    383   uint32_t width, height;
    384   std::tie(width, height, ret) = GetActiveModeResolution();
    385   if (ret) {
    386     ALOGE(
    387         "Failed to allocate framebuffer because the display resolution could "
    388         "not be determined %d",
    389         ret);
    390     return ret;
    391   }
    392 
    393   fb.set_release_fence_fd(-1);
    394   if (!fb.Allocate(width, height)) {
    395     ALOGE("Failed to allocate framebuffer with size %dx%d", width, height);
    396     return -ENOMEM;
    397   }
    398 
    399   display_comp->layers().emplace_back();
    400   DrmHwcLayer &pre_comp_layer = display_comp->layers().back();
    401   pre_comp_layer.sf_handle = fb.buffer()->handle;
    402   pre_comp_layer.blending = DrmHwcBlending::kPreMult;
    403   pre_comp_layer.source_crop = DrmHwcRect<float>(0, 0, width, height);
    404   pre_comp_layer.display_frame = DrmHwcRect<int>(0, 0, width, height);
    405   ret = pre_comp_layer.buffer.ImportBuffer(fb.buffer()->handle,
    406                                            display_comp->importer());
    407   if (ret) {
    408     ALOGE("Failed to import framebuffer for display %d", ret);
    409     return ret;
    410   }
    411 
    412   return ret;
    413 }
    414 
    415 int DrmDisplayCompositor::ApplySquash(DrmDisplayComposition *display_comp) {
    416   int ret = 0;
    417 
    418   DrmFramebuffer &fb = squash_framebuffers_[squash_framebuffer_index_];
    419   ret = PrepareFramebuffer(fb, display_comp);
    420   if (ret) {
    421     ALOGE("Failed to prepare framebuffer for squash %d", ret);
    422     return ret;
    423   }
    424 
    425   std::vector<DrmCompositionRegion> &regions = display_comp->squash_regions();
    426   ret = pre_compositor_->Composite(display_comp->layers().data(),
    427                                    regions.data(), regions.size(), fb.buffer());
    428   pre_compositor_->Finish();
    429 
    430   if (ret) {
    431     ALOGE("Failed to squash layers");
    432     return ret;
    433   }
    434 
    435   ret = display_comp->CreateNextTimelineFence();
    436   if (ret <= 0) {
    437     ALOGE("Failed to create squash framebuffer release fence %d", ret);
    438     return ret;
    439   }
    440 
    441   fb.set_release_fence_fd(ret);
    442   display_comp->SignalSquashDone();
    443 
    444   return 0;
    445 }
    446 
    447 int DrmDisplayCompositor::ApplyPreComposite(
    448     DrmDisplayComposition *display_comp) {
    449   int ret = 0;
    450 
    451   DrmFramebuffer &fb = framebuffers_[framebuffer_index_];
    452   ret = PrepareFramebuffer(fb, display_comp);
    453   if (ret) {
    454     ALOGE("Failed to prepare framebuffer for pre-composite %d", ret);
    455     return ret;
    456   }
    457 
    458   std::vector<DrmCompositionRegion> &regions = display_comp->pre_comp_regions();
    459   ret = pre_compositor_->Composite(display_comp->layers().data(),
    460                                    regions.data(), regions.size(), fb.buffer());
    461   pre_compositor_->Finish();
    462 
    463   if (ret) {
    464     ALOGE("Failed to pre-composite layers");
    465     return ret;
    466   }
    467 
    468   ret = display_comp->CreateNextTimelineFence();
    469   if (ret <= 0) {
    470     ALOGE("Failed to create pre-composite framebuffer release fence %d", ret);
    471     return ret;
    472   }
    473 
    474   fb.set_release_fence_fd(ret);
    475   display_comp->SignalPreCompDone();
    476 
    477   return 0;
    478 }
    479 
    480 int DrmDisplayCompositor::DisablePlanes(DrmDisplayComposition *display_comp) {
    481   drmModeAtomicReqPtr pset = drmModeAtomicAlloc();
    482   if (!pset) {
    483     ALOGE("Failed to allocate property set");
    484     return -ENOMEM;
    485   }
    486 
    487   int ret;
    488   std::vector<DrmCompositionPlane> &comp_planes =
    489       display_comp->composition_planes();
    490   for (DrmCompositionPlane &comp_plane : comp_planes) {
    491     DrmPlane *plane = comp_plane.plane();
    492     ret = drmModeAtomicAddProperty(pset, plane->id(),
    493                                    plane->crtc_property().id(), 0) < 0 ||
    494           drmModeAtomicAddProperty(pset, plane->id(), plane->fb_property().id(),
    495                                    0) < 0;
    496     if (ret) {
    497       ALOGE("Failed to add plane %d disable to pset", plane->id());
    498       drmModeAtomicFree(pset);
    499       return ret;
    500     }
    501   }
    502 
    503   ret = drmModeAtomicCommit(drm_->fd(), pset, 0, drm_);
    504   if (ret) {
    505     ALOGE("Failed to commit pset ret=%d\n", ret);
    506     drmModeAtomicFree(pset);
    507     return ret;
    508   }
    509 
    510   drmModeAtomicFree(pset);
    511   return 0;
    512 }
    513 
    514 int DrmDisplayCompositor::PrepareFrame(DrmDisplayComposition *display_comp) {
    515   int ret = 0;
    516 
    517   std::vector<DrmHwcLayer> &layers = display_comp->layers();
    518   std::vector<DrmCompositionPlane> &comp_planes =
    519       display_comp->composition_planes();
    520   std::vector<DrmCompositionRegion> &squash_regions =
    521       display_comp->squash_regions();
    522   std::vector<DrmCompositionRegion> &pre_comp_regions =
    523       display_comp->pre_comp_regions();
    524 
    525   int squash_layer_index = -1;
    526   if (squash_regions.size() > 0) {
    527     squash_framebuffer_index_ = (squash_framebuffer_index_ + 1) % 2;
    528     ret = ApplySquash(display_comp);
    529     if (ret)
    530       return ret;
    531 
    532     squash_layer_index = layers.size() - 1;
    533   } else {
    534     if (UsesSquash(comp_planes)) {
    535       DrmFramebuffer &fb = squash_framebuffers_[squash_framebuffer_index_];
    536       layers.emplace_back();
    537       squash_layer_index = layers.size() - 1;
    538       DrmHwcLayer &squash_layer = layers.back();
    539       ret = squash_layer.buffer.ImportBuffer(fb.buffer()->handle,
    540                                              display_comp->importer());
    541       if (ret) {
    542         ALOGE("Failed to import old squashed framebuffer %d", ret);
    543         return ret;
    544       }
    545       squash_layer.sf_handle = fb.buffer()->handle;
    546       squash_layer.blending = DrmHwcBlending::kPreMult;
    547       squash_layer.source_crop = DrmHwcRect<float>(
    548           0, 0, squash_layer.buffer->width, squash_layer.buffer->height);
    549       squash_layer.display_frame = DrmHwcRect<int>(
    550           0, 0, squash_layer.buffer->width, squash_layer.buffer->height);
    551       ret = display_comp->CreateNextTimelineFence();
    552 
    553       if (ret <= 0) {
    554         ALOGE("Failed to create squash framebuffer release fence %d", ret);
    555         return ret;
    556       }
    557 
    558       fb.set_release_fence_fd(ret);
    559       ret = 0;
    560     }
    561   }
    562 
    563   bool do_pre_comp = pre_comp_regions.size() > 0;
    564   int pre_comp_layer_index = -1;
    565   if (do_pre_comp) {
    566     ret = ApplyPreComposite(display_comp);
    567     if (ret)
    568       return ret;
    569 
    570     pre_comp_layer_index = layers.size() - 1;
    571     framebuffer_index_ = (framebuffer_index_ + 1) % DRM_DISPLAY_BUFFERS;
    572   }
    573 
    574   for (DrmCompositionPlane &comp_plane : comp_planes) {
    575     std::vector<size_t> &source_layers = comp_plane.source_layers();
    576     switch (comp_plane.type()) {
    577       case DrmCompositionPlane::Type::kSquash:
    578         if (source_layers.size())
    579           ALOGE("Squash source_layers is expected to be empty (%zu/%d)",
    580                 source_layers[0], squash_layer_index);
    581         source_layers.push_back(squash_layer_index);
    582         break;
    583       case DrmCompositionPlane::Type::kPrecomp:
    584         if (!do_pre_comp) {
    585           ALOGE(
    586               "Can not use pre composite framebuffer with no pre composite "
    587               "regions");
    588           return -EINVAL;
    589         }
    590         // Replace source_layers with the output of the precomposite
    591         source_layers.clear();
    592         source_layers.push_back(pre_comp_layer_index);
    593         break;
    594       default:
    595         break;
    596     }
    597   }
    598 
    599   return ret;
    600 }
    601 
    602 int DrmDisplayCompositor::CommitFrame(DrmDisplayComposition *display_comp,
    603                                       bool test_only) {
    604   ATRACE_CALL();
    605 
    606   int ret = 0;
    607 
    608   std::vector<DrmHwcLayer> &layers = display_comp->layers();
    609   std::vector<DrmCompositionPlane> &comp_planes =
    610       display_comp->composition_planes();
    611   std::vector<DrmCompositionRegion> &pre_comp_regions =
    612       display_comp->pre_comp_regions();
    613 
    614   DrmConnector *connector = drm_->GetConnectorForDisplay(display_);
    615   if (!connector) {
    616     ALOGE("Could not locate connector for display %d", display_);
    617     return -ENODEV;
    618   }
    619   DrmCrtc *crtc = drm_->GetCrtcForDisplay(display_);
    620   if (!crtc) {
    621     ALOGE("Could not locate crtc for display %d", display_);
    622     return -ENODEV;
    623   }
    624 
    625   drmModeAtomicReqPtr pset = drmModeAtomicAlloc();
    626   if (!pset) {
    627     ALOGE("Failed to allocate property set");
    628     return -ENOMEM;
    629   }
    630 
    631   if (mode_.needs_modeset) {
    632     ret = drmModeAtomicAddProperty(pset, crtc->id(), crtc->mode_property().id(),
    633                                    mode_.blob_id) < 0 ||
    634           drmModeAtomicAddProperty(pset, connector->id(),
    635                                    connector->crtc_id_property().id(),
    636                                    crtc->id()) < 0;
    637     if (ret) {
    638       ALOGE("Failed to add blob %d to pset", mode_.blob_id);
    639       drmModeAtomicFree(pset);
    640       return ret;
    641     }
    642   }
    643 
    644   for (DrmCompositionPlane &comp_plane : comp_planes) {
    645     DrmPlane *plane = comp_plane.plane();
    646     DrmCrtc *crtc = comp_plane.crtc();
    647     std::vector<size_t> &source_layers = comp_plane.source_layers();
    648 
    649     int fb_id = -1;
    650     DrmHwcRect<int> display_frame;
    651     DrmHwcRect<float> source_crop;
    652     uint64_t rotation = 0;
    653     uint64_t alpha = 0xFF;
    654 
    655     if (comp_plane.type() != DrmCompositionPlane::Type::kDisable) {
    656       if (source_layers.size() > 1) {
    657         ALOGE("Can't handle more than one source layer sz=%zu type=%d",
    658               source_layers.size(), comp_plane.type());
    659         continue;
    660       }
    661 
    662       if (source_layers.empty() || source_layers.front() >= layers.size()) {
    663         ALOGE("Source layer index %zu out of bounds %zu type=%d",
    664               source_layers.front(), layers.size(), comp_plane.type());
    665         break;
    666       }
    667       DrmHwcLayer &layer = layers[source_layers.front()];
    668       if (!test_only && layer.acquire_fence.get() >= 0) {
    669         int acquire_fence = layer.acquire_fence.get();
    670         int total_fence_timeout = 0;
    671         for (int i = 0; i < kAcquireWaitTries; ++i) {
    672           int fence_timeout = kAcquireWaitTimeoutMs * (1 << i);
    673           total_fence_timeout += fence_timeout;
    674           ret = sync_wait(acquire_fence, fence_timeout);
    675           if (ret)
    676             ALOGW("Acquire fence %d wait %d failed (%d). Total time %d",
    677                   acquire_fence, i, ret, total_fence_timeout);
    678         }
    679         if (ret) {
    680           ALOGE("Failed to wait for acquire %d/%d", acquire_fence, ret);
    681           break;
    682         }
    683         layer.acquire_fence.Close();
    684       }
    685       if (!layer.buffer) {
    686         ALOGE("Expected a valid framebuffer for pset");
    687         break;
    688       }
    689       fb_id = layer.buffer->fb_id;
    690       display_frame = layer.display_frame;
    691       source_crop = layer.source_crop;
    692       if (layer.blending == DrmHwcBlending::kPreMult)
    693         alpha = layer.alpha;
    694 
    695       rotation = 0;
    696       if (layer.transform & DrmHwcTransform::kFlipH)
    697         rotation |= 1 << DRM_REFLECT_X;
    698       if (layer.transform & DrmHwcTransform::kFlipV)
    699         rotation |= 1 << DRM_REFLECT_Y;
    700       if (layer.transform & DrmHwcTransform::kRotate90)
    701         rotation |= 1 << DRM_ROTATE_90;
    702       else if (layer.transform & DrmHwcTransform::kRotate180)
    703         rotation |= 1 << DRM_ROTATE_180;
    704       else if (layer.transform & DrmHwcTransform::kRotate270)
    705         rotation |= 1 << DRM_ROTATE_270;
    706     }
    707     // Disable the plane if there's no framebuffer
    708     if (fb_id < 0) {
    709       ret = drmModeAtomicAddProperty(pset, plane->id(),
    710                                      plane->crtc_property().id(), 0) < 0 ||
    711             drmModeAtomicAddProperty(pset, plane->id(),
    712                                      plane->fb_property().id(), 0) < 0;
    713       if (ret) {
    714         ALOGE("Failed to add plane %d disable to pset", plane->id());
    715         break;
    716       }
    717       continue;
    718     }
    719 
    720     // TODO: Once we have atomic test, this should fall back to GL
    721     if (rotation && plane->rotation_property().id() == 0) {
    722       ALOGE("Rotation is not supported on plane %d", plane->id());
    723       ret = -EINVAL;
    724       break;
    725     }
    726 
    727     // TODO: Once we have atomic test, this should fall back to GL
    728     if (alpha != 0xFF && plane->alpha_property().id() == 0) {
    729       ALOGE("Alpha is not supported on plane %d", plane->id());
    730       ret = -EINVAL;
    731       break;
    732     }
    733 
    734     ret = drmModeAtomicAddProperty(pset, plane->id(),
    735                                    plane->crtc_property().id(), crtc->id()) < 0;
    736     ret |= drmModeAtomicAddProperty(pset, plane->id(),
    737                                     plane->fb_property().id(), fb_id) < 0;
    738     ret |= drmModeAtomicAddProperty(pset, plane->id(),
    739                                     plane->crtc_x_property().id(),
    740                                     display_frame.left) < 0;
    741     ret |= drmModeAtomicAddProperty(pset, plane->id(),
    742                                     plane->crtc_y_property().id(),
    743                                     display_frame.top) < 0;
    744     ret |= drmModeAtomicAddProperty(
    745                pset, plane->id(), plane->crtc_w_property().id(),
    746                display_frame.right - display_frame.left) < 0;
    747     ret |= drmModeAtomicAddProperty(
    748                pset, plane->id(), plane->crtc_h_property().id(),
    749                display_frame.bottom - display_frame.top) < 0;
    750     ret |= drmModeAtomicAddProperty(pset, plane->id(),
    751                                     plane->src_x_property().id(),
    752                                     (int)(source_crop.left) << 16) < 0;
    753     ret |= drmModeAtomicAddProperty(pset, plane->id(),
    754                                     plane->src_y_property().id(),
    755                                     (int)(source_crop.top) << 16) < 0;
    756     ret |= drmModeAtomicAddProperty(
    757                pset, plane->id(), plane->src_w_property().id(),
    758                (int)(source_crop.right - source_crop.left) << 16) < 0;
    759     ret |= drmModeAtomicAddProperty(
    760                pset, plane->id(), plane->src_h_property().id(),
    761                (int)(source_crop.bottom - source_crop.top) << 16) < 0;
    762     if (ret) {
    763       ALOGE("Failed to add plane %d to set", plane->id());
    764       break;
    765     }
    766 
    767     if (plane->rotation_property().id()) {
    768       ret = drmModeAtomicAddProperty(pset, plane->id(),
    769                                      plane->rotation_property().id(),
    770                                      rotation) < 0;
    771       if (ret) {
    772         ALOGE("Failed to add rotation property %d to plane %d",
    773               plane->rotation_property().id(), plane->id());
    774         break;
    775       }
    776     }
    777 
    778     if (plane->alpha_property().id()) {
    779       ret = drmModeAtomicAddProperty(pset, plane->id(),
    780                                      plane->alpha_property().id(),
    781                                      alpha) < 0;
    782       if (ret) {
    783         ALOGE("Failed to add alpha property %d to plane %d",
    784               plane->alpha_property().id(), plane->id());
    785         break;
    786       }
    787     }
    788   }
    789 
    790 out:
    791   if (!ret) {
    792     uint32_t flags = DRM_MODE_ATOMIC_ALLOW_MODESET;
    793     if (test_only)
    794       flags |= DRM_MODE_ATOMIC_TEST_ONLY;
    795 
    796     ret = drmModeAtomicCommit(drm_->fd(), pset, flags, drm_);
    797     if (ret) {
    798       if (test_only)
    799         ALOGI("Commit test pset failed ret=%d\n", ret);
    800       else
    801         ALOGE("Failed to commit pset ret=%d\n", ret);
    802       drmModeAtomicFree(pset);
    803       return ret;
    804     }
    805   }
    806   if (pset)
    807     drmModeAtomicFree(pset);
    808 
    809   if (!test_only && mode_.needs_modeset) {
    810     ret = drm_->DestroyPropertyBlob(mode_.old_blob_id);
    811     if (ret) {
    812       ALOGE("Failed to destroy old mode property blob %" PRIu32 "/%d",
    813             mode_.old_blob_id, ret);
    814       return ret;
    815     }
    816 
    817     /* TODO: Add dpms to the pset when the kernel supports it */
    818     ret = ApplyDpms(display_comp);
    819     if (ret) {
    820       ALOGE("Failed to apply DPMS after modeset %d\n", ret);
    821       return ret;
    822     }
    823 
    824     connector->set_active_mode(mode_.mode);
    825     mode_.old_blob_id = mode_.blob_id;
    826     mode_.blob_id = 0;
    827     mode_.needs_modeset = false;
    828   }
    829 
    830   return ret;
    831 }
    832 
    833 int DrmDisplayCompositor::ApplyDpms(DrmDisplayComposition *display_comp) {
    834   DrmConnector *conn = drm_->GetConnectorForDisplay(display_);
    835   if (!conn) {
    836     ALOGE("Failed to get DrmConnector for display %d", display_);
    837     return -ENODEV;
    838   }
    839 
    840   const DrmProperty &prop = conn->dpms_property();
    841   int ret = drmModeConnectorSetProperty(drm_->fd(), conn->id(), prop.id(),
    842                                         display_comp->dpms_mode());
    843   if (ret) {
    844     ALOGE("Failed to set DPMS property for connector %d", conn->id());
    845     return ret;
    846   }
    847   return 0;
    848 }
    849 
    850 std::tuple<int, uint32_t> DrmDisplayCompositor::CreateModeBlob(
    851     const DrmMode &mode) {
    852   struct drm_mode_modeinfo drm_mode;
    853   memset(&drm_mode, 0, sizeof(drm_mode));
    854   mode.ToDrmModeModeInfo(&drm_mode);
    855 
    856   uint32_t id = 0;
    857   int ret = drm_->CreatePropertyBlob(&drm_mode,
    858                                      sizeof(struct drm_mode_modeinfo), &id);
    859   if (ret) {
    860     ALOGE("Failed to create mode property blob %d", ret);
    861     return std::make_tuple(ret, 0);
    862   }
    863   ALOGE("Create blob_id %" PRIu32 "\n", id);
    864   return std::make_tuple(ret, id);
    865 }
    866 
    867 void DrmDisplayCompositor::ClearDisplay() {
    868   AutoLock lock(&lock_, "compositor");
    869   int ret = lock.Lock();
    870   if (ret)
    871     return;
    872 
    873   if (!active_composition_)
    874     return;
    875 
    876   if (DisablePlanes(active_composition_.get()))
    877     return;
    878 
    879   active_composition_->SignalCompositionDone();
    880 
    881   active_composition_.reset(NULL);
    882 }
    883 
    884 void DrmDisplayCompositor::ApplyFrame(
    885     std::unique_ptr<DrmDisplayComposition> composition, int status) {
    886   int ret = status;
    887 
    888   if (!ret)
    889     ret = CommitFrame(composition.get(), false);
    890 
    891   if (ret) {
    892     ALOGE("Composite failed for display %d", display_);
    893     // Disable the hw used by the last active composition. This allows us to
    894     // signal the release fences from that composition to avoid hanging.
    895     ClearDisplay();
    896     return;
    897   }
    898   ++dump_frames_composited_;
    899 
    900   if (active_composition_)
    901     active_composition_->SignalCompositionDone();
    902 
    903   ret = pthread_mutex_lock(&lock_);
    904   if (ret)
    905     ALOGE("Failed to acquire lock for active_composition swap");
    906 
    907   active_composition_.swap(composition);
    908 
    909   if (!ret)
    910     ret = pthread_mutex_unlock(&lock_);
    911   if (ret)
    912     ALOGE("Failed to release lock for active_composition swap");
    913 }
    914 
    915 int DrmDisplayCompositor::Composite() {
    916   ATRACE_CALL();
    917 
    918   if (!pre_compositor_) {
    919     pre_compositor_.reset(new GLWorkerCompositor());
    920     int ret = pre_compositor_->Init();
    921     if (ret) {
    922       ALOGE("Failed to initialize OpenGL compositor %d", ret);
    923       return ret;
    924     }
    925   }
    926 
    927   int ret = pthread_mutex_lock(&lock_);
    928   if (ret) {
    929     ALOGE("Failed to acquire compositor lock %d", ret);
    930     return ret;
    931   }
    932   if (composite_queue_.empty()) {
    933     ret = pthread_mutex_unlock(&lock_);
    934     if (ret)
    935       ALOGE("Failed to release compositor lock %d", ret);
    936     return ret;
    937   }
    938 
    939   std::unique_ptr<DrmDisplayComposition> composition(
    940       std::move(composite_queue_.front()));
    941 
    942   composite_queue_.pop();
    943 
    944   ret = pthread_mutex_unlock(&lock_);
    945   if (ret) {
    946     ALOGE("Failed to release compositor lock %d", ret);
    947     return ret;
    948   }
    949 
    950   switch (composition->type()) {
    951     case DRM_COMPOSITION_TYPE_FRAME:
    952       ret = PrepareFrame(composition.get());
    953       if (ret) {
    954         ALOGE("Failed to prepare frame for display %d", display_);
    955         return ret;
    956       }
    957       if (composition->geometry_changed()) {
    958         // Send the composition to the kernel to ensure we can commit it. This
    959         // is just a test, it won't actually commit the frame. If rejected,
    960         // squash the frame into one layer and use the squashed composition
    961         ret = CommitFrame(composition.get(), true);
    962         if (ret)
    963           ALOGI("Commit test failed, squashing frame for display %d", display_);
    964         use_hw_overlays_ = !ret;
    965       }
    966 
    967       // If use_hw_overlays_ is false, we can't use hardware to composite the
    968       // frame. So squash all layers into a single composition and queue that
    969       // instead.
    970       if (!use_hw_overlays_) {
    971         std::unique_ptr<DrmDisplayComposition> squashed = CreateComposition();
    972         ret = SquashFrame(composition.get(), squashed.get());
    973         if (!ret) {
    974           composition = std::move(squashed);
    975         } else {
    976           ALOGE("Failed to squash frame for display %d", display_);
    977           // Disable the hw used by the last active composition. This allows us
    978           // to signal the release fences from that composition to avoid
    979           // hanging.
    980           ClearDisplay();
    981           return ret;
    982         }
    983       }
    984       frame_worker_.QueueFrame(std::move(composition), ret);
    985       break;
    986     case DRM_COMPOSITION_TYPE_DPMS:
    987       ret = ApplyDpms(composition.get());
    988       if (ret)
    989         ALOGE("Failed to apply dpms for display %d", display_);
    990       return ret;
    991     case DRM_COMPOSITION_TYPE_MODESET:
    992       mode_.mode = composition->display_mode();
    993       if (mode_.blob_id)
    994         drm_->DestroyPropertyBlob(mode_.blob_id);
    995       std::tie(ret, mode_.blob_id) = CreateModeBlob(mode_.mode);
    996       if (ret) {
    997         ALOGE("Failed to create mode blob for display %d", display_);
    998         return ret;
    999       }
   1000       mode_.needs_modeset = true;
   1001       return 0;
   1002     default:
   1003       ALOGE("Unknown composition type %d", composition->type());
   1004       return -EINVAL;
   1005   }
   1006 
   1007   return ret;
   1008 }
   1009 
   1010 bool DrmDisplayCompositor::HaveQueuedComposites() const {
   1011   int ret = pthread_mutex_lock(&lock_);
   1012   if (ret) {
   1013     ALOGE("Failed to acquire compositor lock %d", ret);
   1014     return false;
   1015   }
   1016 
   1017   bool empty_ret = !composite_queue_.empty();
   1018 
   1019   ret = pthread_mutex_unlock(&lock_);
   1020   if (ret) {
   1021     ALOGE("Failed to release compositor lock %d", ret);
   1022     return false;
   1023   }
   1024 
   1025   return empty_ret;
   1026 }
   1027 
   1028 int DrmDisplayCompositor::SquashAll() {
   1029   AutoLock lock(&lock_, "compositor");
   1030   int ret = lock.Lock();
   1031   if (ret)
   1032     return ret;
   1033 
   1034   if (!active_composition_)
   1035     return 0;
   1036 
   1037   std::unique_ptr<DrmDisplayComposition> comp = CreateComposition();
   1038   ret = SquashFrame(active_composition_.get(), comp.get());
   1039 
   1040   // ApplyFrame needs the lock
   1041   lock.Unlock();
   1042 
   1043   if (!ret)
   1044     ApplyFrame(std::move(comp), 0);
   1045 
   1046   return ret;
   1047 }
   1048 
   1049 // Returns:
   1050 //   - 0 if src is successfully squashed into dst
   1051 //   - -EALREADY if the src is already squashed
   1052 //   - Appropriate error if the squash fails
   1053 int DrmDisplayCompositor::SquashFrame(DrmDisplayComposition *src,
   1054                                       DrmDisplayComposition *dst) {
   1055   if (src->type() != DRM_COMPOSITION_TYPE_FRAME)
   1056     return -ENOTSUP;
   1057 
   1058   std::vector<DrmCompositionPlane> &src_planes = src->composition_planes();
   1059   std::vector<DrmHwcLayer> &src_layers = src->layers();
   1060 
   1061   // Make sure there is more than one layer to squash.
   1062   size_t src_planes_with_layer = std::count_if(
   1063       src_planes.begin(), src_planes.end(), [](DrmCompositionPlane &p) {
   1064         return p.type() != DrmCompositionPlane::Type::kDisable;
   1065       });
   1066   if (src_planes_with_layer <= 1)
   1067     return -EALREADY;
   1068 
   1069   int pre_comp_layer_index;
   1070 
   1071   int ret = dst->Init(drm_, src->crtc(), src->importer(), src->planner(),
   1072                       src->frame_no());
   1073   if (ret) {
   1074     ALOGE("Failed to init squash all composition %d", ret);
   1075     return ret;
   1076   }
   1077 
   1078   DrmCompositionPlane squashed_comp(DrmCompositionPlane::Type::kPrecomp, NULL,
   1079                                     src->crtc());
   1080   std::vector<DrmHwcLayer> dst_layers;
   1081   for (DrmCompositionPlane &comp_plane : src_planes) {
   1082     // Composition planes without DRM planes should never happen
   1083     if (comp_plane.plane() == NULL) {
   1084       ALOGE("Skipping squash all because of NULL plane");
   1085       ret = -EINVAL;
   1086       goto move_layers_back;
   1087     }
   1088 
   1089     if (comp_plane.type() == DrmCompositionPlane::Type::kDisable) {
   1090       dst->AddPlaneDisable(comp_plane.plane());
   1091       continue;
   1092     }
   1093 
   1094     for (auto i : comp_plane.source_layers()) {
   1095       DrmHwcLayer &layer = src_layers[i];
   1096 
   1097       // Squashing protected layers is impossible.
   1098       if (layer.protected_usage()) {
   1099         ret = -ENOTSUP;
   1100         goto move_layers_back;
   1101       }
   1102 
   1103       // The OutputFds point to freed memory after hwc_set returns. They are
   1104       // returned to the default to prevent DrmDisplayComposition::Plan from
   1105       // filling the OutputFds.
   1106       layer.release_fence = OutputFd();
   1107       dst_layers.emplace_back(std::move(layer));
   1108       squashed_comp.source_layers().push_back(
   1109           squashed_comp.source_layers().size());
   1110     }
   1111 
   1112     if (comp_plane.plane()->type() == DRM_PLANE_TYPE_PRIMARY)
   1113       squashed_comp.set_plane(comp_plane.plane());
   1114     else
   1115       dst->AddPlaneDisable(comp_plane.plane());
   1116   }
   1117 
   1118   ret = dst->SetLayers(dst_layers.data(), dst_layers.size(), false);
   1119   if (ret) {
   1120     ALOGE("Failed to set layers for squash all composition %d", ret);
   1121     goto move_layers_back;
   1122   }
   1123 
   1124   ret = dst->AddPlaneComposition(std::move(squashed_comp));
   1125   if (ret) {
   1126     ALOGE("Failed to add squashed plane composition %d", ret);
   1127     goto move_layers_back;
   1128   }
   1129 
   1130   ret = dst->FinalizeComposition();
   1131   if (ret) {
   1132     ALOGE("Failed to plan for squash all composition %d", ret);
   1133     goto move_layers_back;
   1134   }
   1135 
   1136   ret = ApplyPreComposite(dst);
   1137   if (ret) {
   1138     ALOGE("Failed to pre-composite for squash all composition %d", ret);
   1139     goto move_layers_back;
   1140   }
   1141 
   1142   pre_comp_layer_index = dst->layers().size() - 1;
   1143   framebuffer_index_ = (framebuffer_index_ + 1) % DRM_DISPLAY_BUFFERS;
   1144 
   1145   for (DrmCompositionPlane &plane : dst->composition_planes()) {
   1146     if (plane.type() == DrmCompositionPlane::Type::kPrecomp) {
   1147       // Replace source_layers with the output of the precomposite
   1148       plane.source_layers().clear();
   1149       plane.source_layers().push_back(pre_comp_layer_index);
   1150       break;
   1151     }
   1152   }
   1153 
   1154   return 0;
   1155 
   1156 // TODO(zachr): think of a better way to transfer ownership back to the active
   1157 // composition.
   1158 move_layers_back:
   1159   for (size_t plane_index = 0;
   1160        plane_index < src_planes.size() && plane_index < dst_layers.size();) {
   1161     if (src_planes[plane_index].source_layers().empty()) {
   1162       plane_index++;
   1163       continue;
   1164     }
   1165     for (auto i : src_planes[plane_index].source_layers())
   1166       src_layers[i] = std::move(dst_layers[plane_index++]);
   1167   }
   1168 
   1169   return ret;
   1170 }
   1171 
   1172 void DrmDisplayCompositor::Dump(std::ostringstream *out) const {
   1173   int ret = pthread_mutex_lock(&lock_);
   1174   if (ret)
   1175     return;
   1176 
   1177   uint64_t num_frames = dump_frames_composited_;
   1178   dump_frames_composited_ = 0;
   1179 
   1180   struct timespec ts;
   1181   ret = clock_gettime(CLOCK_MONOTONIC, &ts);
   1182   if (ret) {
   1183     pthread_mutex_unlock(&lock_);
   1184     return;
   1185   }
   1186 
   1187   uint64_t cur_ts = ts.tv_sec * 1000 * 1000 * 1000 + ts.tv_nsec;
   1188   uint64_t num_ms = (cur_ts - dump_last_timestamp_ns_) / (1000 * 1000);
   1189   float fps = num_ms ? (num_frames * 1000.0f) / (num_ms) : 0.0f;
   1190 
   1191   *out << "--DrmDisplayCompositor[" << display_
   1192        << "]: num_frames=" << num_frames << " num_ms=" << num_ms
   1193        << " fps=" << fps << "\n";
   1194 
   1195   dump_last_timestamp_ns_ = cur_ts;
   1196 
   1197   if (active_composition_)
   1198     active_composition_->Dump(out);
   1199 
   1200   squash_state_.Dump(out);
   1201 
   1202   pthread_mutex_unlock(&lock_);
   1203 }
   1204 }
   1205