/* * Copyright 2021, 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 "HalImpl.h" #include #include #include #include "ExynosDevice.h" #include "ExynosDeviceModule.h" #include "ExynosDisplay.h" #include "ExynosHWCService.h" #include "ExynosLayer.h" #include "TranslateHwcAidl.h" #include "Util.h" using namespace SOC_VERSION; namespace { static constexpr int32_t kMinComposerInterfaceVersionForVrrApi = 3; }; namespace aidl::android::hardware::graphics::composer3::impl { std::unique_ptr IComposerHal::create(int32_t composerInterfaceVersion) { bool vrrApiSupported = composerInterfaceVersion >= kMinComposerInterfaceVersionForVrrApi; auto device = std::make_unique(vrrApiSupported); if (!device) { return nullptr; } return std::make_unique(std::move(device)); } namespace hook { void hotplug(hwc2_callback_data_t callbackData, hwc2_display_t hwcDisplay, int32_t connected) { auto hal = static_cast(callbackData); int64_t display; h2a::translate(hwcDisplay, display); hal->getEventCallback()->onHotplug(display, connected == HWC2_CONNECTION_CONNECTED); } void refresh(hwc2_callback_data_t callbackData, hwc2_display_t hwcDisplay) { auto hal = static_cast(callbackData); int64_t display; h2a::translate(hwcDisplay, display); hal->getEventCallback()->onRefresh(display); } void vsync(hwc2_callback_data_t callbackData, hwc2_display_t hwcDisplay, int64_t timestamp, hwc2_vsync_period_t hwcVsyncPeriodNanos) { auto hal = static_cast(callbackData); int64_t display; int32_t vsyncPeriodNanos; h2a::translate(hwcDisplay, display); h2a::translate(hwcVsyncPeriodNanos, vsyncPeriodNanos); hal->getEventCallback()->onVsync(display, timestamp, vsyncPeriodNanos); } void vsyncPeriodTimingChanged(hwc2_callback_data_t callbackData, hwc2_display_t hwcDisplay, hwc_vsync_period_change_timeline_t* hwcTimeline) { auto hal = static_cast(callbackData); int64_t display; VsyncPeriodChangeTimeline timeline; h2a::translate(hwcDisplay, display); h2a::translate(*hwcTimeline, timeline); hal->getEventCallback()->onVsyncPeriodTimingChanged(display, timeline); } void vsyncIdle(hwc2_callback_data_t callbackData, hwc2_display_t hwcDisplay) { auto hal = static_cast(callbackData); int64_t display; h2a::translate(hwcDisplay, display); hal->getEventCallback()->onVsyncIdle(display); } void seamlessPossible(hwc2_callback_data_t callbackData, hwc2_display_t hwcDisplay) { auto hal = static_cast(callbackData); int64_t display; h2a::translate(hwcDisplay, display); hal->getEventCallback()->onSeamlessPossible(display); } void refreshRateChangedDebug(hwc2_callback_data_t callbackData, hwc2_display_t hwcDisplay, hwc2_vsync_period_t hwcVsyncPeriodNanos) { auto hal = static_cast(callbackData); int64_t display; int32_t vsyncPeriodNanos; h2a::translate(hwcDisplay, display); h2a::translate(hwcVsyncPeriodNanos, vsyncPeriodNanos); // TODO (b/314527560) Update refreshPeriodNanos for VRR display hal->getEventCallback()->onRefreshRateChangedDebug(RefreshRateChangedDebugData{ .display = display, .vsyncPeriodNanos = vsyncPeriodNanos, .refreshPeriodNanos = vsyncPeriodNanos, }); } } // nampesapce hook HalImpl::HalImpl(std::unique_ptr device) : mDevice(std::move(device)) { initCaps(); #ifdef USES_HWC_SERVICES LOG(DEBUG) << "Start HWCService"; mHwcCtx = std::make_unique(); memset(&mHwcCtx->base, 0, sizeof(mHwcCtx->base)); mHwcCtx->device = mDevice.get(); auto hwcService = ::android::ExynosHWCService::getExynosHWCService(); hwcService->setExynosHWCCtx(mHwcCtx.get()); // This callback is for DP hotplug event if connected // hwcService->setBootFinishedCallback(...); #endif } void HalImpl::initCaps() { uint32_t count = 0; mDevice->getCapabilities(&count, nullptr); std::vector halCaps(count); mDevice->getCapabilities(&count, halCaps.data()); for (auto hwcCap : halCaps) { Capability cap; h2a::translate(hwcCap, cap); mCaps.insert(cap); } mCaps.insert(Capability::BOOT_DISPLAY_CONFIG); mCaps.insert(Capability::REFRESH_RATE_CHANGED_CALLBACK_DEBUG); } int32_t HalImpl::getHalDisplay(int64_t display, ExynosDisplay*& halDisplay) { hwc2_display_t hwcDisplay; a2h::translate(display, hwcDisplay); halDisplay = mDevice->getDisplay(static_cast(hwcDisplay)); if (!halDisplay) { [[unlikely]] return HWC2_ERROR_BAD_DISPLAY; } return HWC2_ERROR_NONE; } int32_t HalImpl::getHalLayer(int64_t display, int64_t layer, ExynosLayer*& halLayer) { ExynosDisplay* halDisplay; RET_IF_ERR(getHalDisplay(display, halDisplay)); hwc2_layer_t hwcLayer; a2h::translate(layer, hwcLayer); halLayer = halDisplay->checkLayer(hwcLayer); if (!halLayer) { [[unlikely]] return HWC2_ERROR_BAD_LAYER; } return HWC2_ERROR_NONE; } bool HalImpl::hasCapability(Capability cap) { return mCaps.find(cap) != mCaps.end(); } void HalImpl::getCapabilities(std::vector* caps) { caps->clear(); caps->insert(caps->begin(), mCaps.begin(), mCaps.end()); } void HalImpl::dumpDebugInfo(std::string* output) { if (output == nullptr) return; String8 result; mDevice->dump(result); output->resize(result.size()); output->assign(result.c_str()); } void HalImpl::registerEventCallback(EventCallback* callback) { mEventCallback = callback; mDevice->registerCallback(HWC2_CALLBACK_HOTPLUG, this, reinterpret_cast(hook::hotplug)); mDevice->registerCallback(HWC2_CALLBACK_REFRESH, this, reinterpret_cast(hook::refresh)); mDevice->registerCallback(HWC2_CALLBACK_VSYNC_2_4, this, reinterpret_cast(hook::vsync)); mDevice->registerCallback(HWC2_CALLBACK_VSYNC_PERIOD_TIMING_CHANGED, this, reinterpret_cast(hook::vsyncPeriodTimingChanged)); mDevice->registerCallback(HWC2_CALLBACK_SEAMLESS_POSSIBLE, this, reinterpret_cast(hook::seamlessPossible)); // register HWC3 Callback mDevice->registerHwc3Callback(IComposerCallback::TRANSACTION_onVsyncIdle, this, reinterpret_cast(hook::vsyncIdle)); mDevice->registerHwc3Callback(IComposerCallback::TRANSACTION_onRefreshRateChangedDebug, this, reinterpret_cast( hook::refreshRateChangedDebug)); } void HalImpl::unregisterEventCallback() { mDevice->registerCallback(HWC2_CALLBACK_HOTPLUG, this, nullptr); mDevice->registerCallback(HWC2_CALLBACK_REFRESH, this, nullptr); mDevice->registerCallback(HWC2_CALLBACK_VSYNC_2_4, this, nullptr); mDevice->registerCallback(HWC2_CALLBACK_VSYNC_PERIOD_TIMING_CHANGED, this, nullptr); mDevice->registerCallback(HWC2_CALLBACK_SEAMLESS_POSSIBLE, this, nullptr); // unregister HWC3 Callback mDevice->registerHwc3Callback(IComposerCallback::TRANSACTION_onVsyncIdle, this, nullptr); mDevice->registerHwc3Callback(IComposerCallback::TRANSACTION_onRefreshRateChangedDebug, this, nullptr); mEventCallback = nullptr; } int32_t HalImpl::acceptDisplayChanges(int64_t display) { ExynosDisplay* halDisplay; RET_IF_ERR(getHalDisplay(display, halDisplay)); return halDisplay->acceptDisplayChanges(); } int32_t HalImpl::createLayer(int64_t display, int64_t* outLayer) { ExynosDisplay* halDisplay; RET_IF_ERR(getHalDisplay(display, halDisplay)); hwc2_layer_t hwcLayer = 0; RET_IF_ERR(halDisplay->createLayer(&hwcLayer)); h2a::translate(hwcLayer, *outLayer); return HWC2_ERROR_NONE; } int32_t HalImpl::destroyLayer(int64_t display, int64_t layer) { ExynosDisplay* halDisplay; RET_IF_ERR(getHalDisplay(display, halDisplay)); ExynosLayer *halLayer; RET_IF_ERR(getHalLayer(display, layer, halLayer)); return halDisplay->destroyLayer(reinterpret_cast(halLayer)); } int32_t HalImpl::createVirtualDisplay(uint32_t width, uint32_t height, AidlPixelFormat format, VirtualDisplay* outDisplay) { int32_t hwcFormat; a2h::translate(format, hwcFormat); hwc2_display_t hwcDisplay = getDisplayId(HWC_DISPLAY_VIRTUAL, 0); auto halDisplay = mDevice->getDisplay(static_cast(hwcDisplay)); if (!halDisplay) { return HWC2_ERROR_BAD_PARAMETER; } RET_IF_ERR(mDevice->createVirtualDisplay(width, height, &hwcFormat, halDisplay)); h2a::translate(hwcDisplay, outDisplay->display); h2a::translate(hwcFormat, outDisplay->format); return HWC2_ERROR_NONE; } int32_t HalImpl::destroyVirtualDisplay(int64_t display) { ExynosDisplay* halDisplay; RET_IF_ERR(getHalDisplay(display, halDisplay)); return mDevice->destroyVirtualDisplay(halDisplay); } int32_t HalImpl::getActiveConfig(int64_t display, int32_t* outConfig) { ExynosDisplay* halDisplay; RET_IF_ERR(getHalDisplay(display, halDisplay)); hwc2_config_t hwcConfig; RET_IF_ERR(halDisplay->getActiveConfig(&hwcConfig)); h2a::translate(hwcConfig, *outConfig); return HWC2_ERROR_NONE; } int32_t HalImpl::getColorModes(int64_t display, std::vector* outModes) { ExynosDisplay* halDisplay; RET_IF_ERR(getHalDisplay(display, halDisplay)); uint32_t count = 0; RET_IF_ERR(halDisplay->getColorModes(&count, nullptr)); std::vector hwcModes(count); RET_IF_ERR(halDisplay->getColorModes(&count, hwcModes.data())); h2a::translate(hwcModes, *outModes); return HWC2_ERROR_NONE; } int32_t HalImpl::getDataspaceSaturationMatrix([[maybe_unused]] common::Dataspace dataspace, std::vector* matrix) { // Pixel HWC does not support dataspace saturation matrix, return unit matrix. std::vector unitMatrix = { 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, }; *matrix = std::move(unitMatrix); return HWC2_ERROR_NONE; } int32_t HalImpl::getDisplayAttribute(int64_t display, int32_t config, DisplayAttribute attribute, int32_t* outValue) { ExynosDisplay* halDisplay; RET_IF_ERR(getHalDisplay(display, halDisplay)); hwc2_config_t hwcConfig; int32_t hwcAttr; a2h::translate(config, hwcConfig); a2h::translate(attribute, hwcAttr); auto err = halDisplay->getDisplayAttribute(hwcConfig, hwcAttr, outValue); if (err != HWC2_ERROR_NONE && *outValue == -1) { return HWC2_ERROR_BAD_PARAMETER; } return HWC2_ERROR_NONE; } int32_t HalImpl::getDisplayBrightnessSupport(int64_t display, bool& outSupport) { ExynosDisplay* halDisplay; RET_IF_ERR(getHalDisplay(display, halDisplay)); return halDisplay->getDisplayBrightnessSupport(&outSupport); } int32_t HalImpl::getDisplayCapabilities(int64_t display, std::vector* caps) { ExynosDisplay* halDisplay; RET_IF_ERR(getHalDisplay(display, halDisplay)); uint32_t count = 0; RET_IF_ERR(halDisplay->getDisplayCapabilities(&count, nullptr)); std::vector hwcCaps(count); RET_IF_ERR(halDisplay->getDisplayCapabilities(&count, hwcCaps.data())); h2a::translate(hwcCaps, *caps); return HWC2_ERROR_NONE; } int32_t HalImpl::getDisplayConfigs(int64_t display, std::vector* configs) { ExynosDisplay* halDisplay; RET_IF_ERR(getHalDisplay(display, halDisplay)); uint32_t count = 0; RET_IF_ERR(halDisplay->getDisplayConfigs(&count, nullptr)); std::vector hwcConfigs(count); RET_IF_ERR(halDisplay->getDisplayConfigs(&count, hwcConfigs.data())); h2a::translate(hwcConfigs, *configs); return HWC2_ERROR_NONE; } int32_t HalImpl::getDisplayConfigurations(int64_t display, int32_t, std::vector* outConfigs) { ExynosDisplay* halDisplay; RET_IF_ERR(getHalDisplay(display, halDisplay)); std::vector configIds; RET_IF_ERR(getDisplayConfigs(display, &configIds)); for (const auto configId : configIds) { DisplayConfiguration config; config.configId = configId; // Get required display attributes RET_IF_ERR(getDisplayAttribute(display, configId, DisplayAttribute::WIDTH, &config.width)); RET_IF_ERR( getDisplayAttribute(display, configId, DisplayAttribute::HEIGHT, &config.height)); RET_IF_ERR(getDisplayAttribute(display, configId, DisplayAttribute::VSYNC_PERIOD, &config.vsyncPeriod)); RET_IF_ERR(getDisplayAttribute(display, configId, DisplayAttribute::CONFIG_GROUP, &config.configGroup)); // Get optional display attributes int32_t dpiX, dpiY; auto statusDpiX = getDisplayAttribute(display, configId, DisplayAttribute::DPI_X, &dpiX); auto statusDpiY = getDisplayAttribute(display, configId, DisplayAttribute::DPI_Y, &dpiY); // TODO(b/294120341): getDisplayAttribute for DPI should return dots per inch if (statusDpiX == HWC2_ERROR_NONE && statusDpiY == HWC2_ERROR_NONE) { config.dpi = {dpiX / 1000.0f, dpiY / 1000.0f}; } // Determine whether there is a need to configure VRR. hwc2_config_t hwcConfigId; a2h::translate(configId, hwcConfigId); std::optional vrrConfig = halDisplay->getVrrConfigs(hwcConfigId); if (vrrConfig.has_value()) { // TODO(b/290843234): complete the remaining values within vrrConfig. VrrConfig hwc3VrrConfig; VrrConfig::NotifyExpectedPresentConfig notifyExpectedPresentConfig; hwc3VrrConfig.minFrameIntervalNs = vrrConfig->minFrameIntervalNs; notifyExpectedPresentConfig.notifyExpectedPresentHeadsUpNs = vrrConfig->notifyExpectedPresentConfig.HeadsUpNs; notifyExpectedPresentConfig.notifyExpectedPresentTimeoutNs = vrrConfig->notifyExpectedPresentConfig.TimeoutNs; hwc3VrrConfig.notifyExpectedPresentConfig = std::make_optional(notifyExpectedPresentConfig); config.vrrConfig = std::make_optional(hwc3VrrConfig); } outConfigs->push_back(config); } return HWC2_ERROR_NONE; } int32_t HalImpl::notifyExpectedPresent(int64_t, const ClockMonotonicTimestamp&, int32_t) { return HWC2_ERROR_UNSUPPORTED; } int32_t HalImpl::getDisplayConnectionType(int64_t display, DisplayConnectionType* outType) { ExynosDisplay* halDisplay; RET_IF_ERR(getHalDisplay(display, halDisplay)); uint32_t hwcType = HWC2_DISPLAY_CONNECTION_TYPE_INTERNAL; RET_IF_ERR(halDisplay->getDisplayConnectionType(&hwcType)); h2a::translate(hwcType, *outType); return HWC2_ERROR_NONE; } int32_t HalImpl::getDisplayIdentificationData(int64_t display, DisplayIdentification *id) { ExynosDisplay* halDisplay; RET_IF_ERR(getHalDisplay(display, halDisplay)); uint8_t port; uint32_t count = 0; RET_IF_ERR(halDisplay->getDisplayIdentificationData(&port, &count, nullptr)); id->data.resize(count); RET_IF_ERR(halDisplay->getDisplayIdentificationData(&port, &count, id->data.data())); h2a::translate(port, id->port); return HWC2_ERROR_NONE; } int32_t HalImpl::getDisplayName(int64_t display, std::string* outName) { ExynosDisplay* halDisplay; RET_IF_ERR(getHalDisplay(display, halDisplay)); uint32_t count = 0; RET_IF_ERR(halDisplay->getDisplayName(&count, nullptr)); outName->resize(count); RET_IF_ERR(halDisplay->getDisplayName(&count, outName->data())); return HWC2_ERROR_NONE; } int32_t HalImpl::getDisplayVsyncPeriod(int64_t display, int32_t* outVsyncPeriod) { ExynosDisplay* halDisplay; RET_IF_ERR(getHalDisplay(display, halDisplay)); hwc2_vsync_period_t hwcVsyncPeriod; RET_IF_ERR(halDisplay->getDisplayVsyncPeriod(&hwcVsyncPeriod)); h2a::translate(hwcVsyncPeriod, *outVsyncPeriod); return HWC2_ERROR_NONE; } int32_t HalImpl::getDisplayedContentSample([[maybe_unused]] int64_t display, [[maybe_unused]] int64_t maxFrames, [[maybe_unused]] int64_t timestamp, [[maybe_unused]] DisplayContentSample* samples) { return HWC2_ERROR_UNSUPPORTED; } int32_t HalImpl::getDisplayedContentSamplingAttributes( [[maybe_unused]] int64_t display, [[maybe_unused]] DisplayContentSamplingAttributes* attrs) { return HWC2_ERROR_UNSUPPORTED; } int32_t HalImpl::getDisplayPhysicalOrientation(int64_t display, common::Transform* orientation) { ExynosDisplay* halDisplay; RET_IF_ERR(getHalDisplay(display, halDisplay)); HwcMountOrientation hwcOrientation; RET_IF_ERR(halDisplay->getMountOrientation(&hwcOrientation)); h2a::translate(hwcOrientation, *orientation); return HWC2_ERROR_NONE; } int32_t HalImpl::getDozeSupport(int64_t display, bool& support) { ExynosDisplay* halDisplay; RET_IF_ERR(getHalDisplay(display, halDisplay)); int32_t hwcSupport; RET_IF_ERR(halDisplay->getDozeSupport(&hwcSupport)); h2a::translate(hwcSupport, support); return HWC2_ERROR_NONE; } int32_t HalImpl::getHdrCapabilities(int64_t display, HdrCapabilities* caps) { ExynosDisplay* halDisplay; RET_IF_ERR(getHalDisplay(display, halDisplay)); uint32_t count = 0; RET_IF_ERR(halDisplay->getHdrCapabilities(&count, nullptr, &caps->maxLuminance, &caps->maxAverageLuminance, &caps->minLuminance)); std::vector hwcHdrTypes(count); RET_IF_ERR(halDisplay->getHdrCapabilities(&count, hwcHdrTypes.data(), &caps->maxLuminance, &caps->maxAverageLuminance, &caps->minLuminance)); h2a::translate(hwcHdrTypes, caps->types); return HWC2_ERROR_NONE; } int32_t HalImpl::getOverlaySupport(OverlayProperties* caps) { return mDevice->getOverlaySupport(caps); } int32_t HalImpl::getMaxVirtualDisplayCount(int32_t* count) { uint32_t hwcCount = mDevice->getMaxVirtualDisplayCount(); h2a::translate(hwcCount, *count); return HWC2_ERROR_NONE; } int32_t HalImpl::getPerFrameMetadataKeys(int64_t display, std::vector* keys) { ExynosDisplay* halDisplay; RET_IF_ERR(getHalDisplay(display, halDisplay)); uint32_t numKeys = 0; auto resManager = mDevice->mResourceManager; if (resManager->hasHDR10PlusMPP()) { numKeys = HWC2_HDR10_PLUS_SEI + 1; } else { numKeys = HWC2_MAX_FRAME_AVERAGE_LIGHT_LEVEL + 1; } for (uint32_t i = 0; i < numKeys; ++i) { PerFrameMetadataKey key; h2a::translate(i, key); keys->push_back(key); } return HWC2_ERROR_NONE; } int32_t HalImpl::getReadbackBufferAttributes(int64_t display, ReadbackBufferAttributes* attrs) { ExynosDisplay* halDisplay; RET_IF_ERR(getHalDisplay(display, halDisplay)); int32_t format = -1; int32_t dataspace = -1; RET_IF_ERR(halDisplay->getReadbackBufferAttributes(&format, &dataspace)); h2a::translate(format, attrs->format); h2a::translate(dataspace, attrs->dataspace); return HWC2_ERROR_NONE; } int32_t HalImpl::getReadbackBufferFence(int64_t display, ndk::ScopedFileDescriptor* acquireFence) { ExynosDisplay* halDisplay; RET_IF_ERR(getHalDisplay(display, halDisplay)); int32_t fd = -1; RET_IF_ERR(halDisplay->getReadbackBufferFence(&fd)); h2a::translate(fd, *acquireFence); return HWC2_ERROR_NONE; } int32_t HalImpl::getRenderIntents(int64_t display, ColorMode mode, std::vector* intents) { ExynosDisplay* halDisplay; RET_IF_ERR(getHalDisplay(display, halDisplay)); int32_t hwcMode; uint32_t count = 0; a2h::translate(mode, hwcMode); RET_IF_ERR(halDisplay->getRenderIntents(hwcMode, &count, nullptr)); std::vector hwcIntents(count); RET_IF_ERR(halDisplay->getRenderIntents(hwcMode, &count, hwcIntents.data())); h2a::translate(hwcIntents, *intents); return HWC2_ERROR_NONE; } int32_t HalImpl::getSupportedContentTypes(int64_t display, std::vector* types) { ExynosDisplay* halDisplay; RET_IF_ERR(getHalDisplay(display, halDisplay)); uint32_t count = 0; RET_IF_ERR(halDisplay->getSupportedContentTypes(&count, nullptr)); std::vector hwcTypes(count); RET_IF_ERR(halDisplay->getSupportedContentTypes(&count, hwcTypes.data())); h2a::translate(hwcTypes, *types); return HWC2_ERROR_NONE; } int32_t HalImpl::flushDisplayBrightnessChange(int64_t display) { ExynosDisplay* halDisplay; RET_IF_ERR(getHalDisplay(display, halDisplay)); return halDisplay->flushDisplayBrightnessChange(); } int32_t HalImpl::presentDisplay(int64_t display, ndk::ScopedFileDescriptor& fence, std::vector* outLayers, std::vector* outReleaseFences) { ExynosDisplay* halDisplay; RET_IF_ERR(getHalDisplay(display, halDisplay)); // TODO: not expect acceptDisplayChanges if there are no changes to accept if (halDisplay->mRenderingState == RENDERING_STATE_VALIDATED) { LOG(INFO) << halDisplay->mDisplayName.c_str() << ": acceptDisplayChanges was not called"; if (halDisplay->acceptDisplayChanges() != HWC2_ERROR_NONE) { LOG(ERROR) << halDisplay->mDisplayName.c_str() << ": acceptDisplayChanges is failed"; } } int32_t hwcFence; RET_IF_ERR(halDisplay->presentDisplay(&hwcFence)); h2a::translate(hwcFence, fence); uint32_t count = 0; RET_IF_ERR(halDisplay->getReleaseFences(&count, nullptr, nullptr)); std::vector hwcLayers(count); std::vector hwcFences(count); RET_IF_ERR(halDisplay->getReleaseFences(&count, hwcLayers.data(), hwcFences.data())); h2a::translate(hwcLayers, *outLayers); h2a::translate(hwcFences, *outReleaseFences); return HWC2_ERROR_NONE; } int32_t HalImpl::setActiveConfig(int64_t display, int32_t config) { ExynosDisplay* halDisplay; RET_IF_ERR(getHalDisplay(display, halDisplay)); hwc2_config_t hwcConfig; a2h::translate(config, hwcConfig); return halDisplay->setActiveConfig(hwcConfig); } int32_t HalImpl::setActiveConfigWithConstraints( int64_t display, int32_t config, const VsyncPeriodChangeConstraints& vsyncPeriodChangeConstraints, VsyncPeriodChangeTimeline* timeline) { ExynosDisplay* halDisplay; RET_IF_ERR(getHalDisplay(display, halDisplay)); hwc2_config_t hwcConfig; hwc_vsync_period_change_constraints_t hwcConstraints; hwc_vsync_period_change_timeline_t hwcTimeline; a2h::translate(config, hwcConfig); a2h::translate(vsyncPeriodChangeConstraints, hwcConstraints); RET_IF_ERR(halDisplay->setActiveConfigWithConstraints(hwcConfig, &hwcConstraints, &hwcTimeline)); h2a::translate(hwcTimeline, *timeline); return HWC2_ERROR_NONE; } int32_t HalImpl::setBootDisplayConfig(int64_t display, int32_t config) { ExynosDisplay* halDisplay; RET_IF_ERR(getHalDisplay(display, halDisplay)); return halDisplay->setBootDisplayConfig(config); } int32_t HalImpl::clearBootDisplayConfig(int64_t display) { ExynosDisplay* halDisplay; RET_IF_ERR(getHalDisplay(display, halDisplay)); return halDisplay->clearBootDisplayConfig(); } int32_t HalImpl::getPreferredBootDisplayConfig(int64_t display, int32_t* config) { ExynosDisplay* halDisplay; RET_IF_ERR(getHalDisplay(display, halDisplay)); return halDisplay->getPreferredBootDisplayConfig(config); } int32_t HalImpl::getHdrConversionCapabilities(std::vector*) { return HWC2_ERROR_UNSUPPORTED; } int32_t HalImpl::setHdrConversionStrategy(const common::HdrConversionStrategy&, common::Hdr*) { return HWC2_ERROR_UNSUPPORTED; } int32_t HalImpl::setAutoLowLatencyMode(int64_t display, bool on) { ExynosDisplay* halDisplay; RET_IF_ERR(getHalDisplay(display, halDisplay)); return halDisplay->setAutoLowLatencyMode(on); } int32_t HalImpl::setClientTarget(int64_t display, buffer_handle_t target, const ndk::ScopedFileDescriptor& fence, common::Dataspace dataspace, const std::vector& damage) { ExynosDisplay* halDisplay; RET_IF_ERR(getHalDisplay(display, halDisplay)); int32_t hwcFence; int32_t hwcDataspace; std::vector hwcDamage; a2h::translate(fence, hwcFence); a2h::translate(dataspace, hwcDataspace); a2h::translate(damage, hwcDamage); hwc_region_t region = { hwcDamage.size(), hwcDamage.data() }; UNUSED(region); return halDisplay->setClientTarget(target, hwcFence, hwcDataspace); } int32_t HalImpl::getHasClientComposition(int64_t display, bool& outHasClientComp) { ExynosDisplay* halDisplay; RET_IF_ERR(getHalDisplay(display, halDisplay)); outHasClientComp = halDisplay->hasClientComposition(); return HWC2_ERROR_NONE; } int32_t HalImpl::setColorMode(int64_t display, ColorMode mode, RenderIntent intent) { ExynosDisplay* halDisplay; RET_IF_ERR(getHalDisplay(display, halDisplay)); int32_t hwcMode; int32_t hwcIntent; a2h::translate(mode, hwcMode); a2h::translate(intent, hwcIntent); return halDisplay->setColorModeWithRenderIntent(hwcMode, hwcIntent); } int32_t HalImpl::setColorTransform(int64_t display, const std::vector& matrix) { // clang-format off constexpr std::array kIdentity = { 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, }; // clang-format on const bool isIdentity = (std::equal(matrix.begin(), matrix.end(), kIdentity.begin())); const common::ColorTransform hint = isIdentity ? common::ColorTransform::IDENTITY : common::ColorTransform::ARBITRARY_MATRIX; ExynosDisplay* halDisplay; RET_IF_ERR(getHalDisplay(display, halDisplay)); int32_t hwcHint; a2h::translate(hint, hwcHint); return halDisplay->setColorTransform(matrix.data(), hwcHint); } int32_t HalImpl::setContentType(int64_t display, ContentType contentType) { ExynosDisplay* halDisplay; RET_IF_ERR(getHalDisplay(display, halDisplay)); int32_t type; a2h::translate(contentType, type); return halDisplay->setContentType(type); } int32_t HalImpl::setDisplayBrightness(int64_t display, float brightness) { ExynosDisplay* halDisplay; RET_IF_ERR(getHalDisplay(display, halDisplay)); return halDisplay->setDisplayBrightness(brightness, true /* wait present */); } int32_t HalImpl::setDisplayedContentSamplingEnabled( [[maybe_unused]] int64_t display, [[maybe_unused]] bool enable, [[maybe_unused]] FormatColorComponent componentMask, [[maybe_unused]] int64_t maxFrames) { return HWC2_ERROR_UNSUPPORTED; } int32_t HalImpl::setLayerBlendMode(int64_t display, int64_t layer, common::BlendMode mode) { ExynosLayer *halLayer; RET_IF_ERR(getHalLayer(display, layer, halLayer)); int32_t hwcMode; a2h::translate(mode, hwcMode); return halLayer->setLayerBlendMode(hwcMode); } int32_t HalImpl::setLayerBuffer(int64_t display, int64_t layer, buffer_handle_t buffer, const ndk::ScopedFileDescriptor& acquireFence) { ExynosLayer *halLayer; RET_IF_ERR(getHalLayer(display, layer, halLayer)); int32_t hwcFd; a2h::translate(acquireFence, hwcFd); return halLayer->setLayerBuffer(buffer, hwcFd); } int32_t HalImpl::setLayerColor(int64_t display, int64_t layer, Color color) { ExynosLayer *halLayer; RET_IF_ERR(getHalLayer(display, layer, halLayer)); hwc_color_t hwcColor; a2h::translate(color, hwcColor); return halLayer->setLayerColor(hwcColor); } int32_t HalImpl::setLayerColorTransform(int64_t display, int64_t layer, const std::vector& matrix) { ExynosLayer *halLayer; RET_IF_ERR(getHalLayer(display, layer, halLayer)); return halLayer->setLayerColorTransform(matrix.data()); } int32_t HalImpl::setLayerCompositionType(int64_t display, int64_t layer, Composition type) { ExynosLayer *halLayer; RET_IF_ERR(getHalLayer(display, layer, halLayer)); int32_t hwcType; a2h::translate(type, hwcType); return halLayer->setLayerCompositionType(hwcType); } int32_t HalImpl::setLayerCursorPosition(int64_t display, int64_t layer, int32_t x, int32_t y) { ExynosLayer *halLayer; RET_IF_ERR(getHalLayer(display, layer, halLayer)); return halLayer->setCursorPosition(x, y); } int32_t HalImpl::setLayerDataspace(int64_t display, int64_t layer, common::Dataspace dataspace) { ExynosLayer *halLayer; RET_IF_ERR(getHalLayer(display, layer, halLayer)); int32_t hwcDataspace; a2h::translate(dataspace, hwcDataspace); return halLayer->setLayerDataspace(hwcDataspace); } int32_t HalImpl::setLayerDisplayFrame(int64_t display, int64_t layer, const common::Rect& frame) { ExynosLayer *halLayer; RET_IF_ERR(getHalLayer(display, layer, halLayer)); hwc_rect_t hwcFrame; a2h::translate(frame, hwcFrame); return halLayer->setLayerDisplayFrame(hwcFrame); } int32_t HalImpl::setLayerPerFrameMetadata(int64_t display, int64_t layer, const std::vector>& metadata) { ExynosLayer *halLayer; RET_IF_ERR(getHalLayer(display, layer, halLayer)); uint32_t count = metadata.size(); std::vector keys; std::vector values; for (uint32_t ix = 0; ix < count; ++ix) { if (metadata[ix]) { int32_t key; a2h::translate(metadata[ix]->key, key); keys.push_back(key); values.push_back(metadata[ix]->value); } } return halLayer->setLayerPerFrameMetadata(count, keys.data(), values.data()); } int32_t HalImpl::setLayerPerFrameMetadataBlobs(int64_t display, int64_t layer, const std::vector>& blobs) { ExynosLayer *halLayer; RET_IF_ERR(getHalLayer(display, layer, halLayer)); uint32_t count = blobs.size(); std::vector keys; std::vector sizes; std::vector values; for (uint32_t ix = 0; ix < count; ++ix) { if (blobs[ix]) { int32_t key; a2h::translate(blobs[ix]->key, key); keys.push_back(key); sizes.push_back(blobs[ix]->blob.size()); values.insert(values.end(), blobs[ix]->blob.begin(), blobs[ix]->blob.end()); } } return halLayer->setLayerPerFrameMetadataBlobs(count, keys.data(), sizes.data(), values.data()); } int32_t HalImpl::setLayerPlaneAlpha(int64_t display, int64_t layer, float alpha) { ExynosLayer *halLayer; RET_IF_ERR(getHalLayer(display, layer, halLayer)); return halLayer->setLayerPlaneAlpha(alpha); } int32_t HalImpl::setLayerSidebandStream([[maybe_unused]] int64_t display, [[maybe_unused]] int64_t layer, [[maybe_unused]] buffer_handle_t stream) { return HWC2_ERROR_UNSUPPORTED; } int32_t HalImpl::setLayerSourceCrop(int64_t display, int64_t layer, const common::FRect& crop) { ExynosLayer *halLayer; RET_IF_ERR(getHalLayer(display, layer, halLayer)); hwc_frect_t hwcCrop; a2h::translate(crop, hwcCrop); return halLayer->setLayerSourceCrop(hwcCrop); } int32_t HalImpl::setLayerSurfaceDamage(int64_t display, int64_t layer, const std::vector>& damage) { ExynosLayer *halLayer; RET_IF_ERR(getHalLayer(display, layer, halLayer)); std::vector hwcDamage; a2h::translate(damage, hwcDamage); hwc_region_t region = { hwcDamage.size(), hwcDamage.data() }; return halLayer->setLayerSurfaceDamage(region); } int32_t HalImpl::setLayerTransform(int64_t display, int64_t layer, common::Transform transform) { ExynosLayer *halLayer; RET_IF_ERR(getHalLayer(display, layer, halLayer)); int32_t hwcTransform; a2h::translate(transform, hwcTransform); return halLayer->setLayerTransform(hwcTransform); } int32_t HalImpl::setLayerVisibleRegion(int64_t display, int64_t layer, const std::vector>& visible) { ExynosLayer *halLayer; RET_IF_ERR(getHalLayer(display, layer, halLayer)); std::vector hwcVisible; a2h::translate(visible, hwcVisible); hwc_region_t region = { hwcVisible.size(), hwcVisible.data() }; return halLayer->setLayerVisibleRegion(region); } int32_t HalImpl::setLayerBrightness(int64_t display, int64_t layer, float brightness) { ExynosLayer *halLayer; RET_IF_ERR(getHalLayer(display, layer, halLayer)); return halLayer->setLayerBrightness(brightness); } int32_t HalImpl::setLayerZOrder(int64_t display, int64_t layer, uint32_t z) { ExynosLayer *halLayer; RET_IF_ERR(getHalLayer(display, layer, halLayer)); return halLayer->setLayerZOrder(z); } int32_t HalImpl::setOutputBuffer(int64_t display, buffer_handle_t buffer, const ndk::ScopedFileDescriptor& releaseFence) { ExynosDisplay* halDisplay; RET_IF_ERR(getHalDisplay(display, halDisplay)); int32_t hwcFence; a2h::translate(releaseFence, hwcFence); auto err = halDisplay->setOutputBuffer(buffer, hwcFence); // unlike in setClientTarget, releaseFence is owned by us if (err == HWC2_ERROR_NONE && hwcFence >= 0) { close(hwcFence); } return err; } int32_t HalImpl::setPowerMode(int64_t display, PowerMode mode) { if (mode == PowerMode::ON_SUSPEND || mode == PowerMode::DOZE_SUSPEND) { return HWC2_ERROR_UNSUPPORTED; } ExynosDisplay* halDisplay; RET_IF_ERR(getHalDisplay(display, halDisplay)); int32_t hwcMode; a2h::translate(mode, hwcMode); return halDisplay->setPowerMode(hwcMode); } int32_t HalImpl::setReadbackBuffer(int64_t display, buffer_handle_t buffer, const ndk::ScopedFileDescriptor& releaseFence) { ExynosDisplay* halDisplay; RET_IF_ERR(getHalDisplay(display, halDisplay)); int32_t hwcFence; a2h::translate(releaseFence, hwcFence); return halDisplay->setReadbackBuffer(buffer, hwcFence); } int32_t HalImpl::setVsyncEnabled(int64_t display, bool enabled) { ExynosDisplay* halDisplay; RET_IF_ERR(getHalDisplay(display, halDisplay)); hwc2_vsync_t hwcEnable; a2h::translate(enabled, hwcEnable); return halDisplay->setVsyncEnabled(hwcEnable); } int32_t HalImpl::setIdleTimerEnabled(int64_t display, int32_t timeout) { ExynosDisplay* halDisplay; RET_IF_ERR(getHalDisplay(display, halDisplay)); return halDisplay->setDisplayIdleTimer(timeout); } int32_t HalImpl::validateDisplay(int64_t display, std::vector* outChangedLayers, std::vector* outCompositionTypes, uint32_t* outDisplayRequestMask, std::vector* outRequestedLayers, std::vector* outRequestMasks, ClientTargetProperty* outClientTargetProperty, DimmingStage* outDimmingStage) { ExynosDisplay* halDisplay; RET_IF_ERR(getHalDisplay(display, halDisplay)); uint32_t typesCount = 0; uint32_t reqsCount = 0; auto err = halDisplay->validateDisplay(&typesCount, &reqsCount); if (err != HWC2_ERROR_NONE && err != HWC2_ERROR_HAS_CHANGES) { return err; } std::vector hwcChangedLayers(typesCount); std::vector hwcCompositionTypes(typesCount); RET_IF_ERR(halDisplay->getChangedCompositionTypes(&typesCount, hwcChangedLayers.data(), hwcCompositionTypes.data())); int32_t displayReqs; std::vector hwcRequestedLayers(reqsCount); outRequestMasks->resize(reqsCount); RET_IF_ERR(halDisplay->getDisplayRequests(&displayReqs, &reqsCount, hwcRequestedLayers.data(), outRequestMasks->data())); h2a::translate(hwcChangedLayers, *outChangedLayers); h2a::translate(hwcCompositionTypes, *outCompositionTypes); *outDisplayRequestMask = displayReqs; h2a::translate(hwcRequestedLayers, *outRequestedLayers); hwc_client_target_property hwcProperty; HwcDimmingStage hwcDimmingStage; if (!halDisplay->getClientTargetProperty(&hwcProperty, &hwcDimmingStage)) { h2a::translate(hwcDimmingStage, *outDimmingStage); h2a::translate(hwcProperty, *outClientTargetProperty); } // else ignore this error return err; } int HalImpl::setExpectedPresentTime( int64_t display, const std::optional expectedPresentTime, int frameIntervalNs) { ExynosDisplay* halDisplay; RET_IF_ERR(getHalDisplay(display, halDisplay)); if (!expectedPresentTime.has_value()) return HWC2_ERROR_NONE; if (halDisplay->getPendingExpectedPresentTime() != 0) { ALOGW("HalImpl: set expected present time multiple times in one frame"); } halDisplay->setExpectedPresentTime(expectedPresentTime->timestampNanos, frameIntervalNs); return HWC2_ERROR_NONE; } int32_t HalImpl::getRCDLayerSupport(int64_t display, bool& outSupport) { ExynosDisplay* halDisplay; RET_IF_ERR(getHalDisplay(display, halDisplay)); return halDisplay->getRCDLayerSupport(outSupport); } int32_t HalImpl::setLayerBlockingRegion( int64_t display, int64_t layer, const std::vector>& blockingRegion) { ExynosLayer* halLayer; RET_IF_ERR(getHalLayer(display, layer, halLayer)); std::vector halBlockingRegion; a2h::translate(blockingRegion, halBlockingRegion); return halLayer->setLayerBlockingRegion(halBlockingRegion); } int32_t HalImpl::getDisplayIdleTimerSupport(int64_t display, bool& outSupport) { ExynosDisplay* halDisplay; RET_IF_ERR(getHalDisplay(display, halDisplay)); return halDisplay->getDisplayIdleTimerSupport(outSupport); } int32_t HalImpl::getDisplayMultiThreadedPresentSupport(const int64_t& display, bool& outSupport) { ExynosDisplay* halDisplay; RET_IF_ERR(getHalDisplay(display, halDisplay)); return halDisplay->getDisplayMultiThreadedPresentSupport(outSupport); } int32_t HalImpl::setRefreshRateChangedCallbackDebugEnabled(int64_t display, bool enabled) { ExynosDisplay* halDisplay; RET_IF_ERR(getHalDisplay(display, halDisplay)); return halDisplay->setRefreshRateChangedCallbackDebugEnabled(enabled); } } // namespace aidl::android::hardware::graphics::composer3::impl