blob: abd0b89ef0496fe85431c8de4c4912a84bd60637 [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 "DisplayConfig.h"
#include <unordered_map>
namespace {
template <class T>
inline void hashCombine(size_t& hash, const T& value) {
std::hash<T> hasher;
hash ^= hasher(value) + 0x9e3779b9 + (hash << 6) + (hash >> 2);
}
} // namespace
void DisplayConfig::setAttribute(HWC2::Attribute attribute, int32_t value) {
if (attribute == HWC2::Attribute::Width) {
mWidth = value;
}
if (attribute == HWC2::Attribute::Height) {
mHeight = value;
}
if (attribute == HWC2::Attribute::DpiX) {
mDpiX = value;
}
if (attribute == HWC2::Attribute::DpiY) {
mDpiY = value;
}
if (attribute == HWC2::Attribute::VsyncPeriod) {
mVsyncPeriodNanos = value;
}
if (attribute == HWC2::Attribute::ConfigGroup) {
mConfigGroup = value;
}
}
int32_t DisplayConfig::getAttribute(HWC2::Attribute attribute) const {
if (attribute == HWC2::Attribute::Width) {
return mWidth;
}
if (attribute == HWC2::Attribute::Height) {
return mHeight;
}
if (attribute == HWC2::Attribute::DpiX) {
// From hwcomposer2.h, HWC2_ATTRIBUTE_DPI_X returns "Dots per thousand
// inches (DPI * 1000)".
return getDotsPerThousandInchesX();
}
if (attribute == HWC2::Attribute::DpiY) {
// From hwcomposer2.h, HWC2_ATTRIBUTE_DPI_Y returns "Dots per thousand
// inches (DPI * 1000)"
return getDotsPerThousandInchesY();
}
if (attribute == HWC2::Attribute::VsyncPeriod) {
return mVsyncPeriodNanos;
}
if (attribute == HWC2::Attribute::ConfigGroup) {
return mConfigGroup;
}
return -1;
}
std::string DisplayConfig::toString() const {
std::string output;
output += " w:" + std::to_string(mWidth);
output += " h:" + std::to_string(mHeight);
output += " dpi-x:" + std::to_string(mDpiX);
output += " dpi-y:" + std::to_string(mDpiY);
output += " vsync:" + std::to_string(1e9 / mVsyncPeriodNanos);
output += " config-group:" + std::to_string(mConfigGroup);
return output;
}
/*static*/
void DisplayConfig::addConfigGroups(std::vector<DisplayConfig>* configs) {
// From /hardware/interfaces/graphics/composer/2.4/IComposerClient.hal:
// "Configurations which share the same config group are similar in all
// attributes except for the vsync period."
struct ConfigForGroupHash {
size_t operator()(const DisplayConfig& config) const {
size_t hash = 0;
hashCombine(hash, config.mWidth);
hashCombine(hash, config.mHeight);
hashCombine(hash, config.mDpiX);
hashCombine(hash, config.mDpiY);
return hash;
}
};
struct ConfigForGroupEq {
size_t operator()(const DisplayConfig& a, const DisplayConfig& b) const {
if (a.mWidth != b.mWidth) {
return a.mWidth < b.mWidth;
}
if (a.mHeight != b.mHeight) {
return a.mHeight < b.mHeight;
}
if (a.mDpiX != b.mDpiX) {
return a.mDpiX < b.mDpiX;
}
return a.mDpiY < b.mDpiY;
}
};
std::unordered_map<DisplayConfig, int32_t, ConfigForGroupHash,
ConfigForGroupEq>
configToConfigGroup;
for (auto& config : *configs) {
auto [it, inserted] =
configToConfigGroup.try_emplace(config, configToConfigGroup.size());
config.setConfigGroup(it->second);
}
}