summaryrefslogtreecommitdiff
path: root/hwc3/impl/HalImpl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'hwc3/impl/HalImpl.cpp')
-rw-r--r--hwc3/impl/HalImpl.cpp949
1 files changed, 949 insertions, 0 deletions
diff --git a/hwc3/impl/HalImpl.cpp b/hwc3/impl/HalImpl.cpp
new file mode 100644
index 0000000..f79073b
--- /dev/null
+++ b/hwc3/impl/HalImpl.cpp
@@ -0,0 +1,949 @@
+/*
+ * 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 <android-base/logging.h>
+#include <hardware/hwcomposer2.h>
+
+#include "ExynosDeviceModule.h"
+#include "ExynosDevice.h"
+#include "ExynosDisplay.h"
+#include "ExynosHWCService.h"
+#include "ExynosLayer.h"
+#include "HalImpl.h"
+#include "TranslateHwcAidl.h"
+#include "Util.h"
+
+using namespace SOC_VERSION;
+
+namespace aidl::android::hardware::graphics::composer3::impl {
+
+std::unique_ptr<IComposerHal> IComposerHal::create() {
+ auto device = std::make_unique<ExynosDeviceModule>();
+ if (!device) {
+ return nullptr;
+ }
+
+ return std::make_unique<HalImpl>(std::move(device));
+}
+
+namespace hook {
+
+void hotplug(hwc2_callback_data_t callbackData, hwc2_display_t hwcDisplay,
+ int32_t connected) {
+ auto hal = static_cast<HalImpl*>(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<HalImpl*>(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<HalImpl*>(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<HalImpl*>(callbackData);
+ int64_t display;
+ VsyncPeriodChangeTimeline timeline;
+
+ h2a::translate(hwcDisplay, display);
+ h2a::translate(*hwcTimeline, timeline);
+ hal->getEventCallback()->onVsyncPeriodTimingChanged(display, timeline);
+}
+
+void seamlessPossible(hwc2_callback_data_t callbackData, hwc2_display_t hwcDisplay) {
+ auto hal = static_cast<HalImpl*>(callbackData);
+ int64_t display;
+
+ h2a::translate(hwcDisplay, display);
+ hal->getEventCallback()->onSeamlessPossible(display);
+}
+
+} // nampesapce hook
+
+HalImpl::HalImpl(std::unique_ptr<ExynosDevice> device) : mDevice(std::move(device)) {
+ initCaps();
+#ifdef USES_HWC_SERVICES
+ LOG(DEBUG) << "Start HWCService";
+ mHwcCtx = std::make_unique<ExynosHWCCtx>();
+ 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<int32_t> halCaps(count);
+ mDevice->getCapabilities(&count, halCaps.data());
+
+ for (auto hwcCap : halCaps) {
+ Capability cap;
+ h2a::translate(hwcCap, cap);
+ mCaps.insert(cap);
+ }
+}
+
+int32_t HalImpl::getHalDisplay(int64_t display, ExynosDisplay*& halDisplay) {
+ hwc2_display_t hwcDisplay;
+ a2h::translate(display, hwcDisplay);
+ halDisplay = mDevice->getDisplay(static_cast<uint32_t>(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<Capability>* caps) {
+ caps->clear();
+ caps->insert(caps->begin(), mCaps.begin(), mCaps.end());
+}
+
+void HalImpl::dumpDebugInfo(std::string* output) {
+ uint32_t count = 0;
+ mDevice->dump(&count, nullptr);
+
+ output->resize(count);
+ mDevice->dump(&count, output->data());
+}
+
+void HalImpl::registerEventCallback(EventCallback* callback) {
+ mEventCallback = callback;
+
+ mDevice->registerCallback(HWC2_CALLBACK_HOTPLUG, this,
+ reinterpret_cast<hwc2_function_pointer_t>(hook::hotplug));
+ mDevice->registerCallback(HWC2_CALLBACK_REFRESH, this,
+ reinterpret_cast<hwc2_function_pointer_t>(hook::refresh));
+ mDevice->registerCallback(HWC2_CALLBACK_VSYNC_2_4, this,
+ reinterpret_cast<hwc2_function_pointer_t>(hook::vsync));
+ mDevice->registerCallback(HWC2_CALLBACK_VSYNC_PERIOD_TIMING_CHANGED, this,
+ reinterpret_cast<hwc2_function_pointer_t>(hook::vsyncPeriodTimingChanged));
+ mDevice->registerCallback(HWC2_CALLBACK_SEAMLESS_POSSIBLE, this,
+ reinterpret_cast<hwc2_function_pointer_t>(hook::seamlessPossible));
+}
+
+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);
+
+ 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<hwc2_layer_t>(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<uint32_t>(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<ColorMode>* outModes) {
+ ExynosDisplay* halDisplay;
+ RET_IF_ERR(getHalDisplay(display, halDisplay));
+
+ uint32_t count = 0;
+ RET_IF_ERR(halDisplay->getColorModes(&count, nullptr));
+
+ std::vector<int32_t> 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<float>* matrix) {
+ // Pixel HWC does not support dataspace saturation matrix, return unit matrix.
+ std::vector<float> 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<DisplayCapability>* caps) {
+ ExynosDisplay* halDisplay;
+ RET_IF_ERR(getHalDisplay(display, halDisplay));
+
+ uint32_t count = 0;
+ RET_IF_ERR(halDisplay->getDisplayCapabilities(&count, nullptr));
+
+ std::vector<uint32_t> 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<int32_t>* configs) {
+ ExynosDisplay* halDisplay;
+ RET_IF_ERR(getHalDisplay(display, halDisplay));
+
+ uint32_t count = 0;
+ RET_IF_ERR(halDisplay->getDisplayConfigs(&count, nullptr));
+
+ std::vector<hwc2_config_t> hwcConfigs(count);
+ RET_IF_ERR(halDisplay->getDisplayConfigs(&count, hwcConfigs.data()));
+
+ h2a::translate(hwcConfigs, *configs);
+ return HWC2_ERROR_NONE;
+}
+
+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::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<int32_t> 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::getLayerGenericMetadataKeys(std::vector<LayerGenericMetadataKey>* keys) {
+ uint32_t keyLength = 0;
+
+ // Only attempt to load the first 100 keys to avoid an infinite loop
+ // if something goes wrong
+ for (uint32_t index = 0; index < 100; ++index) {
+ mDevice->getLayerGenericMetadataKey(index, &keyLength, nullptr, nullptr);
+ if (keyLength == 0) {
+ break;
+ }
+
+ LayerGenericMetadataKey key;
+ key.name.resize(keyLength);
+ mDevice->getLayerGenericMetadataKey(index, &keyLength, key.name.data(), &key.mandatory);
+ keys->emplace_back(std::move(key));
+ }
+
+ return HWC2_ERROR_NONE;
+}
+
+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<PerFrameMetadataKey>* 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;
+ } else {
+ numKeys = HWC2_MAX_FRAME_AVERAGE_LIGHT_LEVEL;
+ }
+ 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<RenderIntent>* 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<int32_t> 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<ContentType>* types) {
+ ExynosDisplay* halDisplay;
+ RET_IF_ERR(getHalDisplay(display, halDisplay));
+
+ uint32_t count = 0;
+ RET_IF_ERR(halDisplay->getSupportedContentTypes(&count, nullptr));
+
+ std::vector<uint32_t> hwcTypes(count);
+ RET_IF_ERR(halDisplay->getSupportedContentTypes(&count, hwcTypes.data()));
+
+ h2a::translate(hwcTypes, *types);
+ return HWC2_ERROR_NONE;
+}
+
+int32_t HalImpl::presentDisplay(int64_t display, ndk::ScopedFileDescriptor& fence,
+ std::vector<int64_t>* outLayers,
+ std::vector<ndk::ScopedFileDescriptor>* 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.string()
+ << ": acceptDisplayChanges was not called";
+ if (halDisplay->acceptDisplayChanges() != HWC2_ERROR_NONE) {
+ LOG(ERROR) << halDisplay->mDisplayName.string()
+ << ": 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<hwc2_layer_t> hwcLayers(count);
+ std::vector<int32_t> 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::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<common::Rect>& damage) {
+ ExynosDisplay* halDisplay;
+ RET_IF_ERR(getHalDisplay(display, halDisplay));
+
+ int32_t hwcFence;
+ int32_t hwcDataspace;
+ std::vector<hwc_rect_t> 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::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<float>& matrix,
+ common::ColorTransform hint) {
+ 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);
+}
+
+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<float>& 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::setLayerFloatColor([[maybe_unused]] int64_t display,
+ [[maybe_unused]] int64_t layer,
+ [[maybe_unused]] FloatColor color) {
+ return HWC2_ERROR_UNSUPPORTED;
+}
+
+int32_t HalImpl::setLayerGenericMetadata([[maybe_unused]] int64_t display,
+ [[maybe_unused]] int64_t layer,
+ [[maybe_unused]] const GenericMetadata& metadata) {
+ return HWC2_ERROR_UNSUPPORTED;
+}
+
+int32_t HalImpl::setLayerPerFrameMetadata(int64_t display, int64_t layer,
+ const std::vector<std::optional<PerFrameMetadata>>& metadata) {
+ ExynosLayer *halLayer;
+ RET_IF_ERR(getHalLayer(display, layer, halLayer));
+
+ uint32_t count = metadata.size();
+ std::vector<int32_t> keys;
+ std::vector<float> 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<std::optional<PerFrameMetadataBlob>>& blobs) {
+ ExynosLayer *halLayer;
+ RET_IF_ERR(getHalLayer(display, layer, halLayer));
+
+ uint32_t count = blobs.size();
+ std::vector<int32_t> keys;
+ std::vector<uint32_t> sizes;
+ std::vector<uint8_t> 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<std::optional<common::Rect>>& damage) {
+ ExynosLayer *halLayer;
+ RET_IF_ERR(getHalLayer(display, layer, halLayer));
+
+ std::vector<hwc_rect_t> 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<std::optional<common::Rect>>& visible) {
+ ExynosLayer *halLayer;
+ RET_IF_ERR(getHalLayer(display, layer, halLayer));
+
+ std::vector<hwc_rect_t> hwcVisible;
+ a2h::translate(visible, hwcVisible);
+ hwc_region_t region = { hwcVisible.size(), hwcVisible.data() };
+
+ return halLayer->setLayerVisibleRegion(region);
+}
+
+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) {
+ 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::validateDisplay(int64_t display, std::vector<int64_t>* outChangedLayers,
+ std::vector<Composition>* outCompositionTypes,
+ uint32_t* outDisplayRequestMask,
+ std::vector<int64_t>* outRequestedLayers,
+ std::vector<int32_t>* outRequestMasks,
+ ClientTargetProperty* outClientTargetProperty) {
+ 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<hwc2_layer_t> hwcChangedLayers(typesCount);
+ std::vector<int32_t> hwcCompositionTypes(typesCount);
+ RET_IF_ERR(halDisplay->getChangedCompositionTypes(&typesCount, hwcChangedLayers.data(),
+ hwcCompositionTypes.data()));
+
+ int32_t displayReqs;
+ std::vector<hwc2_layer_t> 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;
+ if (!halDisplay->getClientTargetProperty(&hwcProperty)) {
+ h2a::translate(hwcProperty, *outClientTargetProperty);
+ } // else ignore this error
+
+ return HWC2_ERROR_NONE;
+}
+
+} // namespace aidl::android::hardware::graphics::composer3::impl