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 <pthread.h> 37 #include <sys/param.h> 38 #include <sys/resource.h> 39 #include <xf86drm.h> 40 #include <xf86drmMode.h> 41 42 #include <cutils/log.h> 43 #include <cutils/properties.h> 44 #include <hardware/hardware.h> 45 #include <hardware/hwcomposer.h> 46 #include <sw_sync.h> 47 #include <sync/sync.h> 48 #include <utils/Trace.h> 49 50 #define UM_PER_INCH 25400 51 52 namespace android { 53 54 class DummySwSyncTimeline { 55 public: 56 int Init() { 57 int ret = timeline_fd_.Set(sw_sync_timeline_create()); 58 if (ret < 0) 59 return ret; 60 return 0; 61 } 62 63 UniqueFd CreateDummyFence() { 64 int ret = sw_sync_fence_create(timeline_fd_.get(), "dummy fence", 65 timeline_pt_ + 1); 66 if (ret < 0) { 67 ALOGE("Failed to create dummy fence %d", ret); 68 return ret; 69 } 70 71 UniqueFd ret_fd(ret); 72 73 ret = sw_sync_timeline_inc(timeline_fd_.get(), 1); 74 if (ret) { 75 ALOGE("Failed to increment dummy sync timeline %d", ret); 76 return ret; 77 } 78 79 ++timeline_pt_; 80 return ret_fd; 81 } 82 83 private: 84 UniqueFd timeline_fd_; 85 int timeline_pt_ = 0; 86 }; 87 88 struct CheckedOutputFd { 89 CheckedOutputFd(int *fd, const char *description, 90 DummySwSyncTimeline &timeline) 91 : fd_(fd), description_(description), timeline_(timeline) { 92 } 93 CheckedOutputFd(CheckedOutputFd &&rhs) 94 : description_(rhs.description_), timeline_(rhs.timeline_) { 95 std::swap(fd_, rhs.fd_); 96 } 97 98 CheckedOutputFd &operator=(const CheckedOutputFd &rhs) = delete; 99 100 ~CheckedOutputFd() { 101 if (fd_ == NULL) 102 return; 103 104 if (*fd_ >= 0) 105 return; 106 107 *fd_ = timeline_.CreateDummyFence().Release(); 108 109 if (*fd_ < 0) 110 ALOGE("Failed to fill %s (%p == %d) before destruction", 111 description_.c_str(), fd_, *fd_); 112 } 113 114 private: 115 int *fd_ = NULL; 116 std::string description_; 117 DummySwSyncTimeline &timeline_; 118 }; 119 120 typedef struct hwc_drm_display { 121 struct hwc_context_t *ctx; 122 int display; 123 124 std::vector<uint32_t> config_ids; 125 126 VSyncWorker vsync_worker; 127 } hwc_drm_display_t; 128 129 class DrmHotplugHandler : public DrmEventHandler { 130 public: 131 void Init(DrmResources *drm, const struct hwc_procs *procs) { 132 drm_ = drm; 133 procs_ = procs; 134 } 135 136 void HandleEvent(uint64_t timestamp_us) { 137 for (auto &conn : drm_->connectors()) { 138 drmModeConnection old_state = conn->state(); 139 140 conn->UpdateModes(); 141 142 drmModeConnection cur_state = conn->state(); 143 144 if (cur_state == old_state) 145 continue; 146 147 ALOGI("%s event @%" PRIu64 " for connector %u\n", 148 cur_state == DRM_MODE_CONNECTED ? "Plug" : "Unplug", timestamp_us, 149 conn->id()); 150 151 if (cur_state == DRM_MODE_CONNECTED) { 152 // Take the first one, then look for the preferred 153 DrmMode mode = *(conn->modes().begin()); 154 for (auto &m : conn->modes()) { 155 if (m.type() & DRM_MODE_TYPE_PREFERRED) { 156 mode = m; 157 break; 158 } 159 } 160 ALOGI("Setting mode %dx%d for connector %d\n", mode.h_display(), 161 mode.v_display(), conn->id()); 162 int ret = drm_->SetDisplayActiveMode(conn->display(), mode); 163 if (ret) { 164 ALOGE("Failed to set active config %d", ret); 165 return; 166 } 167 } else { 168 int ret = drm_->SetDpmsMode(conn->display(), DRM_MODE_DPMS_OFF); 169 if (ret) { 170 ALOGE("Failed to set dpms mode off %d", ret); 171 return; 172 } 173 } 174 175 procs_->hotplug(procs_, conn->display(), 176 cur_state == DRM_MODE_CONNECTED ? 1 : 0); 177 } 178 } 179 180 private: 181 DrmResources *drm_ = NULL; 182 const struct hwc_procs *procs_ = NULL; 183 }; 184 185 struct hwc_context_t { 186 // map of display:hwc_drm_display_t 187 typedef std::map<int, hwc_drm_display_t> DisplayMap; 188 189 ~hwc_context_t() { 190 virtual_compositor_worker.Exit(); 191 } 192 193 hwc_composer_device_1_t device; 194 hwc_procs_t const *procs = NULL; 195 196 DisplayMap displays; 197 DrmResources drm; 198 std::unique_ptr<Importer> importer; 199 const gralloc_module_t *gralloc; 200 DummySwSyncTimeline dummy_timeline; 201 VirtualCompositorWorker virtual_compositor_worker; 202 DrmHotplugHandler hotplug_handler; 203 }; 204 205 static native_handle_t *dup_buffer_handle(buffer_handle_t handle) { 206 native_handle_t *new_handle = 207 native_handle_create(handle->numFds, handle->numInts); 208 if (new_handle == NULL) 209 return NULL; 210 211 const int *old_data = handle->data; 212 int *new_data = new_handle->data; 213 for (int i = 0; i < handle->numFds; i++) { 214 *new_data = dup(*old_data); 215 old_data++; 216 new_data++; 217 } 218 memcpy(new_data, old_data, sizeof(int) * handle->numInts); 219 220 return new_handle; 221 } 222 223 static void free_buffer_handle(native_handle_t *handle) { 224 int ret = native_handle_close(handle); 225 if (ret) 226 ALOGE("Failed to close native handle %d", ret); 227 ret = native_handle_delete(handle); 228 if (ret) 229 ALOGE("Failed to delete native handle %d", ret); 230 } 231 232 const hwc_drm_bo *DrmHwcBuffer::operator->() const { 233 if (importer_ == NULL) { 234 ALOGE("Access of non-existent BO"); 235 exit(1); 236 return NULL; 237 } 238 return &bo_; 239 } 240 241 void DrmHwcBuffer::Clear() { 242 if (importer_ != NULL) { 243 importer_->ReleaseBuffer(&bo_); 244 importer_ = NULL; 245 } 246 } 247 248 int DrmHwcBuffer::ImportBuffer(buffer_handle_t handle, Importer *importer) { 249 hwc_drm_bo tmp_bo; 250 251 int ret = importer->ImportBuffer(handle, &tmp_bo); 252 if (ret) 253 return ret; 254 255 if (importer_ != NULL) { 256 importer_->ReleaseBuffer(&bo_); 257 } 258 259 importer_ = importer; 260 261 bo_ = tmp_bo; 262 263 return 0; 264 } 265 266 int DrmHwcNativeHandle::CopyBufferHandle(buffer_handle_t handle, 267 const gralloc_module_t *gralloc) { 268 native_handle_t *handle_copy = dup_buffer_handle(handle); 269 if (handle_copy == NULL) { 270 ALOGE("Failed to duplicate handle"); 271 return -ENOMEM; 272 } 273 274 int ret = gralloc->registerBuffer(gralloc, handle_copy); 275 if (ret) { 276 ALOGE("Failed to register buffer handle %d", ret); 277 free_buffer_handle(handle_copy); 278 return ret; 279 } 280 281 Clear(); 282 283 gralloc_ = gralloc; 284 handle_ = handle_copy; 285 286 return 0; 287 } 288 289 DrmHwcNativeHandle::~DrmHwcNativeHandle() { 290 Clear(); 291 } 292 293 void DrmHwcNativeHandle::Clear() { 294 if (gralloc_ != NULL && handle_ != NULL) { 295 gralloc_->unregisterBuffer(gralloc_, handle_); 296 free_buffer_handle(handle_); 297 gralloc_ = NULL; 298 handle_ = NULL; 299 } 300 } 301 302 int DrmHwcLayer::InitFromHwcLayer(hwc_layer_1_t *sf_layer, Importer *importer, 303 const gralloc_module_t *gralloc) { 304 sf_handle = sf_layer->handle; 305 alpha = sf_layer->planeAlpha; 306 307 source_crop = DrmHwcRect<float>( 308 sf_layer->sourceCropf.left, sf_layer->sourceCropf.top, 309 sf_layer->sourceCropf.right, sf_layer->sourceCropf.bottom); 310 display_frame = DrmHwcRect<int>( 311 sf_layer->displayFrame.left, sf_layer->displayFrame.top, 312 sf_layer->displayFrame.right, sf_layer->displayFrame.bottom); 313 314 transform = 0; 315 // 270* and 180* cannot be combined with flips. More specifically, they 316 // already contain both horizontal and vertical flips, so those fields are 317 // redundant in this case. 90* rotation can be combined with either horizontal 318 // flip or vertical flip, so treat it differently 319 if (sf_layer->transform == HWC_TRANSFORM_ROT_270) { 320 transform = DrmHwcTransform::kRotate270; 321 } else if (sf_layer->transform == HWC_TRANSFORM_ROT_180) { 322 transform = DrmHwcTransform::kRotate180; 323 } else { 324 if (sf_layer->transform & HWC_TRANSFORM_FLIP_H) 325 transform |= DrmHwcTransform::kFlipH; 326 if (sf_layer->transform & HWC_TRANSFORM_FLIP_V) 327 transform |= DrmHwcTransform::kFlipV; 328 if (sf_layer->transform & HWC_TRANSFORM_ROT_90) 329 transform |= DrmHwcTransform::kRotate90; 330 } 331 332 switch (sf_layer->blending) { 333 case HWC_BLENDING_NONE: 334 blending = DrmHwcBlending::kNone; 335 break; 336 case HWC_BLENDING_PREMULT: 337 blending = DrmHwcBlending::kPreMult; 338 break; 339 case HWC_BLENDING_COVERAGE: 340 blending = DrmHwcBlending::kCoverage; 341 break; 342 default: 343 ALOGE("Invalid blending in hwc_layer_1_t %d", sf_layer->blending); 344 return -EINVAL; 345 } 346 347 int ret = buffer.ImportBuffer(sf_layer->handle, importer); 348 if (ret) 349 return ret; 350 351 ret = handle.CopyBufferHandle(sf_layer->handle, gralloc); 352 if (ret) 353 return ret; 354 355 ret = gralloc->perform(gralloc, GRALLOC_MODULE_PERFORM_GET_USAGE, 356 handle.get(), &gralloc_buffer_usage); 357 if (ret) { 358 ALOGE("Failed to get usage for buffer %p (%d)", handle.get(), ret); 359 return ret; 360 } 361 362 return 0; 363 } 364 365 static void hwc_dump(struct hwc_composer_device_1 *dev, char *buff, 366 int buff_len) { 367 struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common; 368 std::ostringstream out; 369 370 ctx->drm.compositor()->Dump(&out); 371 std::string out_str = out.str(); 372 strncpy(buff, out_str.c_str(), 373 std::min((size_t)buff_len, out_str.length() + 1)); 374 buff[buff_len - 1] = '\0'; 375 } 376 377 static bool hwc_skip_layer(const std::pair<int, int> &indices, int i) { 378 return indices.first >= 0 && i >= indices.first && i <= indices.second; 379 } 380 381 static int hwc_prepare(hwc_composer_device_1_t *dev, size_t num_displays, 382 hwc_display_contents_1_t **display_contents) { 383 struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common; 384 385 for (int i = 0; i < (int)num_displays; ++i) { 386 if (!display_contents[i]) 387 continue; 388 389 bool use_framebuffer_target = false; 390 DrmMode mode; 391 if (i == HWC_DISPLAY_VIRTUAL) { 392 use_framebuffer_target = true; 393 } else { 394 DrmConnector *c = ctx->drm.GetConnectorForDisplay(i); 395 if (!c) { 396 ALOGE("Failed to get DrmConnector for display %d", i); 397 return -ENODEV; 398 } 399 mode = c->active_mode(); 400 } 401 402 // Since we can't composite HWC_SKIP_LAYERs by ourselves, we'll let SF 403 // handle all layers in between the first and last skip layers. So find the 404 // outer indices and mark everything in between as HWC_FRAMEBUFFER 405 std::pair<int, int> skip_layer_indices(-1, -1); 406 int num_layers = display_contents[i]->numHwLayers; 407 for (int j = 0; !use_framebuffer_target && j < num_layers; ++j) { 408 hwc_layer_1_t *layer = &display_contents[i]->hwLayers[j]; 409 410 if (!(layer->flags & HWC_SKIP_LAYER)) 411 continue; 412 413 if (skip_layer_indices.first == -1) 414 skip_layer_indices.first = j; 415 skip_layer_indices.second = j; 416 } 417 418 for (int j = 0; j < num_layers; ++j) { 419 hwc_layer_1_t *layer = &display_contents[i]->hwLayers[j]; 420 421 if (!use_framebuffer_target && !hwc_skip_layer(skip_layer_indices, j)) { 422 // If the layer is off the screen, don't earmark it for an overlay. 423 // We'll leave it as-is, which effectively just drops it from the frame 424 const hwc_rect_t *frame = &layer->displayFrame; 425 if ((frame->right - frame->left) <= 0 || 426 (frame->bottom - frame->top) <= 0 || 427 frame->right <= 0 || frame->bottom <= 0 || 428 frame->left >= (int)mode.h_display() || 429 frame->top >= (int)mode.v_display()) 430 continue; 431 432 if (layer->compositionType == HWC_FRAMEBUFFER) 433 layer->compositionType = HWC_OVERLAY; 434 } else { 435 switch (layer->compositionType) { 436 case HWC_OVERLAY: 437 case HWC_BACKGROUND: 438 case HWC_SIDEBAND: 439 case HWC_CURSOR_OVERLAY: 440 layer->compositionType = HWC_FRAMEBUFFER; 441 break; 442 } 443 } 444 } 445 } 446 447 return 0; 448 } 449 450 static void hwc_add_layer_to_retire_fence( 451 hwc_layer_1_t *layer, hwc_display_contents_1_t *display_contents) { 452 if (layer->releaseFenceFd < 0) 453 return; 454 455 if (display_contents->retireFenceFd >= 0) { 456 int old_retire_fence = display_contents->retireFenceFd; 457 display_contents->retireFenceFd = 458 sync_merge("dc_retire", old_retire_fence, layer->releaseFenceFd); 459 close(old_retire_fence); 460 } else { 461 display_contents->retireFenceFd = dup(layer->releaseFenceFd); 462 } 463 } 464 465 static int hwc_set(hwc_composer_device_1_t *dev, size_t num_displays, 466 hwc_display_contents_1_t **sf_display_contents) { 467 ATRACE_CALL(); 468 struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common; 469 int ret = 0; 470 471 std::vector<CheckedOutputFd> checked_output_fences; 472 std::vector<DrmHwcDisplayContents> displays_contents; 473 std::vector<DrmCompositionDisplayLayersMap> layers_map; 474 std::vector<std::vector<size_t>> layers_indices; 475 displays_contents.reserve(num_displays); 476 // layers_map.reserve(num_displays); 477 layers_indices.reserve(num_displays); 478 479 // Phase one does nothing that would cause errors. Only take ownership of FDs. 480 for (size_t i = 0; i < num_displays; ++i) { 481 hwc_display_contents_1_t *dc = sf_display_contents[i]; 482 displays_contents.emplace_back(); 483 DrmHwcDisplayContents &display_contents = displays_contents.back(); 484 layers_indices.emplace_back(); 485 std::vector<size_t> &indices_to_composite = layers_indices.back(); 486 487 if (!sf_display_contents[i]) 488 continue; 489 490 if (i == HWC_DISPLAY_VIRTUAL) { 491 ctx->virtual_compositor_worker.QueueComposite(dc); 492 continue; 493 } 494 495 std::ostringstream display_index_formatter; 496 display_index_formatter << "retire fence for display " << i; 497 std::string display_fence_description(display_index_formatter.str()); 498 checked_output_fences.emplace_back(&dc->retireFenceFd, 499 display_fence_description.c_str(), 500 ctx->dummy_timeline); 501 display_contents.retire_fence = OutputFd(&dc->retireFenceFd); 502 503 size_t num_dc_layers = dc->numHwLayers; 504 int framebuffer_target_index = -1; 505 for (size_t j = 0; j < num_dc_layers; ++j) { 506 hwc_layer_1_t *sf_layer = &dc->hwLayers[j]; 507 if (sf_layer->compositionType == HWC_FRAMEBUFFER_TARGET) { 508 framebuffer_target_index = j; 509 break; 510 } 511 } 512 513 for (size_t j = 0; j < num_dc_layers; ++j) { 514 hwc_layer_1_t *sf_layer = &dc->hwLayers[j]; 515 516 display_contents.layers.emplace_back(); 517 DrmHwcLayer &layer = display_contents.layers.back(); 518 519 // In prepare() we marked all layers FRAMEBUFFER between SKIP_LAYER's. 520 // This means we should insert the FB_TARGET layer in the composition 521 // stack at the location of the first skip layer, and ignore the rest. 522 if (sf_layer->flags & HWC_SKIP_LAYER) { 523 if (framebuffer_target_index < 0) 524 continue; 525 int idx = framebuffer_target_index; 526 framebuffer_target_index = -1; 527 hwc_layer_1_t *fbt_layer = &dc->hwLayers[idx]; 528 if (!fbt_layer->handle || (fbt_layer->flags & HWC_SKIP_LAYER)) { 529 ALOGE("Invalid HWC_FRAMEBUFFER_TARGET with HWC_SKIP_LAYER present"); 530 continue; 531 } 532 indices_to_composite.push_back(idx); 533 continue; 534 } 535 536 if (sf_layer->compositionType == HWC_OVERLAY) 537 indices_to_composite.push_back(j); 538 539 layer.acquire_fence.Set(sf_layer->acquireFenceFd); 540 sf_layer->acquireFenceFd = -1; 541 542 std::ostringstream layer_fence_formatter; 543 layer_fence_formatter << "release fence for layer " << j << " of display " 544 << i; 545 std::string layer_fence_description(layer_fence_formatter.str()); 546 checked_output_fences.emplace_back(&sf_layer->releaseFenceFd, 547 layer_fence_description.c_str(), 548 ctx->dummy_timeline); 549 layer.release_fence = OutputFd(&sf_layer->releaseFenceFd); 550 } 551 552 // This is a catch-all in case we get a frame without any overlay layers, or 553 // skip layers, but with a value fb_target layer. This _shouldn't_ happen, 554 // but it's not ruled out by the hwc specification 555 if (indices_to_composite.empty() && framebuffer_target_index >= 0) { 556 hwc_layer_1_t *sf_layer = &dc->hwLayers[framebuffer_target_index]; 557 if (!sf_layer->handle || (sf_layer->flags & HWC_SKIP_LAYER)) { 558 ALOGE( 559 "Expected valid layer with HWC_FRAMEBUFFER_TARGET when all " 560 "HWC_OVERLAY layers are skipped."); 561 ret = -EINVAL; 562 } 563 indices_to_composite.push_back(framebuffer_target_index); 564 } 565 } 566 567 if (ret) 568 return ret; 569 570 for (size_t i = 0; i < num_displays; ++i) { 571 hwc_display_contents_1_t *dc = sf_display_contents[i]; 572 DrmHwcDisplayContents &display_contents = displays_contents[i]; 573 if (!sf_display_contents[i] || i == HWC_DISPLAY_VIRTUAL) 574 continue; 575 576 layers_map.emplace_back(); 577 DrmCompositionDisplayLayersMap &map = layers_map.back(); 578 map.display = i; 579 map.geometry_changed = 580 (dc->flags & HWC_GEOMETRY_CHANGED) == HWC_GEOMETRY_CHANGED; 581 std::vector<size_t> &indices_to_composite = layers_indices[i]; 582 for (size_t j : indices_to_composite) { 583 hwc_layer_1_t *sf_layer = &dc->hwLayers[j]; 584 585 DrmHwcLayer &layer = display_contents.layers[j]; 586 587 ret = layer.InitFromHwcLayer(sf_layer, ctx->importer.get(), ctx->gralloc); 588 if (ret) { 589 ALOGE("Failed to init composition from layer %d", ret); 590 return ret; 591 } 592 map.layers.emplace_back(std::move(layer)); 593 } 594 } 595 596 std::unique_ptr<DrmComposition> composition( 597 ctx->drm.compositor()->CreateComposition(ctx->importer.get())); 598 if (!composition) { 599 ALOGE("Drm composition init failed"); 600 return -EINVAL; 601 } 602 603 ret = composition->SetLayers(layers_map.size(), layers_map.data()); 604 if (ret) { 605 return -EINVAL; 606 } 607 608 ret = ctx->drm.compositor()->QueueComposition(std::move(composition)); 609 if (ret) { 610 return -EINVAL; 611 } 612 613 for (size_t i = 0; i < num_displays; ++i) { 614 hwc_display_contents_1_t *dc = sf_display_contents[i]; 615 if (!dc) 616 continue; 617 618 size_t num_dc_layers = dc->numHwLayers; 619 for (size_t j = 0; j < num_dc_layers; ++j) { 620 hwc_layer_1_t *layer = &dc->hwLayers[j]; 621 if (layer->flags & HWC_SKIP_LAYER) 622 continue; 623 hwc_add_layer_to_retire_fence(layer, dc); 624 } 625 } 626 627 composition.reset(NULL); 628 629 return ret; 630 } 631 632 static int hwc_event_control(struct hwc_composer_device_1 *dev, int display, 633 int event, int enabled) { 634 if (event != HWC_EVENT_VSYNC || (enabled != 0 && enabled != 1)) 635 return -EINVAL; 636 637 struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common; 638 hwc_drm_display_t *hd = &ctx->displays[display]; 639 return hd->vsync_worker.VSyncControl(enabled); 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