/* * 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. */ #ifndef ANDROID_DISPLAY_DEVICE_H #define ANDROID_DISPLAY_DEVICE_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "DisplayHardware/DisplayIdentification.h" #include "RenderArea.h" namespace android { class Fence; class HWComposer; class IGraphicBufferProducer; class Layer; class SurfaceFlinger; struct CompositionInfo; struct DisplayDeviceCreationArgs; struct DisplayInfo; 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; enum { NO_LAYER_STACK = 0xFFFFFFFF, }; explicit DisplayDevice(DisplayDeviceCreationArgs&& args); virtual ~DisplayDevice(); std::shared_ptr getCompositionDisplay() const { return mCompositionDisplay; } bool isVirtual() const { return mIsVirtual; } 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; int getInstallOrientation() const { return mDisplayInstallOrientation; } void setVisibleLayersSortedByZ(const Vector< sp >& layers); const Vector< sp >& getVisibleLayersSortedByZ() const; void setLayersNeedingFences(const Vector< sp >& layers); const Vector< sp >& getLayersNeedingFences() const; void setLayerStack(uint32_t stack); void setDisplaySize(const int newWidth, const int newHeight); void setProjection(int orientation, const Rect& viewport, const Rect& frame); int getOrientation() const { return mOrientation; } static uint32_t getPrimaryDisplayOrientationTransform(); const ui::Transform& getTransform() const; const Rect& getViewport() const; const Rect& getFrame() const; const Rect& getScissor() const; bool needsFiltering() const; uint32_t 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. */ int getPowerMode() const; void setPowerMode(int mode); bool isPoweredOn() const; ui::Dataspace getCompositionDataSpace() const; /* ------------------------------------------------------------------------ * Display active config management. */ int getActiveConfig() const; void setActiveConfig(int 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: /* * Constants, set during initialization */ const sp mFlinger; const wp mDisplayToken; const int32_t mSequenceId; const int mDisplayInstallOrientation; const std::shared_ptr mCompositionDisplay; std::string mDisplayName; const bool mIsVirtual; /* * Can only accessed from the main thread, these members * don't need synchronization. */ // list of visible layers on that display Vector< sp > mVisibleLayersSortedByZ; // list of layers needing fences Vector< sp > mLayersNeedingFences; /* * Transaction state */ static uint32_t displayStateOrientationToTransformOrientation(int orientation); static status_t orientationToTransfrom(int orientation, int w, int h, ui::Transform* tr); int mOrientation; static uint32_t sPrimaryDisplayOrientation; // Current power mode int mPowerMode; // Current active config int mActiveConfig; // TODO(b/74619554): Remove special cases for primary display. const bool mIsPrimary; }; struct DisplayDeviceState { bool isVirtual() const { return !displayId.has_value(); } int32_t sequenceId = sNextSequenceId++; std::optional displayId; sp surface; uint32_t layerStack = DisplayDevice::NO_LAYER_STACK; Rect viewport; Rect frame; uint8_t orientation = 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& flinger, const wp& displayToken, const std::optional& displayId); const sp flinger; const wp displayToken; const std::optional displayId; int32_t sequenceId{0}; bool isVirtual{false}; bool isSecure{false}; sp nativeWindow; sp displaySurface; int displayInstallOrientation{DisplayState::eOrientationDefault}; bool hasWideColorGamut{false}; HdrCapabilities hdrCapabilities; int32_t supportedPerFrameMetadata{0}; std::unordered_map> hwcColorModes; int initialPowerMode{HWC_POWER_MODE_NORMAL}; bool isPrimary{false}; }; class DisplayRenderArea : public RenderArea { public: DisplayRenderArea(const sp device, ui::Transform::orientation_flags rotation = ui::Transform::ROT_0) : DisplayRenderArea(device, device->getBounds(), device->getWidth(), device->getHeight(), device->getCompositionDataSpace(), rotation) {} DisplayRenderArea(const sp device, Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, ui::Dataspace reqDataSpace, ui::Transform::orientation_flags rotation, bool allowSecureLayers = true) : RenderArea(reqWidth, reqHeight, CaptureFill::OPAQUE, reqDataSpace, getDisplayRotation(rotation, device->getInstallOrientation())), mDevice(device), mSourceCrop(sourceCrop), mAllowSecureLayers(allowSecureLayers) {} const ui::Transform& getTransform() const override { return mDevice->getTransform(); } Rect getBounds() const override { return mDevice->getBounds(); } int getHeight() const override { return mDevice->getHeight(); } int getWidth() const override { return mDevice->getWidth(); } bool isSecure() const override { return mAllowSecureLayers && mDevice->isSecure(); } const sp getDisplayDevice() const override { return mDevice; } bool needsFiltering() const override { // check if the projection from the logical display to the physical // display needs filtering if (mDevice->needsFiltering()) { return true; } // check if the projection from the logical render area (i.e., the // physical display) 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 mDevice->getScissor(); } // Recompute the device transformation for the source crop. ui::Transform rotation; ui::Transform translatePhysical; ui::Transform translateLogical; ui::Transform scale; const Rect& viewport = mDevice->getViewport(); const Rect& scissor = mDevice->getScissor(); const Rect& frame = mDevice->getFrame(); const int orientation = mDevice->getInstallOrientation(); // Install orientation is transparent to the callers. Apply it now. uint32_t flags = 0x00; switch (orientation) { case DisplayState::eOrientation90: flags = ui::Transform::ROT_90; break; case DisplayState::eOrientation180: flags = ui::Transform::ROT_180; break; case DisplayState::eOrientation270: flags = ui::Transform::ROT_270; break; default: break; } rotation.set(flags, getWidth(), getHeight()); translateLogical.set(-viewport.left, -viewport.top); translatePhysical.set(scissor.left, scissor.top); scale.set(frame.getWidth() / float(viewport.getWidth()), 0, 0, frame.getHeight() / float(viewport.getHeight())); const ui::Transform finalTransform = rotation * translatePhysical * scale * translateLogical; return finalTransform.transform(mSourceCrop); } private: // Install orientation is transparent to the callers. We need to cancel // it out by modifying rotation flags. static ui::Transform::orientation_flags getDisplayRotation( ui::Transform::orientation_flags rotation, int orientation) { if (orientation == DisplayState::eOrientationDefault) { return rotation; } // convert hw orientation into flag presentation // here inverse transform needed uint8_t hw_rot_90 = 0x00; uint8_t hw_flip_hv = 0x00; switch (orientation) { case DisplayState::eOrientation90: hw_rot_90 = ui::Transform::ROT_90; hw_flip_hv = ui::Transform::ROT_180; break; case DisplayState::eOrientation180: hw_flip_hv = ui::Transform::ROT_180; break; case DisplayState::eOrientation270: hw_rot_90 = ui::Transform::ROT_90; break; } // transform flags operation // 1) flip H V if both have ROT_90 flag // 2) XOR these flags uint8_t rotation_rot_90 = rotation & ui::Transform::ROT_90; uint8_t rotation_flip_hv = rotation & ui::Transform::ROT_180; if (rotation_rot_90 & hw_rot_90) { rotation_flip_hv = (~rotation_flip_hv) & ui::Transform::ROT_180; } return static_cast( (rotation_rot_90 ^ hw_rot_90) | (rotation_flip_hv ^ hw_flip_hv)); } const sp mDevice; const Rect mSourceCrop; const bool mAllowSecureLayers; }; }; // namespace android #endif // ANDROID_DISPLAY_DEVICE_H