/* * 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 #include #include #include #include #include #include #include namespace android { namespace hal = android::hardware::graphics::composer::hal; class DisplayMode; using DisplayModePtr = std::shared_ptr; using DisplayModes = std::vector; using DisplayModeId = StrongTyping; class DisplayMode { public: class Builder { public: explicit Builder(hal::HWConfigId id) : mDisplayMode(new DisplayMode(id)) {} DisplayModePtr build() { return std::const_pointer_cast(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 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