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> ®ion : 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 ®ion : 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 ®ion : 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 ®ion = 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 ®ion, 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