blob: 06f67baf86a32e181cfe790c30d37d9d0ae6e627 [file] [log] [blame]
/*
* Copyright 2016 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.
*/
#undef LOG_TAG
#define LOG_TAG "HwcComposer"
#include <inttypes.h>
#include <log/log.h>
#include "ComposerHal.h"
namespace android {
using hardware::Return;
using hardware::hidl_vec;
using hardware::hidl_handle;
namespace Hwc2 {
namespace {
class BufferHandle {
public:
BufferHandle(const native_handle_t* buffer)
{
// nullptr is not a valid handle to HIDL
mHandle = (buffer) ? buffer : native_handle_init(mStorage, 0, 0);
}
operator const hidl_handle&() const
{
return mHandle;
}
private:
NATIVE_HANDLE_DECLARE_STORAGE(mStorage, 0, 0);
hidl_handle mHandle;
};
class FenceHandle
{
public:
FenceHandle(int fd, bool owned)
: mOwned(owned)
{
native_handle_t* handle;
if (fd >= 0) {
handle = native_handle_init(mStorage, 1, 0);
handle->data[0] = fd;
} else {
// nullptr is not a valid handle to HIDL
handle = native_handle_init(mStorage, 0, 0);
}
mHandle = handle;
}
~FenceHandle()
{
if (mOwned) {
native_handle_close(mHandle);
}
}
operator const hidl_handle&() const
{
return mHandle;
}
private:
bool mOwned;
NATIVE_HANDLE_DECLARE_STORAGE(mStorage, 1, 0);
hidl_handle mHandle;
};
// assume NO_RESOURCES when Status::isOk returns false
constexpr Error kDefaultError = Error::NO_RESOURCES;
template<typename T, typename U>
T unwrapRet(Return<T>& ret, const U& default_val)
{
return (ret.getStatus().isOk()) ? static_cast<T>(ret) :
static_cast<T>(default_val);
}
Error unwrapRet(Return<Error>& ret)
{
return unwrapRet(ret, kDefaultError);
}
template<typename T>
void assignFromHidlVec(std::vector<T>& vec, const hidl_vec<T>& data)
{
vec.clear();
vec.insert(vec.begin(), &data[0], &data[data.size()]);
}
} // anonymous namespace
Composer::Composer()
{
mService = IComposer::getService("hwcomposer");
if (mService == nullptr) {
LOG_ALWAYS_FATAL("failed to get hwcomposer service");
}
}
std::vector<IComposer::Capability> Composer::getCapabilities() const
{
std::vector<IComposer::Capability> capabilities;
mService->getCapabilities(
[&](const auto& tmpCapabilities) {
assignFromHidlVec(capabilities, tmpCapabilities);
});
return capabilities;
}
std::string Composer::dumpDebugInfo() const
{
std::string info;
mService->dumpDebugInfo([&](const auto& tmpInfo) {
info = tmpInfo.c_str();
});
return info;
}
void Composer::registerCallback(const sp<IComposerCallback>& callback) const
{
auto ret = mService->registerCallback(callback);
if (!ret.getStatus().isOk()) {
ALOGE("failed to register IComposerCallback");
}
}
uint32_t Composer::getMaxVirtualDisplayCount() const
{
auto ret = mService->getMaxVirtualDisplayCount();
return unwrapRet(ret, 0);
}
Error Composer::createVirtualDisplay(uint32_t width, uint32_t height,
PixelFormat& format, Display& display) const
{
Error error = kDefaultError;
mService->createVirtualDisplay(width, height, format,
[&](const auto& tmpError, const auto& tmpDisplay,
const auto& tmpFormat) {
error = tmpError;
if (error != Error::NONE) {
return;
}
display = tmpDisplay;
format = tmpFormat;
});
return error;
}
Error Composer::destroyVirtualDisplay(Display display) const
{
auto ret = mService->destroyVirtualDisplay(display);
return unwrapRet(ret);
}
Error Composer::acceptDisplayChanges(Display display) const
{
auto ret = mService->acceptDisplayChanges(display);
return unwrapRet(ret);
}
Error Composer::createLayer(Display display, Layer& layer) const
{
Error error = kDefaultError;
mService->createLayer(display,
[&](const auto& tmpError, const auto& tmpLayer) {
error = tmpError;
if (error != Error::NONE) {
return;
}
layer = tmpLayer;
});
return error;
}
Error Composer::destroyLayer(Display display, Layer layer) const
{
auto ret = mService->destroyLayer(display, layer);
return unwrapRet(ret);
}
Error Composer::getActiveConfig(Display display, Config& config) const
{
Error error = kDefaultError;
mService->getActiveConfig(display,
[&](const auto& tmpError, const auto& tmpConfig) {
error = tmpError;
if (error != Error::NONE) {
return;
}
config = tmpConfig;
});
return error;
}
Error Composer::getChangedCompositionTypes(Display display,
std::vector<Layer>& layers,
std::vector<IComposer::Composition>& types) const
{
Error error = kDefaultError;
mService->getChangedCompositionTypes(display,
[&](const auto& tmpError, const auto& tmpLayers,
const auto& tmpTypes) {
error = tmpError;
if (error != Error::NONE) {
return;
}
assignFromHidlVec(layers, tmpLayers);
assignFromHidlVec(types, tmpTypes);
});
return error;
}
Error Composer::getColorModes(Display display,
std::vector<ColorMode>& modes) const
{
Error error = kDefaultError;
mService->getColorModes(display,
[&](const auto& tmpError, const auto& tmpModes) {
error = tmpError;
if (error != Error::NONE) {
return;
}
assignFromHidlVec(modes, tmpModes);
});
return error;
}
Error Composer::getDisplayAttribute(Display display, Config config,
IComposer::Attribute attribute, int32_t& value) const
{
Error error = kDefaultError;
mService->getDisplayAttribute(display, config, attribute,
[&](const auto& tmpError, const auto& tmpValue) {
error = tmpError;
if (error != Error::NONE) {
return;
}
value = tmpValue;
});
return error;
}
Error Composer::getDisplayConfigs(Display display,
std::vector<Config>& configs) const
{
Error error = kDefaultError;
mService->getDisplayConfigs(display,
[&](const auto& tmpError, const auto& tmpConfigs) {
error = tmpError;
if (error != Error::NONE) {
return;
}
assignFromHidlVec(configs, tmpConfigs);
});
return error;
}
Error Composer::getDisplayName(Display display, std::string& name) const
{
Error error = kDefaultError;
mService->getDisplayName(display,
[&](const auto& tmpError, const auto& tmpName) {
error = tmpError;
if (error != Error::NONE) {
return;
}
name = tmpName.c_str();
});
return error;
}
Error Composer::getDisplayRequests(Display display,
uint32_t& displayRequestMask, std::vector<Layer>& layers,
std::vector<uint32_t>& layerRequestMasks) const
{
Error error = kDefaultError;
mService->getDisplayRequests(display,
[&](const auto& tmpError, const auto& tmpDisplayRequestMask,
const auto& tmpLayers, const auto& tmpLayerRequestMasks) {
error = tmpError;
if (error != Error::NONE) {
return;
}
displayRequestMask = tmpDisplayRequestMask;
assignFromHidlVec(layers, tmpLayers);
assignFromHidlVec(layerRequestMasks, tmpLayerRequestMasks);
});
return error;
}
Error Composer::getDisplayType(Display display, IComposer::DisplayType& type) const
{
Error error = kDefaultError;
mService->getDisplayType(display,
[&](const auto& tmpError, const auto& tmpType) {
error = tmpError;
if (error != Error::NONE) {
return;
}
type = tmpType;
});
return error;
}
Error Composer::getDozeSupport(Display display, bool& support) const
{
Error error = kDefaultError;
mService->getDozeSupport(display,
[&](const auto& tmpError, const auto& tmpSupport) {
error = tmpError;
if (error != Error::NONE) {
return;
}
support = tmpSupport;
});
return error;
}
Error Composer::getHdrCapabilities(Display display, std::vector<Hdr>& types,
float& maxLuminance, float& maxAverageLuminance,
float& minLuminance) const
{
Error error = kDefaultError;
mService->getHdrCapabilities(display,
[&](const auto& tmpError, const auto& tmpTypes,
const auto& tmpMaxLuminance,
const auto& tmpMaxAverageLuminance,
const auto& tmpMinLuminance) {
error = tmpError;
if (error != Error::NONE) {
return;
}
assignFromHidlVec(types, tmpTypes);
maxLuminance = tmpMaxLuminance;
maxAverageLuminance = tmpMaxAverageLuminance;
minLuminance = tmpMinLuminance;
});
return error;
}
Error Composer::getReleaseFences(Display display, std::vector<Layer>& layers,
std::vector<int>& releaseFences) const
{
Error error = kDefaultError;
mService->getReleaseFences(display,
[&](const auto& tmpError, const auto& tmpLayers,
const auto& tmpReleaseFences) {
error = tmpError;
if (error != Error::NONE) {
return;
}
if (static_cast<int>(tmpLayers.size()) !=
tmpReleaseFences->numFds) {
ALOGE("invalid releaseFences outputs: "
"layer count %zu != fence count %d",
tmpLayers.size(), tmpReleaseFences->numFds);
error = Error::NO_RESOURCES;
return;
}
// dup the file descriptors
std::vector<int> tmpFds;
tmpFds.reserve(tmpReleaseFences->numFds);
for (int i = 0; i < tmpReleaseFences->numFds; i++) {
int fd = dup(tmpReleaseFences->data[i]);
if (fd < 0) {
break;
}
tmpFds.push_back(fd);
}
if (static_cast<int>(tmpFds.size()) <
tmpReleaseFences->numFds) {
for (auto fd : tmpFds) {
close(fd);
}
error = Error::NO_RESOURCES;
return;
}
assignFromHidlVec(layers, tmpLayers);
releaseFences = std::move(tmpFds);
});
return error;
}
Error Composer::presentDisplay(Display display, int& presentFence) const
{
Error error = kDefaultError;
mService->presentDisplay(display,
[&](const auto& tmpError, const auto& tmpPresentFence) {
error = tmpError;
if (error != Error::NONE) {
return;
}
if (tmpPresentFence->numFds == 1) {
int fd = dup(tmpPresentFence->data[0]);
if (fd >= 0) {
presentFence = fd;
} else {
error = Error::NO_RESOURCES;
}
} else {
presentFence = -1;
}
});
return error;
}
Error Composer::setActiveConfig(Display display, Config config) const
{
auto ret = mService->setActiveConfig(display, config);
return unwrapRet(ret);
}
Error Composer::setClientTarget(Display display, const native_handle_t* target,
int acquireFence, Dataspace dataspace,
const std::vector<IComposer::Rect>& damage) const
{
BufferHandle tmpTarget(target);
FenceHandle tmpAcquireFence(acquireFence, true);
hidl_vec<IComposer::Rect> tmpDamage;
tmpDamage.setToExternal(const_cast<IComposer::Rect*>(damage.data()),
damage.size());
auto ret = mService->setClientTarget(display, tmpTarget,
tmpAcquireFence, dataspace, tmpDamage);
return unwrapRet(ret);
}
Error Composer::setColorMode(Display display, ColorMode mode) const
{
auto ret = mService->setColorMode(display, mode);
return unwrapRet(ret);
}
Error Composer::setColorTransform(Display display, const float* matrix,
ColorTransform hint) const
{
hidl_vec<float> tmpMatrix;
tmpMatrix.setToExternal(const_cast<float*>(matrix), 16);
auto ret = mService->setColorTransform(display, tmpMatrix, hint);
return unwrapRet(ret);
}
Error Composer::setOutputBuffer(Display display, const native_handle_t* buffer,
int releaseFence) const
{
BufferHandle tmpBuffer(buffer);
FenceHandle tmpReleaseFence(releaseFence, false);
auto ret = mService->setOutputBuffer(display, tmpBuffer, tmpReleaseFence);
return unwrapRet(ret);
}
Error Composer::setPowerMode(Display display, IComposer::PowerMode mode) const
{
auto ret = mService->setPowerMode(display, mode);
return unwrapRet(ret);
}
Error Composer::setVsyncEnabled(Display display, IComposer::Vsync enabled) const
{
auto ret = mService->setVsyncEnabled(display, enabled);
return unwrapRet(ret);
}
Error Composer::validateDisplay(Display display, uint32_t& numTypes, uint32_t&
numRequests) const
{
Error error = kDefaultError;
mService->validateDisplay(display,
[&](const auto& tmpError, const auto& tmpNumTypes,
const auto& tmpNumRequests) {
error = tmpError;
if (error != Error::NONE) {
return;
}
numTypes = tmpNumTypes;
numRequests = tmpNumRequests;
});
return error;
}
Error Composer::setCursorPosition(Display display, Layer layer,
int32_t x, int32_t y) const
{
auto ret = mService->setCursorPosition(display, layer, x, y);
return unwrapRet(ret);
}
Error Composer::setLayerBuffer(Display display, Layer layer,
const native_handle_t* buffer, int acquireFence) const
{
BufferHandle tmpBuffer(buffer);
FenceHandle tmpAcquireFence(acquireFence, true);
auto ret = mService->setLayerBuffer(display, layer,
tmpBuffer, tmpAcquireFence);
return unwrapRet(ret);
}
Error Composer::setLayerSurfaceDamage(Display display, Layer layer,
const std::vector<IComposer::Rect>& damage) const
{
hidl_vec<IComposer::Rect> tmpDamage;
tmpDamage.setToExternal(const_cast<IComposer::Rect*>(damage.data()),
damage.size());
auto ret = mService->setLayerSurfaceDamage(display, layer, tmpDamage);
return unwrapRet(ret);
}
Error Composer::setLayerBlendMode(Display display, Layer layer,
IComposer::BlendMode mode) const
{
auto ret = mService->setLayerBlendMode(display, layer, mode);
return unwrapRet(ret);
}
Error Composer::setLayerColor(Display display, Layer layer,
const IComposer::Color& color) const
{
auto ret = mService->setLayerColor(display, layer, color);
return unwrapRet(ret);
}
Error Composer::setLayerCompositionType(Display display, Layer layer,
IComposer::Composition type) const
{
auto ret = mService->setLayerCompositionType(display, layer, type);
return unwrapRet(ret);
}
Error Composer::setLayerDataspace(Display display, Layer layer,
Dataspace dataspace) const
{
auto ret = mService->setLayerDataspace(display, layer, dataspace);
return unwrapRet(ret);
}
Error Composer::setLayerDisplayFrame(Display display, Layer layer,
const IComposer::Rect& frame) const
{
auto ret = mService->setLayerDisplayFrame(display, layer, frame);
return unwrapRet(ret);
}
Error Composer::setLayerPlaneAlpha(Display display, Layer layer,
float alpha) const
{
auto ret = mService->setLayerPlaneAlpha(display, layer, alpha);
return unwrapRet(ret);
}
Error Composer::setLayerSidebandStream(Display display, Layer layer,
const native_handle_t* stream) const
{
BufferHandle tmpStream(stream);
auto ret = mService->setLayerSidebandStream(display, layer, tmpStream);
return unwrapRet(ret);
}
Error Composer::setLayerSourceCrop(Display display, Layer layer,
const IComposer::FRect& crop) const
{
auto ret = mService->setLayerSourceCrop(display, layer, crop);
return unwrapRet(ret);
}
Error Composer::setLayerTransform(Display display, Layer layer,
Transform transform) const
{
auto ret = mService->setLayerTransform(display, layer, transform);
return unwrapRet(ret);
}
Error Composer::setLayerVisibleRegion(Display display, Layer layer,
const std::vector<IComposer::Rect>& visible) const
{
hidl_vec<IComposer::Rect> tmpVisible;
tmpVisible.setToExternal(const_cast<IComposer::Rect*>(visible.data()),
visible.size());
auto ret = mService->setLayerVisibleRegion(display, layer, tmpVisible);
return unwrapRet(ret);
}
Error Composer::setLayerZOrder(Display display, Layer layer, uint32_t z) const
{
auto ret = mService->setLayerZOrder(display, layer, z);
return unwrapRet(ret);
}
} // namespace Hwc2
} // namespace android