Home | History | Annotate | Download | only in drm_hwcomposer
      1 /*
      2  * Copyright (C) 2016 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-platform"
     18 
     19 #include "drmresources.h"
     20 #include "platform.h"
     21 
     22 #include <cutils/log.h>
     23 
     24 namespace android {
     25 
     26 std::vector<DrmPlane *> Planner::GetUsablePlanes(
     27     DrmCrtc *crtc, std::vector<DrmPlane *> *primary_planes,
     28     std::vector<DrmPlane *> *overlay_planes) {
     29   std::vector<DrmPlane *> usable_planes;
     30   std::copy_if(primary_planes->begin(), primary_planes->end(),
     31                std::back_inserter(usable_planes),
     32                [=](DrmPlane *plane) { return plane->GetCrtcSupported(*crtc); });
     33   std::copy_if(overlay_planes->begin(), overlay_planes->end(),
     34                std::back_inserter(usable_planes),
     35                [=](DrmPlane *plane) { return plane->GetCrtcSupported(*crtc); });
     36   return usable_planes;
     37 }
     38 
     39 std::tuple<int, std::vector<DrmCompositionPlane>> Planner::ProvisionPlanes(
     40     std::map<size_t, DrmHwcLayer *> &layers, bool use_squash_fb, DrmCrtc *crtc,
     41     std::vector<DrmPlane *> *primary_planes,
     42     std::vector<DrmPlane *> *overlay_planes) {
     43   std::vector<DrmCompositionPlane> composition;
     44   std::vector<DrmPlane *> planes =
     45       GetUsablePlanes(crtc, primary_planes, overlay_planes);
     46   if (planes.empty()) {
     47     ALOGE("Display %d has no usable planes", crtc->display());
     48     return std::make_tuple(-ENODEV, std::vector<DrmCompositionPlane>());
     49   }
     50 
     51   // If needed, reserve the squash plane at the highest z-order
     52   DrmPlane *squash_plane = NULL;
     53   if (use_squash_fb) {
     54     if (!planes.empty()) {
     55       squash_plane = planes.back();
     56       planes.pop_back();
     57     } else {
     58       ALOGI("Not enough planes to reserve for squash fb");
     59     }
     60   }
     61 
     62   // If needed, reserve the precomp plane at the next highest z-order
     63   DrmPlane *precomp_plane = NULL;
     64   if (layers.size() > planes.size()) {
     65     if (!planes.empty()) {
     66       precomp_plane = planes.back();
     67       planes.pop_back();
     68       composition.emplace_back(DrmCompositionPlane::Type::kPrecomp,
     69                                precomp_plane, crtc);
     70     } else {
     71       ALOGE("Not enough planes to reserve for precomp fb");
     72     }
     73   }
     74 
     75   // Go through the provisioning stages and provision planes
     76   for (auto &i : stages_) {
     77     int ret = i->ProvisionPlanes(&composition, layers, crtc, &planes);
     78     if (ret) {
     79       ALOGE("Failed provision stage with ret %d", ret);
     80       return std::make_tuple(ret, std::vector<DrmCompositionPlane>());
     81     }
     82   }
     83 
     84   if (squash_plane)
     85     composition.emplace_back(DrmCompositionPlane::Type::kSquash, squash_plane,
     86                              crtc);
     87 
     88   return std::make_tuple(0, std::move(composition));
     89 }
     90 
     91 int PlanStageProtected::ProvisionPlanes(
     92     std::vector<DrmCompositionPlane> *composition,
     93     std::map<size_t, DrmHwcLayer *> &layers, DrmCrtc *crtc,
     94     std::vector<DrmPlane *> *planes) {
     95   int ret;
     96   int protected_zorder = -1;
     97   for (auto i = layers.begin(); i != layers.end();) {
     98     if (!i->second->protected_usage()) {
     99       ++i;
    100       continue;
    101     }
    102 
    103     ret = Emplace(composition, planes, DrmCompositionPlane::Type::kLayer, crtc,
    104                   i->first);
    105     if (ret)
    106       ALOGE("Failed to dedicate protected layer! Dropping it.");
    107 
    108     protected_zorder = i->first;
    109     i = layers.erase(i);
    110   }
    111 
    112   if (protected_zorder == -1)
    113     return 0;
    114 
    115   // Add any layers below the protected content to the precomposition since we
    116   // need to punch a hole through them.
    117   for (auto i = layers.begin(); i != layers.end();) {
    118     // Skip layers above the z-order of the protected content
    119     if (i->first > static_cast<size_t>(protected_zorder)) {
    120       ++i;
    121       continue;
    122     }
    123 
    124     // If there's no precomp layer already queued, queue one now.
    125     DrmCompositionPlane *precomp = GetPrecomp(composition);
    126     if (precomp) {
    127       precomp->source_layers().emplace_back(i->first);
    128     } else {
    129       if (!planes->empty()) {
    130         DrmPlane *precomp_plane = planes->back();
    131         planes->pop_back();
    132         composition->emplace_back(DrmCompositionPlane::Type::kPrecomp,
    133                                   precomp_plane, crtc, i->first);
    134       } else {
    135         ALOGE("Not enough planes to reserve for precomp fb");
    136       }
    137     }
    138     i = layers.erase(i);
    139   }
    140   return 0;
    141 }
    142 
    143 int PlanStagePrecomp::ProvisionPlanes(
    144     std::vector<DrmCompositionPlane> *composition,
    145     std::map<size_t, DrmHwcLayer *> &layers, DrmCrtc *crtc,
    146     std::vector<DrmPlane *> *planes) {
    147   DrmCompositionPlane *precomp = GetPrecomp(composition);
    148   if (!precomp || precomp->source_layers().empty())
    149     return 0;
    150 
    151   // Find lowest zorder out of precomp layers
    152   size_t precomp_zorder = *std::min_element(
    153       precomp->source_layers().begin(), precomp->source_layers().end(),
    154       [](size_t a, size_t b) { return a < b; });
    155 
    156   // if there are any remaining layers on top of any of the precomp layers,
    157   // add them to precomp to avoid blending issues since precomp is always at
    158   // highest zorder
    159   for (auto i = layers.begin(); i != layers.end();) {
    160     if (i->first < precomp_zorder) {
    161       i++;
    162       continue;
    163     }
    164     precomp->source_layers().emplace_back(i->first);
    165     i = layers.erase(i);
    166   }
    167 
    168   return 0;
    169 }
    170 
    171 int PlanStageGreedy::ProvisionPlanes(
    172     std::vector<DrmCompositionPlane> *composition,
    173     std::map<size_t, DrmHwcLayer *> &layers, DrmCrtc *crtc,
    174     std::vector<DrmPlane *> *planes) {
    175   // Fill up the remaining planes
    176   for (auto i = layers.begin(); i != layers.end(); i = layers.erase(i)) {
    177     int ret = Emplace(composition, planes, DrmCompositionPlane::Type::kLayer,
    178                       crtc, i->first);
    179     // We don't have any planes left
    180     if (ret == -ENOENT)
    181       break;
    182     else if (ret)
    183       ALOGE("Failed to emplace layer %zu, dropping it", i->first);
    184   }
    185 
    186   // Put the rest of the layers in the precomp plane
    187   DrmCompositionPlane *precomp = GetPrecomp(composition);
    188   if (precomp) {
    189     for (auto i = layers.begin(); i != layers.end(); i = layers.erase(i))
    190       precomp->source_layers().emplace_back(i->first);
    191   }
    192 
    193   return 0;
    194 }
    195 }
    196