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