diff options
Diffstat (limited to 'compositor/DrmDisplayCompositor.cpp')
-rw-r--r-- | compositor/DrmDisplayCompositor.cpp | 384 |
1 files changed, 4 insertions, 380 deletions
diff --git a/compositor/DrmDisplayCompositor.cpp b/compositor/DrmDisplayCompositor.cpp index 8d96d0e..2cc0da5 100644 --- a/compositor/DrmDisplayCompositor.cpp +++ b/compositor/DrmDisplayCompositor.cpp @@ -37,8 +37,6 @@ #include "drm/DrmPlane.h" #include "utils/autolock.h" -static const uint32_t kWaitWritebackFence = 100; // ms - namespace android { std::ostream &operator<<(std::ostream &str, FlatteningState state) { @@ -73,7 +71,6 @@ DrmDisplayCompositor::DrmDisplayCompositor() dump_frames_composited_(0), dump_last_timestamp_ns_(0), flatten_countdown_(FLATTEN_COUNTDOWN_INIT), - writeback_fence_(-1), flattening_state_(FlatteningState::kNone), frames_flattened_(0) { struct timespec ts {}; @@ -216,49 +213,8 @@ int DrmDisplayCompositor::DisablePlanes(DrmDisplayComposition *display_comp) { return 0; } -int DrmDisplayCompositor::SetupWritebackCommit(drmModeAtomicReqPtr pset, - uint32_t crtc_id, - DrmConnector *writeback_conn, - DrmHwcBuffer *writeback_buffer) { - int ret = 0; - if (writeback_conn->writeback_fb_id().id() == 0 || - writeback_conn->writeback_out_fence().id() == 0) { - ALOGE("Writeback properties don't exit"); - return -EINVAL; - } - if ((*writeback_buffer)->fb_id == 0) { - ALOGE("Invalid writeback buffer"); - return -EINVAL; - } - ret = drmModeAtomicAddProperty(pset, writeback_conn->id(), - writeback_conn->writeback_fb_id().id(), - (*writeback_buffer)->fb_id); - if (ret < 0) { - ALOGE("Failed to add writeback_fb_id"); - return ret; - } - ret = drmModeAtomicAddProperty(pset, writeback_conn->id(), - writeback_conn->writeback_out_fence().id(), - (uint64_t)&writeback_fence_); - if (ret < 0) { - ALOGE("Failed to add writeback_out_fence"); - return ret; - } - - ret = drmModeAtomicAddProperty(pset, writeback_conn->id(), - writeback_conn->crtc_id_property().id(), - crtc_id); - if (ret < 0) { - ALOGE("Failed to attach writeback"); - return ret; - } - return 0; -} - int DrmDisplayCompositor::CommitFrame(DrmDisplayComposition *display_comp, - bool test_only, - DrmConnector *writeback_conn, - DrmHwcBuffer *writeback_buffer) { + bool test_only) { ATRACE_CALL(); int ret = 0; @@ -286,18 +242,6 @@ int DrmDisplayCompositor::CommitFrame(DrmDisplayComposition *display_comp, return -ENOMEM; } - if (writeback_buffer != nullptr) { - if (writeback_conn == nullptr) { - ALOGE("Invalid arguments requested writeback without writeback conn"); - return -EINVAL; - } - ret = SetupWritebackCommit(pset, crtc->id(), writeback_conn, - writeback_buffer); - if (ret < 0) { - ALOGE("Failed to Setup Writeback Commit ret = %d", ret); - return ret; - } - } if (crtc->out_fence_ptr_property().id() != 0) { ret = drmModeAtomicAddProperty(pset, crtc->id(), crtc->out_fence_ptr_property().id(), @@ -661,22 +605,16 @@ void DrmDisplayCompositor::ClearDisplay() { return; active_composition_.reset(nullptr); - vsync_worker_.VSyncControl(false); } void DrmDisplayCompositor::ApplyFrame( - std::unique_ptr<DrmDisplayComposition> composition, int status, - bool writeback) { + std::unique_ptr<DrmDisplayComposition> composition, int status) { AutoLock lock(&lock_, __func__); if (lock.Lock()) return; int ret = status; if (!ret) { - if (writeback && !CountdownExpired()) { - ALOGE("Abort playing back scene"); - return; - } ret = CommitFrame(composition.get(), false); } @@ -697,7 +635,7 @@ void DrmDisplayCompositor::ApplyFrame( } else { SetFlattening(FlatteningState::kClientDone); } - vsync_worker_.VSyncControl(!writeback); + vsync_worker_.VSyncControl(true); } int DrmDisplayCompositor::ApplyComposition( @@ -747,118 +685,10 @@ int DrmDisplayCompositor::TestComposition(DrmDisplayComposition *composition) { return CommitFrame(composition, true); } -// Flatten a scene on the display by using a writeback connector -// and returns the composition result as a DrmHwcLayer. -int DrmDisplayCompositor::FlattenOnDisplay( - std::unique_ptr<DrmDisplayComposition> &src, DrmConnector *writeback_conn, - DrmMode &src_mode, DrmHwcLayer *writeback_layer) { - int ret = 0; - DrmDevice *drm = resource_manager_->GetDrmDevice(display_); - ret = writeback_conn->UpdateModes(); - if (ret) { - ALOGE("Failed to update modes %d", ret); - return ret; - } - for (const DrmMode &mode : writeback_conn->modes()) { - if (mode.h_display() == src_mode.h_display() && - mode.v_display() == src_mode.v_display()) { - mode_.mode = mode; - if (mode_.blob_id) - drm->DestroyPropertyBlob(mode_.blob_id); - std::tie(ret, mode_.blob_id) = CreateModeBlob(mode_.mode); - if (ret) { - ALOGE("Failed to create mode blob for display %d", display_); - return ret; - } - mode_.needs_modeset = true; - break; - } - } - if (mode_.blob_id <= 0) { - ALOGE("Failed to find similar mode"); - return -EINVAL; - } - - DrmCrtc *crtc = drm->GetCrtcForDisplay(display_); - if (!crtc) { - ALOGE("Failed to find crtc for display %d", display_); - return -EINVAL; - } - // TODO(nobody) what happens if planes could go to both CRTCs, I don't think - // it's handled anywhere - std::vector<DrmPlane *> primary_planes; - std::vector<DrmPlane *> overlay_planes; - for (auto &plane : drm->planes()) { - if (!plane->GetCrtcSupported(*crtc)) - continue; - if (plane->type() == DRM_PLANE_TYPE_PRIMARY) - primary_planes.push_back(plane.get()); - else if (plane->type() == DRM_PLANE_TYPE_OVERLAY) - overlay_planes.push_back(plane.get()); - } - - ret = src->Plan(&primary_planes, &overlay_planes); - if (ret) { - ALOGE("Failed to plan the composition ret = %d", ret); - return ret; - } - - // Disable the planes we're not using - for (auto i = primary_planes.begin(); i != primary_planes.end();) { - src->AddPlaneDisable(*i); - i = primary_planes.erase(i); - } - for (auto i = overlay_planes.begin(); i != overlay_planes.end();) { - src->AddPlaneDisable(*i); - i = overlay_planes.erase(i); - } - - AutoLock lock(&lock_, __func__); - ret = lock.Lock(); - if (ret) - return ret; - DrmFramebuffer *writeback_fb = &framebuffers_[framebuffer_index_]; - framebuffer_index_ = (framebuffer_index_ + 1) % DRM_DISPLAY_BUFFERS; - if (!writeback_fb->Allocate(mode_.mode.h_display(), mode_.mode.v_display())) { - ALOGE("Failed to allocate writeback buffer"); - return -ENOMEM; - } - DrmHwcBuffer *writeback_buffer = &writeback_layer->buffer; - writeback_layer->sf_handle = writeback_fb->buffer()->handle; - ret = writeback_layer->ImportBuffer( - resource_manager_->GetImporter(display_).get()); - if (ret) { - ALOGE("Failed to import writeback buffer"); - return ret; - } - - ret = CommitFrame(src.get(), true, writeback_conn, writeback_buffer); - if (ret) { - ALOGE("Atomic check failed"); - return ret; - } - ret = CommitFrame(src.get(), false, writeback_conn, writeback_buffer); - if (ret) { - ALOGE("Atomic commit failed"); - return ret; - } - - ret = sync_wait(writeback_fence_, kWaitWritebackFence); - writeback_layer->acquire_fence.Set(writeback_fence_); - writeback_fence_ = -1; - if (ret) { - ALOGE("Failed to wait on writeback fence"); - return ret; - } - return 0; -} - void DrmDisplayCompositor::SetFlattening(FlatteningState new_state) { if (flattening_state_ != new_state) { switch (flattening_state_) { case FlatteningState::kClientDone: - case FlatteningState::kConcurrent: - case FlatteningState::kSerial: ++frames_flattened_; break; case FlatteningState::kClientRequested: @@ -901,214 +731,8 @@ int DrmDisplayCompositor::FlattenOnClient() { return -EINVAL; } -// Flatten a scene by enabling the writeback connector attached -// to the same CRTC as the one driving the display. -int DrmDisplayCompositor::FlattenSerial(DrmConnector *writeback_conn) { - ALOGV("FlattenSerial by enabling writeback connector to the same crtc"); - // Flattened composition with only one layer that is obtained - // using the writeback connector - std::unique_ptr<DrmDisplayComposition> - writeback_comp = CreateInitializedComposition(); - if (!writeback_comp) - return -EINVAL; - - AutoLock lock(&lock_, __func__); - int ret = lock.Lock(); - if (ret) - return ret; - if (!IsFlatteningNeeded()) { - ALOGV("Flattening is not needed"); - SetFlattening(FlatteningState::kNotNeeded); - return -EALREADY; - } - - DrmFramebuffer *writeback_fb = &framebuffers_[framebuffer_index_]; - framebuffer_index_ = (framebuffer_index_ + 1) % DRM_DISPLAY_BUFFERS; - lock.Unlock(); - - if (!writeback_fb->Allocate(mode_.mode.h_display(), mode_.mode.v_display())) { - ALOGE("Failed to allocate writeback buffer"); - return -ENOMEM; - } - writeback_comp->layers().emplace_back(); - - DrmHwcLayer &writeback_layer = writeback_comp->layers().back(); - writeback_layer.sf_handle = writeback_fb->buffer()->handle; - writeback_layer.source_crop = {0, 0, (float)mode_.mode.h_display(), - (float)mode_.mode.v_display()}; - writeback_layer.display_frame = {0, 0, (int)mode_.mode.h_display(), - (int)mode_.mode.v_display()}; - ret = writeback_layer.ImportBuffer( - resource_manager_->GetImporter(display_).get()); - if (ret || writeback_comp->layers().size() != 1) { - ALOGE("Failed to import writeback buffer"); - return ret; - } - - drmModeAtomicReqPtr pset = drmModeAtomicAlloc(); - if (!pset) { - ALOGE("Failed to allocate property set"); - return -ENOMEM; - } - DrmDevice *drm = resource_manager_->GetDrmDevice(display_); - DrmCrtc *crtc = drm->GetCrtcForDisplay(display_); - if (!crtc) { - ALOGE("Failed to find crtc for display %d", display_); - return -EINVAL; - } - ret = SetupWritebackCommit(pset, crtc->id(), writeback_conn, - &writeback_layer.buffer); - if (ret < 0) { - ALOGE("Failed to Setup Writeback Commit"); - return ret; - } - ret = drmModeAtomicCommit(drm->fd(), pset, 0, drm); - if (ret) { - ALOGE("Failed to enable writeback %d", ret); - return ret; - } - ret = sync_wait(writeback_fence_, kWaitWritebackFence); - writeback_layer.acquire_fence.Set(writeback_fence_); - writeback_fence_ = -1; - if (ret) { - ALOGE("Failed to wait on writeback fence"); - return ret; - } - - DrmCompositionPlane squashed_comp(DrmCompositionPlane::Type::kLayer, nullptr, - crtc); - for (auto &drmplane : drm->planes()) { - if (!drmplane->GetCrtcSupported(*crtc)) - continue; - if (!squashed_comp.plane() && drmplane->type() == DRM_PLANE_TYPE_PRIMARY) - squashed_comp.set_plane(drmplane.get()); - else - writeback_comp->AddPlaneDisable(drmplane.get()); - } - squashed_comp.source_layers().push_back(0); - ret = writeback_comp->AddPlaneComposition(std::move(squashed_comp)); - if (ret) { - ALOGE("Failed to add flatten scene"); - return ret; - } - - ApplyFrame(std::move(writeback_comp), 0, true); - return 0; -} - -// Flatten a scene by using a crtc which works concurrent with -// the one driving the display. -int DrmDisplayCompositor::FlattenConcurrent(DrmConnector *writeback_conn) { - ALOGV("FlattenConcurrent by using an unused crtc/display"); - int ret = 0; - DrmDisplayCompositor drmdisplaycompositor; - ret = drmdisplaycompositor.Init(resource_manager_, writeback_conn->display()); - if (ret) { - ALOGE("Failed to init drmdisplaycompositor = %d", ret); - return ret; - } - // Copy of the active_composition, needed because of two things: - // 1) Not to hold the lock for the whole time we are accessing - // active_composition - // 2) It will be committed on a crtc that might not be on the same - // dri node, so buffers need to be imported on the right node. - std::unique_ptr<DrmDisplayComposition> - copy_comp = drmdisplaycompositor.CreateInitializedComposition(); - - // Writeback composition that will be committed to the display. - std::unique_ptr<DrmDisplayComposition> - writeback_comp = CreateInitializedComposition(); - - if (!copy_comp || !writeback_comp) - return -EINVAL; - AutoLock lock(&lock_, __func__); - ret = lock.Lock(); - if (ret) - return ret; - if (!IsFlatteningNeeded()) { - ALOGV("Flattening is not needed"); - SetFlattening(FlatteningState::kNotNeeded); - return -EALREADY; - } - DrmCrtc *crtc = active_composition_->crtc(); - - std::vector<DrmHwcLayer> copy_layers; - for (DrmHwcLayer &src_layer : active_composition_->layers()) { - DrmHwcLayer copy; - ret = copy.InitFromDrmHwcLayer(&src_layer, - resource_manager_ - ->GetImporter(writeback_conn->display()) - .get()); - if (ret) { - ALOGE("Failed to import buffer ret = %d", ret); - return -EINVAL; - } - copy_layers.emplace_back(std::move(copy)); - } - ret = copy_comp->SetLayers(copy_layers.data(), copy_layers.size(), true); - if (ret) { - ALOGE("Failed to set copy_comp layers"); - return ret; - } - - lock.Unlock(); - DrmHwcLayer writeback_layer; - ret = drmdisplaycompositor.FlattenOnDisplay(copy_comp, writeback_conn, - mode_.mode, &writeback_layer); - if (ret) { - ALOGE("Failed to flatten on display ret = %d", ret); - return ret; - } - - DrmCompositionPlane squashed_comp(DrmCompositionPlane::Type::kLayer, nullptr, - crtc); - for (auto &drmplane : resource_manager_->GetDrmDevice(display_)->planes()) { - if (!drmplane->GetCrtcSupported(*crtc)) - continue; - if (drmplane->type() == DRM_PLANE_TYPE_PRIMARY) - squashed_comp.set_plane(drmplane.get()); - else - writeback_comp->AddPlaneDisable(drmplane.get()); - } - writeback_comp->layers().emplace_back(); - DrmHwcLayer &next_layer = writeback_comp->layers().back(); - next_layer.sf_handle = writeback_layer.get_usable_handle(); - next_layer.blending = DrmHwcBlending::kPreMult; - next_layer.source_crop = {0, 0, (float)mode_.mode.h_display(), - (float)mode_.mode.v_display()}; - next_layer.display_frame = {0, 0, (int)mode_.mode.h_display(), - (int)mode_.mode.v_display()}; - ret = next_layer.ImportBuffer(resource_manager_->GetImporter(display_).get()); - if (ret) { - ALOGE("Failed to import framebuffer for display %d", ret); - return ret; - } - squashed_comp.source_layers().push_back(0); - ret = writeback_comp->AddPlaneComposition(std::move(squashed_comp)); - if (ret) { - ALOGE("Failed to add plane composition %d", ret); - return ret; - } - ApplyFrame(std::move(writeback_comp), 0, true); - return ret; -} - int DrmDisplayCompositor::FlattenActiveComposition() { - DrmConnector *writeback_conn = resource_manager_->AvailableWritebackConnector( - display_); - if (!active_composition_ || !writeback_conn) { - // Try to fallback to GPU composition on client, since it is more - // power-efficient than composition on device side - return FlattenOnClient(); - } - - if (writeback_conn->display() != display_) { - SetFlattening(FlatteningState::kConcurrent); - return FlattenConcurrent(writeback_conn); - } - - SetFlattening(FlatteningState::kSerial); - return FlattenSerial(writeback_conn); + return FlattenOnClient(); } bool DrmDisplayCompositor::CountdownExpired() const { |