/* * Copyright (C) 2007 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "DisplayHardware/DisplayIdentification.h" #include "DisplayHardware/Hal.h" #include "DisplayHardware/PowerAdvisor.h" #include "RenderArea.h" #include "Scheduler/HwcStrongTypes.h" namespace android { class Fence; class HWComposer; class IGraphicBufferProducer; class Layer; class SurfaceFlinger; struct CompositionInfo; struct DisplayDeviceCreationArgs; namespace compositionengine { class Display; class DisplaySurface; } // namespace compositionengine class DisplayDevice : public LightRefBase { public: constexpr static float sDefaultMinLumiance = 0.0; constexpr static float sDefaultMaxLumiance = 500.0; explicit DisplayDevice(DisplayDeviceCreationArgs& args); virtual ~DisplayDevice(); std::shared_ptr getCompositionDisplay() const { return mCompositionDisplay; } std::optional getConnectionType() const { return mConnectionType; } bool isVirtual() const { return !mConnectionType; } bool isPrimary() const { return mIsPrimary; } // isSecure indicates whether this display can be trusted to display // secure surfaces. bool isSecure() const; int getWidth() const; int getHeight() const; ui::Size getSize() const { return {getWidth(), getHeight()}; } void setLayerStack(ui::LayerStack); void setDisplaySize(int width, int height); void setProjection(ui::Rotation orientation, Rect viewport, Rect frame); ui::Rotation getPhysicalOrientation() const { return mPhysicalOrientation; } ui::Rotation getOrientation() const { return mOrientation; } static ui::Transform::RotationFlags getPrimaryDisplayRotationFlags(); ui::Transform::RotationFlags getTransformHint() const { return static_cast(getTransform().getOrientation()); } const ui::Transform& getTransform() const; const Rect& getViewport() const; const Rect& getFrame() const; const Rect& getSourceClip() const; bool needsFiltering() const; ui::LayerStack getLayerStack() const; const std::optional& getId() const; const wp& getDisplayToken() const { return mDisplayToken; } int32_t getSequenceId() const { return mSequenceId; } const Region& getUndefinedRegion() const; int32_t getSupportedPerFrameMetadata() const; bool hasWideColorGamut() const; // Whether h/w composer has native support for specific HDR type. bool hasHDR10PlusSupport() const; bool hasHDR10Support() const; bool hasHLGSupport() const; bool hasDolbyVisionSupport() const; // The returned HdrCapabilities is the combination of HDR capabilities from // hardware composer and RenderEngine. When the DisplayDevice supports wide // color gamut, RenderEngine is able to simulate HDR support in Display P3 // color space for both PQ and HLG HDR contents. The minimum and maximum // luminance will be set to sDefaultMinLumiance and sDefaultMaxLumiance // respectively if hardware composer doesn't return meaningful values. const HdrCapabilities& getHdrCapabilities() const; // Return true if intent is supported by the display. bool hasRenderIntent(ui::RenderIntent intent) const; const Rect& getBounds() const; const Rect& bounds() const { return getBounds(); } void setDisplayName(const std::string& displayName); const std::string& getDisplayName() const { return mDisplayName; } /* ------------------------------------------------------------------------ * Display power mode management. */ hardware::graphics::composer::hal::PowerMode getPowerMode() const; void setPowerMode(hardware::graphics::composer::hal::PowerMode mode); bool isPoweredOn() const; ui::Dataspace getCompositionDataSpace() const; /* ------------------------------------------------------------------------ * Display active config management. */ HwcConfigIndexType getActiveConfig() const; void setActiveConfig(HwcConfigIndexType mode); // release HWC resources (if any) for removable displays void disconnect(); /* ------------------------------------------------------------------------ * Debugging */ uint32_t getPageFlipCount() const; std::string getDebugName() const; void dump(std::string& result) const; private: const sp mFlinger; const wp mDisplayToken; const int32_t mSequenceId; const std::optional mConnectionType; const std::shared_ptr mCompositionDisplay; std::string mDisplayName; const ui::Rotation mPhysicalOrientation; ui::Rotation mOrientation = ui::ROTATION_0; static ui::Transform::RotationFlags sPrimaryDisplayRotationFlags; hardware::graphics::composer::hal::PowerMode mPowerMode = hardware::graphics::composer::hal::PowerMode::OFF; HwcConfigIndexType mActiveConfig; // TODO(b/74619554): Remove special cases for primary display. const bool mIsPrimary; }; struct DisplayDeviceState { struct Physical { DisplayId id; DisplayConnectionType type; hardware::graphics::composer::hal::HWDisplayId hwcDisplayId; bool operator==(const Physical& other) const { return id == other.id && type == other.type && hwcDisplayId == other.hwcDisplayId; } }; bool isVirtual() const { return !physical; } int32_t sequenceId = sNextSequenceId++; std::optional physical; sp surface; ui::LayerStack layerStack = ui::NO_LAYER_STACK; Rect viewport; Rect frame; ui::Rotation orientation = ui::ROTATION_0; uint32_t width = 0; uint32_t height = 0; std::string displayName; bool isSecure = false; private: static std::atomic sNextSequenceId; }; struct DisplayDeviceCreationArgs { // We use a constructor to ensure some of the values are set, without // assuming a default value. DisplayDeviceCreationArgs(const sp&, const wp& displayToken, std::shared_ptr); const sp flinger; const wp displayToken; const std::shared_ptr compositionDisplay; int32_t sequenceId{0}; std::optional connectionType; bool isSecure{false}; sp nativeWindow; sp displaySurface; ui::Rotation physicalOrientation{ui::ROTATION_0}; bool hasWideColorGamut{false}; HdrCapabilities hdrCapabilities; int32_t supportedPerFrameMetadata{0}; std::unordered_map> hwcColorModes; hardware::graphics::composer::hal::PowerMode initialPowerMode{ hardware::graphics::composer::hal::PowerMode::ON}; bool isPrimary{false}; }; class DisplayRenderArea : public RenderArea { public: DisplayRenderArea(const sp& display, RotationFlags rotation = ui::Transform::ROT_0) : DisplayRenderArea(display, display->getBounds(), static_cast(display->getWidth()), static_cast(display->getHeight()), display->getCompositionDataSpace(), rotation) {} DisplayRenderArea(sp display, const Rect& sourceCrop, uint32_t reqWidth, uint32_t reqHeight, ui::Dataspace reqDataSpace, RotationFlags rotation, bool allowSecureLayers = true) : RenderArea(reqWidth, reqHeight, CaptureFill::OPAQUE, reqDataSpace, display->getViewport(), applyDeviceOrientation(rotation, display)), mDisplay(std::move(display)), mSourceCrop(sourceCrop), mAllowSecureLayers(allowSecureLayers) {} const ui::Transform& getTransform() const override { return mTransform; } Rect getBounds() const override { return mDisplay->getBounds(); } int getHeight() const override { return mDisplay->getHeight(); } int getWidth() const override { return mDisplay->getWidth(); } bool isSecure() const override { return mAllowSecureLayers && mDisplay->isSecure(); } sp getDisplayDevice() const override { return mDisplay; } bool needsFiltering() const override { // check if the projection from the logical render area // to the physical render area requires filtering const Rect& sourceCrop = getSourceCrop(); int width = sourceCrop.width(); int height = sourceCrop.height(); if (getRotationFlags() & ui::Transform::ROT_90) { std::swap(width, height); } return width != getReqWidth() || height != getReqHeight(); } Rect getSourceCrop() const override { // use the projected display viewport by default. if (mSourceCrop.isEmpty()) { return mDisplay->getSourceClip(); } // If there is a source crop provided then it is assumed that the device // was in portrait orientation. This may not logically be true, so // correct for the orientation error by undoing the rotation ui::Rotation logicalOrientation = mDisplay->getOrientation(); if (logicalOrientation == ui::Rotation::Rotation90) { logicalOrientation = ui::Rotation::Rotation270; } else if (logicalOrientation == ui::Rotation::Rotation270) { logicalOrientation = ui::Rotation::Rotation90; } const auto flags = ui::Transform::toRotationFlags(logicalOrientation); int width = mDisplay->getSourceClip().getWidth(); int height = mDisplay->getSourceClip().getHeight(); ui::Transform rotation; rotation.set(flags, width, height); return rotation.transform(mSourceCrop); } private: static RotationFlags applyDeviceOrientation(RotationFlags orientationFlag, const sp& device) { uint32_t inverseRotate90 = 0; uint32_t inverseReflect = 0; // Reverse the logical orientation. ui::Rotation logicalOrientation = device->getOrientation(); if (logicalOrientation == ui::Rotation::Rotation90) { logicalOrientation = ui::Rotation::Rotation270; } else if (logicalOrientation == ui::Rotation::Rotation270) { logicalOrientation = ui::Rotation::Rotation90; } const ui::Rotation orientation = device->getPhysicalOrientation() + logicalOrientation; switch (orientation) { case ui::ROTATION_0: return orientationFlag; case ui::ROTATION_90: inverseRotate90 = ui::Transform::ROT_90; inverseReflect = ui::Transform::ROT_180; break; case ui::ROTATION_180: inverseReflect = ui::Transform::ROT_180; break; case ui::ROTATION_270: inverseRotate90 = ui::Transform::ROT_90; break; } const uint32_t rotate90 = orientationFlag & ui::Transform::ROT_90; uint32_t reflect = orientationFlag & ui::Transform::ROT_180; // Apply reflection for double rotation. if (rotate90 & inverseRotate90) { reflect = ~reflect & ui::Transform::ROT_180; } return static_cast((rotate90 ^ inverseRotate90) | (reflect ^ inverseReflect)); } const sp mDisplay; const Rect mSourceCrop; const bool mAllowSecureLayers; const ui::Transform mTransform = ui::Transform(); }; } // namespace android