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