/* * 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. */ #ifndef ANDROID_HWC_DISPLAY_H #define ANDROID_HWC_DISPLAY_H #include #include #include #include #include #include #include "Common.h" #include "Composer.h" #include "FencedBuffer.h" #include "Layer.h" namespace android { class Composer; class Device; class Display { public: Display(Device& device, Composer* composer, hwc2_display_t id); ~Display(); Display(const Display& display) = delete; Display& operator=(const Display& display) = delete; Display(Display&& display) = delete; Display& operator=(Display&& display) = delete; HWC2::Error init(uint32_t width, uint32_t height, uint32_t dpiX, uint32_t dpiY, uint32_t refreshRateHz, const std::optional>& edid = std::nullopt); HWC2::Error updateParameters(uint32_t width, uint32_t height, uint32_t dpiX, uint32_t dpiY, uint32_t refreshRateHz, const std::optional>& edid = std::nullopt); hwc2_display_t getId() const { return mId; } Layer* getLayer(hwc2_layer_t layerHandle); FencedBuffer& getClientTarget() { return mClientTarget; } buffer_handle_t waitAndGetClientTargetBuffer(); const std::vector& getOrderedLayers() { return mOrderedLayers; } HWC2::Error acceptChanges(); HWC2::Error createLayer(hwc2_layer_t* outLayerId); HWC2::Error destroyLayer(hwc2_layer_t layerId); HWC2::Error getActiveConfig(hwc2_config_t* outConfigId); HWC2::Error getDisplayAttribute(hwc2_config_t configId, int32_t attribute, int32_t* outValue); HWC2::Error getDisplayAttributeEnum(hwc2_config_t configId, HWC2::Attribute attribute, int32_t* outValue); HWC2::Error getChangedCompositionTypes(uint32_t* outNumElements, hwc2_layer_t* outLayers, int32_t* outTypes); HWC2::Error getColorModes(uint32_t* outNumModes, int32_t* outModes); HWC2::Error getConfigs(uint32_t* outNumConfigs, hwc2_config_t* outConfigIds); HWC2::Error getDozeSupport(int32_t* outSupport); HWC2::Error getHdrCapabilities(uint32_t* outNumTypes, int32_t* outTypes, float* outMaxLuminance, float* outMaxAverageLuminance, float* outMinLuminance); HWC2::Error getName(uint32_t* outSize, char* outName); HWC2::Error addReleaseFenceLocked(int32_t fence); HWC2::Error addReleaseLayerLocked(hwc2_layer_t layerId); HWC2::Error getReleaseFences(uint32_t* outNumElements, hwc2_layer_t* outLayers, int32_t* outFences); HWC2::Error clearReleaseFencesAndIdsLocked(); HWC2::Error getRequests(int32_t* outDisplayRequests, uint32_t* outNumElements, hwc2_layer_t* outLayers, int32_t* outLayerRequests); HWC2::Error getType(int32_t* outType); HWC2::Error present(int32_t* outRetireFence); HWC2::Error setActiveConfig(hwc2_config_t configId); HWC2::Error setClientTarget(buffer_handle_t target, int32_t acquireFence, int32_t dataspace, hwc_region_t damage); HWC2::Error setColorMode(int32_t mode); HWC2::Error setColorTransform(const float* matrix, int32_t hint); bool hasColorTransform() const { return mSetColorTransform; } HWC2::Error setOutputBuffer(buffer_handle_t buffer, int32_t releaseFence); HWC2::Error setPowerMode(int32_t mode); HWC2::Error setVsyncEnabled(int32_t enabled); HWC2::Error setVsyncPeriod(uint32_t period); HWC2::Error validate(uint32_t* outNumTypes, uint32_t* outNumRequests); HWC2::Error updateLayerZ(hwc2_layer_t layerId, uint32_t z); HWC2::Error getClientTargetSupport(uint32_t width, uint32_t height, int32_t format, int32_t dataspace); HWC2::Error getDisplayIdentificationData(uint8_t* outPort, uint32_t* outDataSize, uint8_t* outData); HWC2::Error getDisplayCapabilities(uint32_t* outNumCapabilities, uint32_t* outCapabilities); HWC2::Error getDisplayBrightnessSupport(bool* out_support); HWC2::Error setDisplayBrightness(float brightness); void lock() { mStateMutex.lock(); } void unlock() { mStateMutex.unlock(); } private: class Config { public: Config(hwc2_config_t configId) : mId(configId) {} Config(const Config& display) = default; Config& operator=(const Config& display) = default; Config(Config&& display) = default; Config& operator=(Config&& display) = default; hwc2_config_t getId() const { return mId; } void setId(hwc2_config_t id) { mId = id; } int32_t getAttribute(HWC2::Attribute attribute) const; void setAttribute(HWC2::Attribute attribute, int32_t value); std::string toString() const; private: hwc2_config_t mId; std::unordered_map mAttributes; }; // Stores changes requested from the device upon calling prepare(). // Handles change request to: // - Layer composition type. // - Layer hints. class Changes { public: uint32_t getNumTypes() const { return static_cast(mTypeChanges.size()); } uint32_t getNumLayerRequests() const { return static_cast(mLayerRequests.size()); } const std::unordered_map& getTypeChanges() const { return mTypeChanges; } const std::unordered_map& getLayerRequests() const { return mLayerRequests; } void addTypeChange(hwc2_layer_t layerId, HWC2::Composition type) { mTypeChanges.insert({layerId, type}); } void clearTypeChanges() { mTypeChanges.clear(); } void addLayerRequest(hwc2_layer_t layerId, HWC2::LayerRequest request) { mLayerRequests.insert({layerId, request}); } private: std::unordered_map mTypeChanges; std::unordered_map mLayerRequests; }; // Generate sw vsync signal class VsyncThread : public Thread { public: VsyncThread(Display& display) : mDisplay(display) {} virtual ~VsyncThread() {} VsyncThread(const VsyncThread&) = default; VsyncThread& operator=(const VsyncThread&) = default; VsyncThread(VsyncThread&&) = default; VsyncThread& operator=(VsyncThread&&) = default; private: Display& mDisplay; bool threadLoop() final; }; private: // The state of this display should only be modified from // SurfaceFlinger's main loop, with the exception of when dump is // called. To prevent a bad state from crashing us during a dump // call, all public calls into Display must acquire this mutex. mutable std::recursive_mutex mStateMutex; Device& mDevice; Composer* mComposer = nullptr; const hwc2_display_t mId; std::string mName; HWC2::DisplayType mType = HWC2::DisplayType::Physical; HWC2::PowerMode mPowerMode = HWC2::PowerMode::Off; HWC2::Vsync mVsyncEnabled = HWC2::Vsync::Invalid; uint32_t mVsyncPeriod; sp mVsyncThread; FencedBuffer mClientTarget; // Will only be non-null after the Display has been validated and // before it has been presented std::unique_ptr mChanges; std::unordered_map> mLayers; // Ordered layers available after validate(). std::vector mOrderedLayers; std::vector mReleaseLayerIds; std::vector mReleaseFences; std::optional mActiveConfigId; std::unordered_map mConfigs; std::set mColorModes; android_color_mode_t mActiveColorMode; bool mSetColorTransform = false; std::optional> mEdid; }; } // namespace android #endif