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 "hwcomposer-drm" 19 20 #include "drmhwcomposer.h" 21 #include "drmeventlistener.h" 22 #include "drmresources.h" 23 #include "platform.h" 24 #include "virtualcompositorworker.h" 25 #include "vsyncworker.h" 26 27 #include <stdlib.h> 28 29 #include <cinttypes> 30 #include <map> 31 #include <vector> 32 #include <sstream> 33 34 #include <errno.h> 35 #include <fcntl.h> 36 #include <sys/param.h> 37 #include <sys/resource.h> 38 #include <xf86drm.h> 39 #include <xf86drmMode.h> 40 41 #include <cutils/log.h> 42 #include <cutils/properties.h> 43 #include <hardware/hardware.h> 44 #include <hardware/hwcomposer.h> 45 #include <sw_sync.h> 46 #include <sync/sync.h> 47 #include <utils/Trace.h> 48 49 #define UM_PER_INCH 25400 50 51 namespace android { 52 53 class DummySwSyncTimeline { 54 public: 55 int Init() { 56 int ret = timeline_fd_.Set(sw_sync_timeline_create()); 57 if (ret < 0) 58 return ret; 59 return 0; 60 } 61 62 UniqueFd CreateDummyFence() { 63 int ret = sw_sync_fence_create(timeline_fd_.get(), "dummy fence", 64 timeline_pt_ + 1); 65 if (ret < 0) { 66 ALOGE("Failed to create dummy fence %d", ret); 67 return ret; 68 } 69 70 UniqueFd ret_fd(ret); 71 72 ret = sw_sync_timeline_inc(timeline_fd_.get(), 1); 73 if (ret) { 74 ALOGE("Failed to increment dummy sync timeline %d", ret); 75 return ret; 76 } 77 78 ++timeline_pt_; 79 return ret_fd; 80 } 81 82 private: 83 UniqueFd timeline_fd_; 84 int timeline_pt_ = 0; 85 }; 86 87 struct CheckedOutputFd { 88 CheckedOutputFd(int *fd, const char *description, 89 DummySwSyncTimeline &timeline) 90 : fd_(fd), description_(description), timeline_(timeline) { 91 } 92 CheckedOutputFd(CheckedOutputFd &&rhs) 93 : description_(rhs.description_), timeline_(rhs.timeline_) { 94 std::swap(fd_, rhs.fd_); 95 } 96 97 CheckedOutputFd &operator=(const CheckedOutputFd &rhs) = delete; 98 99 ~CheckedOutputFd() { 100 if (fd_ == NULL) 101 return; 102 103 if (*fd_ >= 0) 104 return; 105 106 *fd_ = timeline_.CreateDummyFence().Release(); 107 108 if (*fd_ < 0) 109 ALOGE("Failed to fill %s (%p == %d) before destruction", 110 description_.c_str(), fd_, *fd_); 111 } 112 113 private: 114 int *fd_ = NULL; 115 std::string description_; 116 DummySwSyncTimeline &timeline_; 117 }; 118 119 typedef struct hwc_drm_display { 120 struct hwc_context_t *ctx; 121 int display; 122 123 std::vector<uint32_t> config_ids; 124 125 VSyncWorker vsync_worker; 126 } hwc_drm_display_t; 127 128 class DrmHotplugHandler : public DrmEventHandler { 129 public: 130 void Init(DrmResources *drm, const struct hwc_procs *procs) { 131 drm_ = drm; 132 procs_ = procs; 133 } 134 135 void HandleEvent(uint64_t timestamp_us) { 136 for (auto &conn : drm_->connectors()) { 137 drmModeConnection old_state = conn->state(); 138 139 conn->UpdateModes(); 140 141 drmModeConnection cur_state = conn->state(); 142 143 if (cur_state == old_state) 144 continue; 145 146 ALOGI("%s event @%" PRIu64 " for connector %u\n", 147 cur_state == DRM_MODE_CONNECTED ? "Plug" : "Unplug", timestamp_us, 148 conn->id()); 149 150 if (cur_state == DRM_MODE_CONNECTED) { 151 // Take the first one, then look for the preferred 152 DrmMode mode = *(conn->modes().begin()); 153 for (auto &m : conn->modes()) { 154 if (m.type() & DRM_MODE_TYPE_PREFERRED) { 155 mode = m; 156 break; 157 } 158 } 159 ALOGI("Setting mode %dx%d for connector %d\n", mode.h_display(), 160 mode.v_display(), conn->id()); 161 int ret = drm_->SetDisplayActiveMode(conn->display(), mode); 162 if (ret) { 163 ALOGE("Failed to set active config %d", ret); 164 return; 165 } 166 } else { 167 int ret = drm_->SetDpmsMode(conn->display(), DRM_MODE_DPMS_OFF); 168 if (ret) { 169 ALOGE("Failed to set dpms mode off %d", ret); 170 return; 171 } 172 } 173 174 procs_->hotplug(procs_, conn->display(), 175 cur_state == DRM_MODE_CONNECTED ? 1 : 0); 176 } 177 } 178 179 private: 180 DrmResources *drm_ = NULL; 181 const struct hwc_procs *procs_ = NULL; 182 }; 183 184 struct hwc_context_t { 185 // map of display:hwc_drm_display_t 186 typedef std::map<int, hwc_drm_display_t> DisplayMap; 187 188 ~hwc_context_t() { 189 virtual_compositor_worker.Exit(); 190 } 191 192 hwc_composer_device_1_t device; 193 hwc_procs_t const *procs = NULL; 194 195 DisplayMap displays; 196 DrmResources drm; 197 std::unique_ptr<Importer> importer; 198 const gralloc_module_t *gralloc; 199 DummySwSyncTimeline dummy_timeline; 200 VirtualCompositorWorker virtual_compositor_worker; 201 DrmHotplugHandler hotplug_handler; 202 }; 203 204 static native_handle_t *dup_buffer_handle(buffer_handle_t handle) { 205 native_handle_t *new_handle = 206 native_handle_create(handle->numFds, handle->numInts); 207 if (new_handle == NULL) 208 return NULL; 209 210 const int *old_data = handle->data; 211 int *new_data = new_handle->data; 212 for (int i = 0; i < handle->numFds; i++) { 213 *new_data = dup(*old_data); 214 old_data++; 215 new_data++; 216 } 217 memcpy(new_data, old_data, sizeof(int) * handle->numInts); 218 219 return new_handle; 220 } 221 222 static void free_buffer_handle(native_handle_t *handle) { 223 int ret = native_handle_close(handle); 224 if (ret) 225 ALOGE("Failed to close native handle %d", ret); 226 ret = native_handle_delete(handle); 227 if (ret) 228 ALOGE("Failed to delete native handle %d", ret); 229 } 230 231 const hwc_drm_bo *DrmHwcBuffer::operator->() const { 232 if (importer_ == NULL) { 233 ALOGE("Access of non-existent BO"); 234 exit(1); 235 return NULL; 236 } 237 return &bo_; 238 } 239 240 void DrmHwcBuffer::Clear() { 241 if (importer_ != NULL) { 242 importer_->ReleaseBuffer(&bo_); 243 importer_ = NULL; 244 } 245 } 246 247 int DrmHwcBuffer::ImportBuffer(buffer_handle_t handle, Importer *importer) { 248 hwc_drm_bo tmp_bo; 249 250 int ret = importer->ImportBuffer(handle, &tmp_bo); 251 if (ret) 252 return ret; 253 254 if (importer_ != NULL) { 255 importer_->ReleaseBuffer(&bo_); 256 } 257 258 importer_ = importer; 259 260 bo_ = tmp_bo; 261 262 return 0; 263 } 264 265 int DrmHwcNativeHandle::CopyBufferHandle(buffer_handle_t handle, 266 const gralloc_module_t *gralloc) { 267 native_handle_t *handle_copy = dup_buffer_handle(handle); 268 if (handle_copy == NULL) { 269 ALOGE("Failed to duplicate handle"); 270 return -ENOMEM; 271 } 272 273 int ret = gralloc->registerBuffer(gralloc, handle_copy); 274 if (ret) { 275 ALOGE("Failed to register buffer handle %d", ret); 276 free_buffer_handle(handle_copy); 277 return ret; 278 } 279 280 Clear(); 281 282 gralloc_ = gralloc; 283 handle_ = handle_copy; 284 285 return 0; 286 } 287 288 DrmHwcNativeHandle::~DrmHwcNativeHandle() { 289 Clear(); 290 } 291 292 void DrmHwcNativeHandle::Clear() { 293 if (gralloc_ != NULL && handle_ != NULL) { 294 gralloc_->unregisterBuffer(gralloc_, handle_); 295 free_buffer_handle(handle_); 296 gralloc_ = NULL; 297 handle_ = NULL; 298 } 299 } 300 301 int DrmHwcLayer::InitFromHwcLayer(hwc_layer_1_t *sf_layer, Importer *importer, 302 const gralloc_module_t *gralloc) { 303 sf_handle = sf_layer->handle; 304 alpha = sf_layer->planeAlpha; 305 306 source_crop = DrmHwcRect<float>( 307 sf_layer->sourceCropf.left, sf_layer->sourceCropf.top, 308 sf_layer->sourceCropf.right, sf_layer->sourceCropf.bottom); 309 display_frame = DrmHwcRect<int>( 310 sf_layer->displayFrame.left, sf_layer->displayFrame.top, 311 sf_layer->displayFrame.right, sf_layer->displayFrame.bottom); 312 313 transform = 0; 314 // 270* and 180* cannot be combined with flips. More specifically, they 315 // already contain both horizontal and vertical flips, so those fields are 316 // redundant in this case. 90* rotation can be combined with either horizontal 317 // flip or vertical flip, so treat it differently 318 if (sf_layer->transform == HWC_TRANSFORM_ROT_270) { 319 transform = DrmHwcTransform::kRotate270; 320 } else if (sf_layer->transform == HWC_TRANSFORM_ROT_180) { 321 transform = DrmHwcTransform::kRotate180; 322 } else { 323 if (sf_layer->transform & HWC_TRANSFORM_FLIP_H) 324 transform |= DrmHwcTransform::kFlipH; 325 if (sf_layer->transform & HWC_TRANSFORM_FLIP_V) 326 transform |= DrmHwcTransform::kFlipV; 327 if (sf_layer->transform & HWC_TRANSFORM_ROT_90) 328 transform |= DrmHwcTransform::kRotate90; 329 } 330 331 switch (sf_layer->blending) { 332 case HWC_BLENDING_NONE: 333 blending = DrmHwcBlending::kNone; 334 break; 335 case HWC_BLENDING_PREMULT: 336 blending = DrmHwcBlending::kPreMult; 337 break; 338 case HWC_BLENDING_COVERAGE: 339 blending = DrmHwcBlending::kCoverage; 340 break; 341 default: 342 ALOGE("Invalid blending in hwc_layer_1_t %d", sf_layer->blending); 343 return -EINVAL; 344 } 345 346 int ret = buffer.ImportBuffer(sf_layer->handle, importer); 347 if (ret) 348 return ret; 349 350 ret = handle.CopyBufferHandle(sf_layer->handle, gralloc); 351 if (ret) 352 return ret; 353 354 ret = gralloc->perform(gralloc, GRALLOC_MODULE_PERFORM_GET_USAGE, 355 handle.get(), &gralloc_buffer_usage); 356 if (ret) { 357 ALOGE("Failed to get usage for buffer %p (%d)", handle.get(), ret); 358 return ret; 359 } 360 361 return 0; 362 } 363 364 static void hwc_dump(struct hwc_composer_device_1 *dev, char *buff, 365 int buff_len) { 366 struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common; 367 std::ostringstream out; 368 369 ctx->drm.compositor()->Dump(&out); 370 std::string out_str = out.str(); 371 strncpy(buff, out_str.c_str(), 372 std::min((size_t)buff_len, out_str.length() + 1)); 373 buff[buff_len - 1] = '\0'; 374 } 375 376 static bool hwc_skip_layer(const std::pair<int, int> &indices, int i) { 377 return indices.first >= 0 && i >= indices.first && i <= indices.second; 378 } 379 380 static int hwc_prepare(hwc_composer_device_1_t *dev, size_t num_displays, 381 hwc_display_contents_1_t **display_contents) { 382 struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common; 383 384 for (int i = 0; i < (int)num_displays; ++i) { 385 if (!display_contents[i]) 386 continue; 387 388 bool use_framebuffer_target = false; 389 DrmMode mode; 390 if (i == HWC_DISPLAY_VIRTUAL) { 391 use_framebuffer_target = true; 392 } else { 393 DrmConnector *c = ctx->drm.GetConnectorForDisplay(i); 394 if (!c) { 395 ALOGE("Failed to get DrmConnector for display %d", i); 396 return -ENODEV; 397 } 398 mode = c->active_mode(); 399 } 400 401 // Since we can't composite HWC_SKIP_LAYERs by ourselves, we'll let SF 402 // handle all layers in between the first and last skip layers. So find the 403 // outer indices and mark everything in between as HWC_FRAMEBUFFER 404 std::pair<int, int> skip_layer_indices(-1, -1); 405 int num_layers = display_contents[i]->numHwLayers; 406 for (int j = 0; !use_framebuffer_target && j < num_layers; ++j) { 407 hwc_layer_1_t *layer = &display_contents[i]->hwLayers[j]; 408 409 if (!(layer->flags & HWC_SKIP_LAYER)) 410 continue; 411 412 if (skip_layer_indices.first == -1) 413 skip_layer_indices.first = j; 414 skip_layer_indices.second = j; 415 } 416 417 for (int j = 0; j < num_layers; ++j) { 418 hwc_layer_1_t *layer = &display_contents[i]->hwLayers[j]; 419 420 if (!use_framebuffer_target && !hwc_skip_layer(skip_layer_indices, j)) { 421 // If the layer is off the screen, don't earmark it for an overlay. 422 // We'll leave it as-is, which effectively just drops it from the frame 423 const hwc_rect_t *frame = &layer->displayFrame; 424 if ((frame->right - frame->left) <= 0 || 425 (frame->bottom - frame->top) <= 0 || 426 frame->right <= 0 || frame->bottom <= 0 || 427 frame->left >= (int)mode.h_display() || 428 frame->top >= (int)mode.v_display()) 429 continue; 430 431 if (layer->compositionType == HWC_FRAMEBUFFER) 432 layer->compositionType = HWC_OVERLAY; 433 } else { 434 switch (layer->compositionType) { 435 case HWC_OVERLAY: 436 case HWC_BACKGROUND: 437 case HWC_SIDEBAND: 438 case HWC_CURSOR_OVERLAY: 439 layer->compositionType = HWC_FRAMEBUFFER; 440 break; 441 } 442 } 443 } 444 } 445 446 return 0; 447 } 448 449 static void hwc_add_layer_to_retire_fence( 450 hwc_layer_1_t *layer, hwc_display_contents_1_t *display_contents) { 451 if (layer->releaseFenceFd < 0) 452 return; 453 454 if (display_contents->retireFenceFd >= 0) { 455 int old_retire_fence = display_contents->retireFenceFd; 456 display_contents->retireFenceFd = 457 sync_merge("dc_retire", old_retire_fence, layer->releaseFenceFd); 458 close(old_retire_fence); 459 } else { 460 display_contents->retireFenceFd = dup(layer->releaseFenceFd); 461 } 462 } 463 464 static int hwc_set(hwc_composer_device_1_t *dev, size_t num_displays, 465 hwc_display_contents_1_t **sf_display_contents) { 466 ATRACE_CALL(); 467 struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common; 468 int ret = 0; 469 470 std::vector<CheckedOutputFd> checked_output_fences; 471 std::vector<DrmHwcDisplayContents> displays_contents; 472 std::vector<DrmCompositionDisplayLayersMap> layers_map; 473 std::vector<std::vector<size_t>> layers_indices; 474 displays_contents.reserve(num_displays); 475 // layers_map.reserve(num_displays); 476 layers_indices.reserve(num_displays); 477 478 // Phase one does nothing that would cause errors. Only take ownership of FDs. 479 for (size_t i = 0; i < num_displays; ++i) { 480 hwc_display_contents_1_t *dc = sf_display_contents[i]; 481 displays_contents.emplace_back(); 482 DrmHwcDisplayContents &display_contents = displays_contents.back(); 483 layers_indices.emplace_back(); 484 std::vector<size_t> &indices_to_composite = layers_indices.back(); 485 486 if (!sf_display_contents[i]) 487 continue; 488 489 if (i == HWC_DISPLAY_VIRTUAL) { 490 ctx->virtual_compositor_worker.QueueComposite(dc); 491 continue; 492 } 493 494 std::ostringstream display_index_formatter; 495 display_index_formatter << "retire fence for display " << i; 496 std::string display_fence_description(display_index_formatter.str()); 497 checked_output_fences.emplace_back(&dc->retireFenceFd, 498 display_fence_description.c_str(), 499 ctx->dummy_timeline); 500 display_contents.retire_fence = OutputFd(&dc->retireFenceFd); 501 502 size_t num_dc_layers = dc->numHwLayers; 503 int framebuffer_target_index = -1; 504 for (size_t j = 0; j < num_dc_layers; ++j) { 505 hwc_layer_1_t *sf_layer = &dc->hwLayers[j]; 506 if (sf_layer->compositionType == HWC_FRAMEBUFFER_TARGET) { 507 framebuffer_target_index = j; 508 break; 509 } 510 } 511 512 for (size_t j = 0; j < num_dc_layers; ++j) { 513 hwc_layer_1_t *sf_layer = &dc->hwLayers[j]; 514 515 display_contents.layers.emplace_back(); 516 DrmHwcLayer &layer = display_contents.layers.back(); 517 518 // In prepare() we marked all layers FRAMEBUFFER between SKIP_LAYER's. 519 // This means we should insert the FB_TARGET layer in the composition 520 // stack at the location of the first skip layer, and ignore the rest. 521 if (sf_layer->flags & HWC_SKIP_LAYER) { 522 if (framebuffer_target_index < 0) 523 continue; 524 int idx = framebuffer_target_index; 525 framebuffer_target_index = -1; 526 hwc_layer_1_t *fbt_layer = &dc->hwLayers[idx]; 527 if (!fbt_layer->handle || (fbt_layer->flags & HWC_SKIP_LAYER)) { 528 ALOGE("Invalid HWC_FRAMEBUFFER_TARGET with HWC_SKIP_LAYER present"); 529 continue; 530 } 531 indices_to_composite.push_back(idx); 532 continue; 533 } 534 535 if (sf_layer->compositionType == HWC_OVERLAY) 536 indices_to_composite.push_back(j); 537 538 layer.acquire_fence.Set(sf_layer->acquireFenceFd); 539 sf_layer->acquireFenceFd = -1; 540 541 std::ostringstream layer_fence_formatter; 542 layer_fence_formatter << "release fence for layer " << j << " of display " 543 << i; 544 std::string layer_fence_description(layer_fence_formatter.str()); 545 checked_output_fences.emplace_back(&sf_layer->releaseFenceFd, 546 layer_fence_description.c_str(), 547 ctx->dummy_timeline); 548 layer.release_fence = OutputFd(&sf_layer->releaseFenceFd); 549 } 550 551 // This is a catch-all in case we get a frame without any overlay layers, or 552 // skip layers, but with a value fb_target layer. This _shouldn't_ happen, 553 // but it's not ruled out by the hwc specification 554 if (indices_to_composite.empty() && framebuffer_target_index >= 0) { 555 hwc_layer_1_t *sf_layer = &dc->hwLayers[framebuffer_target_index]; 556 if (!sf_layer->handle || (sf_layer->flags & HWC_SKIP_LAYER)) { 557 ALOGE( 558 "Expected valid layer with HWC_FRAMEBUFFER_TARGET when all " 559 "HWC_OVERLAY layers are skipped."); 560 ret = -EINVAL; 561 } 562 indices_to_composite.push_back(framebuffer_target_index); 563 } 564 } 565 566 if (ret) 567 return ret; 568 569 for (size_t i = 0; i < num_displays; ++i) { 570 hwc_display_contents_1_t *dc = sf_display_contents[i]; 571 DrmHwcDisplayContents &display_contents = displays_contents[i]; 572 if (!sf_display_contents[i] || i == HWC_DISPLAY_VIRTUAL) 573 continue; 574 575 layers_map.emplace_back(); 576 DrmCompositionDisplayLayersMap &map = layers_map.back(); 577 map.display = i; 578 map.geometry_changed = 579 (dc->flags & HWC_GEOMETRY_CHANGED) == HWC_GEOMETRY_CHANGED; 580 std::vector<size_t> &indices_to_composite = layers_indices[i]; 581 for (size_t j : indices_to_composite) { 582 hwc_layer_1_t *sf_layer = &dc->hwLayers[j]; 583 584 DrmHwcLayer &layer = display_contents.layers[j]; 585 586 ret = layer.InitFromHwcLayer(sf_layer, ctx->importer.get(), ctx->gralloc); 587 if (ret) { 588 ALOGE("Failed to init composition from layer %d", ret); 589 return ret; 590 } 591 map.layers.emplace_back(std::move(layer)); 592 } 593 } 594 595 std::unique_ptr<DrmComposition> composition( 596 ctx->drm.compositor()->CreateComposition(ctx->importer.get())); 597 if (!composition) { 598 ALOGE("Drm composition init failed"); 599 return -EINVAL; 600 } 601 602 ret = composition->SetLayers(layers_map.size(), layers_map.data()); 603 if (ret) { 604 return -EINVAL; 605 } 606 607 ret = ctx->drm.compositor()->QueueComposition(std::move(composition)); 608 if (ret) { 609 return -EINVAL; 610 } 611 612 for (size_t i = 0; i < num_displays; ++i) { 613 hwc_display_contents_1_t *dc = sf_display_contents[i]; 614 if (!dc) 615 continue; 616 617 size_t num_dc_layers = dc->numHwLayers; 618 for (size_t j = 0; j < num_dc_layers; ++j) { 619 hwc_layer_1_t *layer = &dc->hwLayers[j]; 620 if (layer->flags & HWC_SKIP_LAYER) 621 continue; 622 hwc_add_layer_to_retire_fence(layer, dc); 623 } 624 } 625 626 composition.reset(NULL); 627 628 return ret; 629 } 630 631 static int hwc_event_control(struct hwc_composer_device_1 *dev, int display, 632 int event, int enabled) { 633 if (event != HWC_EVENT_VSYNC || (enabled != 0 && enabled != 1)) 634 return -EINVAL; 635 636 struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common; 637 hwc_drm_display_t *hd = &ctx->displays[display]; 638 hd->vsync_worker.VSyncControl(enabled); 639 return 0; 640 } 641 642 static int hwc_set_power_mode(struct hwc_composer_device_1 *dev, int display, 643 int mode) { 644 struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common; 645 646 uint64_t dpmsValue = 0; 647 switch (mode) { 648 case HWC_POWER_MODE_OFF: 649 dpmsValue = DRM_MODE_DPMS_OFF; 650 break; 651 652 /* We can't support dozing right now, so go full on */ 653 case HWC_POWER_MODE_DOZE: 654 case HWC_POWER_MODE_DOZE_SUSPEND: 655 case HWC_POWER_MODE_NORMAL: 656 dpmsValue = DRM_MODE_DPMS_ON; 657 break; 658 }; 659 return ctx->drm.SetDpmsMode(display, dpmsValue); 660 } 661 662 static int hwc_query(struct hwc_composer_device_1 * /* dev */, int what, 663 int *value) { 664 switch (what) { 665 case HWC_BACKGROUND_LAYER_SUPPORTED: 666 *value = 0; /* TODO: We should do this */ 667 break; 668 case HWC_VSYNC_PERIOD: 669 ALOGW("Query for deprecated vsync value, returning 60Hz"); 670 *value = 1000 * 1000 * 1000 / 60; 671 break; 672 case HWC_DISPLAY_TYPES_SUPPORTED: 673 *value = HWC_DISPLAY_PRIMARY_BIT | HWC_DISPLAY_EXTERNAL_BIT | 674 HWC_DISPLAY_VIRTUAL_BIT; 675 break; 676 } 677 return 0; 678 } 679 680 static void hwc_register_procs(struct hwc_composer_device_1 *dev, 681 hwc_procs_t const *procs) { 682 struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common; 683 684 ctx->procs = procs; 685 686 for (std::pair<const int, hwc_drm_display> &display_entry : ctx->displays) 687 display_entry.second.vsync_worker.SetProcs(procs); 688 689 ctx->hotplug_handler.Init(&ctx->drm, procs); 690 ctx->drm.event_listener()->RegisterHotplugHandler(&ctx->hotplug_handler); 691 } 692 693 static int hwc_get_display_configs(struct hwc_composer_device_1 *dev, 694 int display, uint32_t *configs, 695 size_t *num_configs) { 696 if (!*num_configs) 697 return 0; 698 699 struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common; 700 hwc_drm_display_t *hd = &ctx->displays[display]; 701 hd->config_ids.clear(); 702 703 DrmConnector *connector = ctx->drm.GetConnectorForDisplay(display); 704 if (!connector) { 705 ALOGE("Failed to get connector for display %d", display); 706 return -ENODEV; 707 } 708 709 int ret = connector->UpdateModes(); 710 if (ret) { 711 ALOGE("Failed to update display modes %d", ret); 712 return ret; 713 } 714 715 for (const DrmMode &mode : connector->modes()) { 716 size_t idx = hd->config_ids.size(); 717 if (idx == *num_configs) 718 break; 719 hd->config_ids.push_back(mode.id()); 720 configs[idx] = mode.id(); 721 } 722 *num_configs = hd->config_ids.size(); 723 return *num_configs == 0 ? -1 : 0; 724 } 725 726 static int hwc_get_display_attributes(struct hwc_composer_device_1 *dev, 727 int display, uint32_t config, 728 const uint32_t *attributes, 729 int32_t *values) { 730 struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common; 731 DrmConnector *c = ctx->drm.GetConnectorForDisplay(display); 732 if (!c) { 733 ALOGE("Failed to get DrmConnector for display %d", display); 734 return -ENODEV; 735 } 736 DrmMode mode; 737 for (const DrmMode &conn_mode : c->modes()) { 738 if (conn_mode.id() == config) { 739 mode = conn_mode; 740 break; 741 } 742 } 743 if (mode.id() == 0) { 744 ALOGE("Failed to find active mode for display %d", display); 745 return -ENOENT; 746 } 747 748 uint32_t mm_width = c->mm_width(); 749 uint32_t mm_height = c->mm_height(); 750 for (int i = 0; attributes[i] != HWC_DISPLAY_NO_ATTRIBUTE; ++i) { 751 switch (attributes[i]) { 752 case HWC_DISPLAY_VSYNC_PERIOD: 753 values[i] = 1000 * 1000 * 1000 / mode.v_refresh(); 754 break; 755 case HWC_DISPLAY_WIDTH: 756 values[i] = mode.h_display(); 757 break; 758 case HWC_DISPLAY_HEIGHT: 759 values[i] = mode.v_display(); 760 break; 761 case HWC_DISPLAY_DPI_X: 762 /* Dots per 1000 inches */ 763 values[i] = mm_width ? (mode.h_display() * UM_PER_INCH) / mm_width : 0; 764 break; 765 case HWC_DISPLAY_DPI_Y: 766 /* Dots per 1000 inches */ 767 values[i] = 768 mm_height ? (mode.v_display() * UM_PER_INCH) / mm_height : 0; 769 break; 770 } 771 } 772 return 0; 773 } 774 775 static int hwc_get_active_config(struct hwc_composer_device_1 *dev, 776 int display) { 777 struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common; 778 DrmConnector *c = ctx->drm.GetConnectorForDisplay(display); 779 if (!c) { 780 ALOGE("Failed to get DrmConnector for display %d", display); 781 return -ENODEV; 782 } 783 784 DrmMode mode = c->active_mode(); 785 hwc_drm_display_t *hd = &ctx->displays[display]; 786 for (size_t i = 0; i < hd->config_ids.size(); ++i) { 787 if (hd->config_ids[i] == mode.id()) 788 return i; 789 } 790 return -1; 791 } 792 793 static int hwc_set_active_config(struct hwc_composer_device_1 *dev, int display, 794 int index) { 795 struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common; 796 hwc_drm_display_t *hd = &ctx->displays[display]; 797 if (index >= (int)hd->config_ids.size()) { 798 ALOGE("Invalid config index %d passed in", index); 799 return -EINVAL; 800 } 801 802 DrmConnector *c = ctx->drm.GetConnectorForDisplay(display); 803 if (!c) { 804 ALOGE("Failed to get connector for display %d", display); 805 return -ENODEV; 806 } 807 808 if (c->state() != DRM_MODE_CONNECTED) 809 return -ENODEV; 810 811 DrmMode mode; 812 for (const DrmMode &conn_mode : c->modes()) { 813 if (conn_mode.id() == hd->config_ids[index]) { 814 mode = conn_mode; 815 break; 816 } 817 } 818 if (mode.id() != hd->config_ids[index]) { 819 ALOGE("Could not find active mode for %d/%d", index, hd->config_ids[index]); 820 return -ENOENT; 821 } 822 int ret = ctx->drm.SetDisplayActiveMode(display, mode); 823 if (ret) { 824 ALOGE("Failed to set active config %d", ret); 825 return ret; 826 } 827 ret = ctx->drm.SetDpmsMode(display, DRM_MODE_DPMS_ON); 828 if (ret) { 829 ALOGE("Failed to set dpms mode on %d", ret); 830 return ret; 831 } 832 return ret; 833 } 834 835 static int hwc_device_close(struct hw_device_t *dev) { 836 struct hwc_context_t *ctx = (struct hwc_context_t *)dev; 837 delete ctx; 838 return 0; 839 } 840 841 /* 842 * TODO: This function sets the active config to the first one in the list. This 843 * should be fixed such that it selects the preferred mode for the display, or 844 * some other, saner, method of choosing the config. 845 */ 846 static int hwc_set_initial_config(hwc_drm_display_t *hd) { 847 uint32_t config; 848 size_t num_configs = 1; 849 int ret = hwc_get_display_configs(&hd->ctx->device, hd->display, &config, 850 &num_configs); 851 if (ret || !num_configs) 852 return 0; 853 854 ret = hwc_set_active_config(&hd->ctx->device, hd->display, 0); 855 if (ret) { 856 ALOGE("Failed to set active config d=%d ret=%d", hd->display, ret); 857 return ret; 858 } 859 860 return ret; 861 } 862 863 static int hwc_initialize_display(struct hwc_context_t *ctx, int display) { 864 hwc_drm_display_t *hd = &ctx->displays[display]; 865 hd->ctx = ctx; 866 hd->display = display; 867 868 int ret = hwc_set_initial_config(hd); 869 if (ret) { 870 ALOGE("Failed to set initial config for d=%d ret=%d", display, ret); 871 return ret; 872 } 873 874 ret = hd->vsync_worker.Init(&ctx->drm, display); 875 if (ret) { 876 ALOGE("Failed to create event worker for display %d %d\n", display, ret); 877 return ret; 878 } 879 880 return 0; 881 } 882 883 static int hwc_enumerate_displays(struct hwc_context_t *ctx) { 884 int ret; 885 for (auto &conn : ctx->drm.connectors()) { 886 ret = hwc_initialize_display(ctx, conn->display()); 887 if (ret) { 888 ALOGE("Failed to initialize display %d", conn->display()); 889 return ret; 890 } 891 } 892 893 ret = ctx->virtual_compositor_worker.Init(); 894 if (ret) { 895 ALOGE("Failed to initialize virtual compositor worker"); 896 return ret; 897 } 898 return 0; 899 } 900 901 static int hwc_device_open(const struct hw_module_t *module, const char *name, 902 struct hw_device_t **dev) { 903 if (strcmp(name, HWC_HARDWARE_COMPOSER)) { 904 ALOGE("Invalid module name- %s", name); 905 return -EINVAL; 906 } 907 908 std::unique_ptr<hwc_context_t> ctx(new hwc_context_t()); 909 if (!ctx) { 910 ALOGE("Failed to allocate hwc context"); 911 return -ENOMEM; 912 } 913 914 int ret = ctx->drm.Init(); 915 if (ret) { 916 ALOGE("Can't initialize Drm object %d", ret); 917 return ret; 918 } 919 920 ret = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, 921 (const hw_module_t **)&ctx->gralloc); 922 if (ret) { 923 ALOGE("Failed to open gralloc module %d", ret); 924 return ret; 925 } 926 927 ret = ctx->dummy_timeline.Init(); 928 if (ret) { 929 ALOGE("Failed to create dummy sw sync timeline %d", ret); 930 return ret; 931 } 932 933 ctx->importer.reset(Importer::CreateInstance(&ctx->drm)); 934 if (!ctx->importer) { 935 ALOGE("Failed to create importer instance"); 936 return ret; 937 } 938 939 ret = hwc_enumerate_displays(ctx.get()); 940 if (ret) { 941 ALOGE("Failed to enumerate displays: %s", strerror(ret)); 942 return ret; 943 } 944 945 ctx->device.common.tag = HARDWARE_DEVICE_TAG; 946 ctx->device.common.version = HWC_DEVICE_API_VERSION_1_4; 947 ctx->device.common.module = const_cast<hw_module_t *>(module); 948 ctx->device.common.close = hwc_device_close; 949 950 ctx->device.dump = hwc_dump; 951 ctx->device.prepare = hwc_prepare; 952 ctx->device.set = hwc_set; 953 ctx->device.eventControl = hwc_event_control; 954 ctx->device.setPowerMode = hwc_set_power_mode; 955 ctx->device.query = hwc_query; 956 ctx->device.registerProcs = hwc_register_procs; 957 ctx->device.getDisplayConfigs = hwc_get_display_configs; 958 ctx->device.getDisplayAttributes = hwc_get_display_attributes; 959 ctx->device.getActiveConfig = hwc_get_active_config; 960 ctx->device.setActiveConfig = hwc_set_active_config; 961 ctx->device.setCursorPositionAsync = NULL; /* TODO: Add cursor */ 962 963 *dev = &ctx->device.common; 964 ctx.release(); 965 966 return 0; 967 } 968 } 969 970 static struct hw_module_methods_t hwc_module_methods = { 971 .open = android::hwc_device_open 972 }; 973 974 hwc_module_t HAL_MODULE_INFO_SYM = { 975 .common = { 976 .tag = HARDWARE_MODULE_TAG, 977 .version_major = 1, 978 .version_minor = 0, 979 .id = HWC_HARDWARE_MODULE_ID, 980 .name = "DRM hwcomposer module", 981 .author = "The Android Open Source Project", 982 .methods = &hwc_module_methods, 983 .dso = NULL, 984 .reserved = {0}, 985 } 986 }; 987