1 /*
2  * Copyright 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "DisplayConfig.h"
18 
19 #include <unordered_map>
20 
21 namespace aidl::android::hardware::graphics::composer3::impl {
22 namespace {
23 
24 template <class T>
hashCombine(size_t & hash,const T & value)25 inline void hashCombine(size_t& hash, const T& value) {
26     std::hash<T> hasher;
27     hash ^= hasher(value) + 0x9e3779b9 + (hash << 6) + (hash >> 2);
28 }
29 
30 }  // namespace
31 
setAttribute(DisplayAttribute attribute,int32_t value)32 void DisplayConfig::setAttribute(DisplayAttribute attribute, int32_t value) {
33     if (attribute == DisplayAttribute::WIDTH) {
34         mWidth = value;
35     }
36     if (attribute == DisplayAttribute::HEIGHT) {
37         mHeight = value;
38     }
39     if (attribute == DisplayAttribute::DPI_X) {
40         mDpiX = value;
41     }
42     if (attribute == DisplayAttribute::DPI_Y) {
43         mDpiY = value;
44     }
45     if (attribute == DisplayAttribute::VSYNC_PERIOD) {
46         mVsyncPeriodNanos = value;
47     }
48     if (attribute == DisplayAttribute::CONFIG_GROUP) {
49         mConfigGroup = value;
50     }
51 }
52 
getAttribute(DisplayAttribute attribute) const53 int32_t DisplayConfig::getAttribute(DisplayAttribute attribute) const {
54     if (attribute == DisplayAttribute::WIDTH) {
55         return mWidth;
56     }
57     if (attribute == DisplayAttribute::HEIGHT) {
58         return mHeight;
59     }
60     if (attribute == DisplayAttribute::DPI_X) {
61         // From hwcomposer2.h, HWC2_ATTRIBUTE_DPI_X returns "Dots per thousand
62         // inches (DPI * 1000)".
63         return getDotsPerThousandInchesX();
64     }
65     if (attribute == DisplayAttribute::DPI_Y) {
66         // From hwcomposer2.h, HWC2_ATTRIBUTE_DPI_Y returns "Dots per thousand
67         // inches (DPI * 1000)"
68         return getDotsPerThousandInchesY();
69     }
70     if (attribute == DisplayAttribute::VSYNC_PERIOD) {
71         return mVsyncPeriodNanos;
72     }
73     if (attribute == DisplayAttribute::CONFIG_GROUP) {
74         return mConfigGroup;
75     }
76     return -1;
77 }
78 
toString() const79 std::string DisplayConfig::toString() const {
80     std::string output;
81     output += " id: " + std::to_string(mId);
82     output += " w:" + std::to_string(mWidth);
83     output += " h:" + std::to_string(mHeight);
84     output += " dpi-x:" + std::to_string(mDpiX);
85     output += " dpi-y:" + std::to_string(mDpiY);
86     output += " vsync:" + std::to_string(1e9 / mVsyncPeriodNanos);
87     output += " config-group:" + std::to_string(mConfigGroup);
88     return output;
89 }
90 
91 /*static*/
addConfigGroups(std::vector<DisplayConfig> * configs)92 void DisplayConfig::addConfigGroups(std::vector<DisplayConfig>* configs) {
93     // From /hardware/interfaces/graphics/composer/2.4/IComposerClient.hal:
94     // "Configurations which share the same config group are similar in all
95     // attributes except for the vsync period."
96     struct ConfigForGroupHash {
97         size_t operator()(const DisplayConfig& config) const {
98             size_t hash = 0;
99             hashCombine(hash, config.mWidth);
100             hashCombine(hash, config.mHeight);
101             hashCombine(hash, config.mDpiX);
102             hashCombine(hash, config.mDpiY);
103             return hash;
104         }
105     };
106     struct ConfigForGroupEq {
107         size_t operator()(const DisplayConfig& a, const DisplayConfig& b) const {
108             if (a.mWidth != b.mWidth) {
109                 return a.mWidth < b.mWidth;
110             }
111             if (a.mHeight != b.mHeight) {
112                 return a.mHeight < b.mHeight;
113             }
114             if (a.mDpiX != b.mDpiX) {
115                 return a.mDpiX < b.mDpiX;
116             }
117             return a.mDpiY < b.mDpiY;
118         }
119     };
120 
121     std::unordered_map<DisplayConfig, int32_t, ConfigForGroupHash, ConfigForGroupEq>
122         configToConfigGroup;
123 
124     for (auto& config : *configs) {
125         auto [it, inserted] = configToConfigGroup.try_emplace(config, configToConfigGroup.size());
126         config.setConfigGroup(it->second);
127     }
128 }
129 
130 }  // namespace aidl::android::hardware::graphics::composer3::impl
131