| /* |
| * Copyright 2022 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include "ClientFrameComposer.h" |
| |
| #include <android-base/parseint.h> |
| #include <android-base/properties.h> |
| #include <android-base/strings.h> |
| #include <android/hardware/graphics/common/1.0/types.h> |
| #include <device_config_shared.h> |
| #include <drm_fourcc.h> |
| #include <libyuv.h> |
| #include <sync/sync.h> |
| #include <ui/GraphicBuffer.h> |
| #include <ui/GraphicBufferAllocator.h> |
| #include <ui/GraphicBufferMapper.h> |
| |
| #include "Display.h" |
| #include "Drm.h" |
| #include "Layer.h" |
| |
| namespace aidl::android::hardware::graphics::composer3::impl { |
| |
| HWC3::Error ClientFrameComposer::init() { |
| DEBUG_LOG("%s", __FUNCTION__); |
| |
| HWC3::Error error = mDrmClient.init(); |
| if (error != HWC3::Error::None) { |
| ALOGE("%s: failed to initialize DrmClient", __FUNCTION__); |
| return error; |
| } |
| |
| return HWC3::Error::None; |
| } |
| |
| HWC3::Error ClientFrameComposer::registerOnHotplugCallback( |
| const HotplugCallback& cb) { |
| return mDrmClient.registerOnHotplugCallback(cb); |
| return HWC3::Error::None; |
| } |
| |
| HWC3::Error ClientFrameComposer::unregisterOnHotplugCallback() { |
| return mDrmClient.unregisterOnHotplugCallback(); |
| } |
| |
| HWC3::Error ClientFrameComposer::onDisplayCreate(Display* display) { |
| const auto displayId = display->getId(); |
| DEBUG_LOG("%s display:%" PRIu64, __FUNCTION__, displayId); |
| |
| // Ensure created. |
| mDisplayInfos.emplace(displayId, DisplayInfo{}); |
| |
| return HWC3::Error::None; |
| } |
| |
| HWC3::Error ClientFrameComposer::onDisplayDestroy(Display* display) { |
| const auto displayId = display->getId(); |
| DEBUG_LOG("%s display:%" PRIu64, __FUNCTION__, displayId); |
| |
| auto it = mDisplayInfos.find(displayId); |
| if (it == mDisplayInfos.end()) { |
| ALOGE("%s: display:%" PRIu64 " missing display buffers?", __FUNCTION__, |
| displayId); |
| return HWC3::Error::BadDisplay; |
| } |
| |
| mDisplayInfos.erase(it); |
| |
| return HWC3::Error::None; |
| } |
| |
| HWC3::Error ClientFrameComposer::onDisplayClientTargetSet(Display* display) { |
| const auto displayId = display->getId(); |
| DEBUG_LOG("%s display:%" PRIu64, __FUNCTION__, displayId); |
| |
| auto it = mDisplayInfos.find(displayId); |
| if (it == mDisplayInfos.end()) { |
| ALOGE("%s: display:%" PRIu64 " missing display buffers?", __FUNCTION__, |
| displayId); |
| return HWC3::Error::BadDisplay; |
| } |
| |
| DisplayInfo& displayInfo = it->second; |
| |
| auto [drmBufferCreateError, drmBuffer] = |
| mDrmClient.create(display->getClientTarget().getBuffer()); |
| if (drmBufferCreateError != HWC3::Error::None) { |
| ALOGE("%s: display:%" PRIu64 " failed to create client target drm buffer", |
| __FUNCTION__, displayId); |
| return HWC3::Error::NoResources; |
| } |
| displayInfo.clientTargetDrmBuffer = std::move(drmBuffer); |
| |
| return HWC3::Error::None; |
| } |
| |
| HWC3::Error ClientFrameComposer::onActiveConfigChange(Display* /*display*/) { |
| return HWC3::Error::None; |
| }; |
| |
| HWC3::Error ClientFrameComposer::validateDisplay(Display* display, |
| DisplayChanges* outChanges) { |
| const auto displayId = display->getId(); |
| DEBUG_LOG("%s display:%" PRIu64, __FUNCTION__, displayId); |
| |
| const std::vector<Layer*>& layers = display->getOrderedLayers(); |
| |
| for (Layer* layer : layers) { |
| const auto layerId = layer->getId(); |
| const auto layerCompositionType = layer->getCompositionType(); |
| |
| if (layerCompositionType != Composition::CLIENT) { |
| outChanges->addLayerCompositionChange(displayId, layerId, Composition::CLIENT); |
| continue; |
| } |
| } |
| |
| return HWC3::Error::None; |
| } |
| |
| HWC3::Error ClientFrameComposer::presentDisplay( |
| Display* display, ::android::base::unique_fd* outDisplayFence, |
| std::unordered_map<int64_t, |
| ::android::base::unique_fd>* /*outLayerFences*/) { |
| const auto displayId = display->getId(); |
| DEBUG_LOG("%s display:%" PRIu64, __FUNCTION__, displayId); |
| |
| auto displayInfoIt = mDisplayInfos.find(displayId); |
| if (displayInfoIt == mDisplayInfos.end()) { |
| ALOGE("%s: failed to find display buffers for display:%" PRIu64, |
| __FUNCTION__, displayId); |
| return HWC3::Error::BadDisplay; |
| } |
| |
| DisplayInfo& displayInfo = displayInfoIt->second; |
| if (!displayInfo.clientTargetDrmBuffer) { |
| ALOGW("%s: display:%" PRIu64 " no client target set, nothing to present.", |
| __FUNCTION__, displayId); |
| return HWC3::Error::None; |
| } |
| |
| ::android::base::unique_fd fence = display->getClientTarget().getFence(); |
| |
| auto [flushError, flushCompleteFence] = mDrmClient.flushToDisplay( |
| displayId, displayInfo.clientTargetDrmBuffer, fence); |
| if (flushError != HWC3::Error::None) { |
| ALOGE("%s: display:%" PRIu64 " failed to flush drm buffer" PRIu64, |
| __FUNCTION__, displayId); |
| } |
| |
| *outDisplayFence = std::move(flushCompleteFence); |
| return flushError; |
| } |
| |
| } // namespace aidl::android::hardware::graphics::composer3::impl |