blob: 74f850d077e96d1be4d12309d98dac93c4d372a6 [file] [log] [blame]
/*
* 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::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) {
// clang-format off
constexpr std::array<float, 16> 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);
}
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::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;
}
int HalImpl::setExpectedPresentTime(
int64_t display, const std::optional<ClockMonotonicTimestamp> expectedPresentTime) {
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);
return HWC2_ERROR_NONE;
}
} // namespace aidl::android::hardware::graphics::composer3::impl