summaryrefslogtreecommitdiff
path: root/services/surfaceflinger/DisplayHardware/DisplayMode.h
blob: 85cc993c67bc59407c5402e9d2d37f0be2efb1fe (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
/*
 * Copyright 2020 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.
 */

#pragma once

#include "DisplayHardware/Hal.h"
#include "Fps.h"
#include "Scheduler/StrongTyping.h"

#include <android-base/stringprintf.h>
#include <android/configuration.h>
#include <ui/DisplayMode.h>
#include <ui/Size.h>
#include <utils/Timers.h>

#include <cstddef>
#include <memory>
#include <vector>

namespace android {

namespace hal = android::hardware::graphics::composer::hal;

class DisplayMode;
using DisplayModePtr = std::shared_ptr<const DisplayMode>;
using DisplayModes = std::vector<DisplayModePtr>;
using DisplayModeId = StrongTyping<ui::DisplayModeId, struct DisplayModeIdTag, Compare, Hash>;

class DisplayMode {
public:
    class Builder {
    public:
        explicit Builder(hal::HWConfigId id) : mDisplayMode(new DisplayMode(id)) {}

        DisplayModePtr build() {
            return std::const_pointer_cast<const DisplayMode>(std::move(mDisplayMode));
        }

        Builder& setId(DisplayModeId id) {
            mDisplayMode->mId = id;
            return *this;
        }

        Builder& setWidth(int32_t width) {
            mDisplayMode->mWidth = width;
            return *this;
        }

        Builder& setHeight(int32_t height) {
            mDisplayMode->mHeight = height;
            return *this;
        }

        Builder& setVsyncPeriod(int32_t vsyncPeriod) {
            mDisplayMode->mFps = Fps::fromPeriodNsecs(vsyncPeriod);
            return *this;
        }

        Builder& setDpiX(int32_t dpiX) {
            if (dpiX == -1) {
                mDisplayMode->mDpiX = getDefaultDensity();
            } else {
                mDisplayMode->mDpiX = dpiX / 1000.0f;
            }
            return *this;
        }

        Builder& setDpiY(int32_t dpiY) {
            if (dpiY == -1) {
                mDisplayMode->mDpiY = getDefaultDensity();
            } else {
                mDisplayMode->mDpiY = dpiY / 1000.0f;
            }
            return *this;
        }

        Builder& setGroup(int32_t group) {
            mDisplayMode->mGroup = group;
            return *this;
        }

    private:
        float getDefaultDensity() {
            // Default density is based on TVs: 1080p displays get XHIGH density, lower-
            // resolution displays get TV density. Maybe eventually we'll need to update
            // it for 4k displays, though hopefully those will just report accurate DPI
            // information to begin with. This is also used for virtual displays and
            // older HWC implementations, so be careful about orientation.

            auto longDimension = std::max(mDisplayMode->mWidth, mDisplayMode->mHeight);
            if (longDimension >= 1080) {
                return ACONFIGURATION_DENSITY_XHIGH;
            } else {
                return ACONFIGURATION_DENSITY_TV;
            }
        }
        std::shared_ptr<DisplayMode> mDisplayMode;
    };

    DisplayModeId getId() const { return mId; }
    hal::HWConfigId getHwcId() const { return mHwcId; }

    int32_t getWidth() const { return mWidth; }
    int32_t getHeight() const { return mHeight; }
    ui::Size getSize() const { return {mWidth, mHeight}; }
    Fps getFps() const { return mFps; }
    nsecs_t getVsyncPeriod() const { return mFps.getPeriodNsecs(); }
    float getDpiX() const { return mDpiX; }
    float getDpiY() const { return mDpiY; }

    // Switches between modes in the same group are seamless, i.e.
    // without visual interruptions such as a black screen.
    int32_t getGroup() const { return mGroup; }

    bool equalsExceptDisplayModeId(const DisplayModePtr& other) const {
        return mHwcId == other->mHwcId && mWidth == other->mWidth && mHeight == other->mHeight &&
                getVsyncPeriod() == other->getVsyncPeriod() && mDpiX == other->mDpiX &&
                mDpiY == other->mDpiY && mGroup == other->mGroup;
    }

private:
    explicit DisplayMode(hal::HWConfigId id) : mHwcId(id) {}

    hal::HWConfigId mHwcId;
    DisplayModeId mId;

    int32_t mWidth = -1;
    int32_t mHeight = -1;
    Fps mFps;
    float mDpiX = -1;
    float mDpiY = -1;
    int32_t mGroup = -1;
};

inline std::string to_string(const DisplayMode& mode) {
    return base::StringPrintf("{id=%d, hwcId=%d, width=%d, height=%d, refreshRate=%s, "
                              "dpiX=%.2f, dpiY=%.2f, group=%d}",
                              mode.getId().value(), mode.getHwcId(), mode.getWidth(),
                              mode.getHeight(), to_string(mode.getFps()).c_str(), mode.getDpiX(),
                              mode.getDpiY(), mode.getGroup());
}

} // namespace android