blob: f744cc1b7eb844bc5586e09cdd40f31c1d631834 [file] [log] [blame]
/*
* Copyright (C) 2012 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 _EXYNOSDISPLAY_H
#define _EXYNOSDISPLAY_H
#include <android/hardware/graphics/composer/2.4/types.h>
#include <hardware/hwcomposer2.h>
#include <system/graphics.h>
#include <utils/KeyedVector.h>
#include <utils/Vector.h>
#include <atomic>
#include <chrono>
#include <set>
#include "DeconHeader.h"
#include "ExynosDisplayInterface.h"
#include "ExynosHWC.h"
#include "ExynosHWCDebug.h"
#include "ExynosHWCHelper.h"
#include "ExynosHwc3Types.h"
#include "ExynosMPP.h"
#include "ExynosResourceManager.h"
#include "drmeventlistener.h"
#include "worker.h"
#define HWC_CLEARDISPLAY_WITH_COLORMAP
#define HWC_PRINT_FRAME_NUM 10
#define LOW_FPS_THRESHOLD 5
using ::android::hardware::graphics::composer::V2_4::VsyncPeriodNanos;
using namespace std::chrono_literals;
#ifndef SECOND_DISPLAY_START_BIT
#define SECOND_DISPLAY_START_BIT 4
#endif
typedef hwc2_composition_t exynos_composition;
class BrightnessController;
class ExynosLayer;
class ExynosDevice;
class ExynosMPP;
class ExynosMPPSource;
class HistogramController;
namespace aidl {
namespace google {
namespace hardware {
namespace power {
namespace extension {
namespace pixel {
class IPowerExt;
} // namespace pixel
} // namespace extension
} // namespace power
} // namespace hardware
} // namespace google
} // namespace aidl
namespace aidl {
namespace android {
namespace hardware {
namespace power {
class IPower;
class IPowerHintSession;
class WorkDuration;
} // namespace power
} // namespace hardware
} // namespace android
} // namespace aidl
using WorkDuration = aidl::android::hardware::power::WorkDuration;
enum dynamic_recomp_mode {
NO_MODE_SWITCH,
DEVICE_2_CLIENT,
CLIENT_2_DEVICE
};
enum rendering_state {
RENDERING_STATE_NONE = 0,
RENDERING_STATE_VALIDATED,
RENDERING_STATE_ACCEPTED_CHANGE,
RENDERING_STATE_PRESENTED,
RENDERING_STATE_MAX
};
enum composition_type {
COMPOSITION_NONE = 0,
COMPOSITION_CLIENT,
COMPOSITION_EXYNOS,
COMPOSITION_MAX
};
enum {
PSR_NONE = 0,
PSR_DP,
PSR_MIPI,
PSR_MAX,
};
enum {
PANEL_LEGACY = 0,
PANEL_DSC,
PANEL_MIC,
};
enum {
eDisplayNone = 0x0,
ePrimaryDisplay = 0x00000001,
eExternalDisplay = 0x00000002,
eVirtualDisplay = 0x00000004,
};
// served as extension of hwc2_power_mode_t for use with setPowerMode
enum class ext_hwc2_power_mode_t{
PAUSE = 10,
RESUME,
};
enum class PanelGammaSource {
GAMMA_DEFAULT, // Resotre gamma table to default
GAMMA_CALIBRATION, // Update gamma table from calibration file
GAMMA_TYPES,
};
enum class hwc_request_state_t {
SET_CONFIG_STATE_DONE = 0,
SET_CONFIG_STATE_PENDING,
SET_CONFIG_STATE_REQUESTED,
};
enum class RrThrottleRequester : uint32_t {
PIXEL_DISP = 0,
TEST,
LHBM,
BRIGHTNESS,
MAX,
};
enum class DispIdleTimerRequester : uint32_t {
SF = 0,
RR_THROTTLE,
MAX,
};
#define NUM_SKIP_STATIC_LAYER 5
struct ExynosFrameInfo
{
uint32_t srcNum;
exynos_image srcInfo[NUM_SKIP_STATIC_LAYER];
exynos_image dstInfo[NUM_SKIP_STATIC_LAYER];
};
struct exynos_readback_info
{
buffer_handle_t handle = NULL;
/* release sync fence file descriptor,
* which will be signaled when it is safe to write to the output buffer.
*/
int rel_fence = -1;
/* acquire sync fence file descriptor which will signal when the
* buffer provided to setReadbackBuffer has been filled by the device and is
* safe for the client to read.
*/
int acq_fence = -1;
/* Requested from HWCService */
bool requested_from_service = false;
};
struct exynos_win_config_data
{
enum {
WIN_STATE_DISABLED = 0,
WIN_STATE_COLOR,
WIN_STATE_BUFFER,
WIN_STATE_UPDATE,
WIN_STATE_CURSOR,
WIN_STATE_RCD,
} state = WIN_STATE_DISABLED;
uint32_t color = 0;
const ExynosLayer* layer = nullptr;
uint64_t buffer_id = 0;
int fd_idma[3] = {-1, -1, -1};
int acq_fence = -1;
int rel_fence = -1;
float plane_alpha = 1;
int32_t blending = HWC2_BLEND_MODE_NONE;
ExynosMPP* assignedMPP = NULL;
int format = 0;
uint32_t transform = 0;
android_dataspace dataspace = HAL_DATASPACE_UNKNOWN;
bool hdr_enable = false;
enum dpp_comp_src comp_src = DPP_COMP_SRC_NONE;
uint32_t min_luminance = 0;
uint32_t max_luminance = 0;
struct decon_win_rect block_area = { 0, 0, 0, 0};
struct decon_win_rect transparent_area = {0, 0, 0, 0};
struct decon_win_rect opaque_area = {0, 0, 0, 0};
struct decon_frame src = {0, 0, 0, 0, 0, 0};
struct decon_frame dst = {0, 0, 0, 0, 0, 0};
bool protection = false;
CompressionInfo compressionInfo;
bool needColorTransform = false;
void reset(){
*this = {};
};
};
struct exynos_dpu_data
{
int retire_fence = -1;
std::vector<exynos_win_config_data> configs;
std::vector<exynos_win_config_data> rcdConfigs;
bool enable_win_update = false;
std::atomic<bool> enable_readback = false;
struct decon_frame win_update_region = {0, 0, 0, 0, 0, 0};
struct exynos_readback_info readback_info;
void init(size_t configNum, size_t rcdConfigNum) {
configs.resize(configNum);
rcdConfigs.resize(rcdConfigNum);
};
void reset() {
retire_fence = -1;
for (auto& config : configs) config.reset();
for (auto& config : rcdConfigs) config.reset();
/*
* Should not initialize readback_info
* readback_info should be initialized after present
*/
};
exynos_dpu_data& operator =(const exynos_dpu_data &configs_data){
retire_fence = configs_data.retire_fence;
if (configs.size() != configs_data.configs.size()) {
HWC_LOGE(NULL, "invalid config, it has different configs size");
return *this;
}
configs = configs_data.configs;
if (rcdConfigs.size() != configs_data.rcdConfigs.size()) {
HWC_LOGE(NULL, "invalid config, it has different rcdConfigs size");
return *this;
}
rcdConfigs = configs_data.rcdConfigs;
return *this;
};
};
class ExynosLowFpsLayerInfo
{
public:
ExynosLowFpsLayerInfo();
bool mHasLowFpsLayer;
int32_t mFirstIndex;
int32_t mLastIndex;
void initializeInfos();
int32_t addLowFpsLayer(uint32_t layerIndex);
};
class ExynosSortedLayer : public Vector <ExynosLayer*>
{
public:
ssize_t remove(const ExynosLayer *item);
status_t vector_sort();
static int compare(ExynosLayer * const *lhs, ExynosLayer *const *rhs);
};
class DisplayTDMInfo {
public:
/* Could be extended */
typedef struct ResourceAmount {
uint32_t totalAmount;
} ResourceAmount_t;
std::map<tdm_attr_t, ResourceAmount_t> mAmount;
uint32_t initTDMInfo(ResourceAmount_t amount, tdm_attr_t attr) {
mAmount[attr] = amount;
return 0;
}
ResourceAmount_t getAvailableAmount(tdm_attr_t attr) { return mAmount[attr]; }
};
class ExynosCompositionInfo : public ExynosMPPSource {
public:
ExynosCompositionInfo():ExynosCompositionInfo(COMPOSITION_NONE){};
ExynosCompositionInfo(uint32_t type);
uint32_t mType;
bool mHasCompositionLayer;
bool mPrevHasCompositionLayer = false;
int32_t mFirstIndex;
int32_t mLastIndex;
buffer_handle_t mTargetBuffer;
android_dataspace mDataSpace;
int32_t mAcquireFence;
int32_t mReleaseFence;
bool mEnableSkipStatic;
bool mSkipStaticInitFlag;
bool mSkipFlag;
ExynosFrameInfo mSkipSrcInfo;
exynos_win_config_data mLastWinConfigData;
int32_t mWindowIndex;
CompressionInfo mCompressionInfo;
void initializeInfos(ExynosDisplay *display);
void initializeInfosComplete(ExynosDisplay *display);
void setTargetBuffer(ExynosDisplay *display, buffer_handle_t handle,
int32_t acquireFence, android_dataspace dataspace);
void setCompressionType(uint32_t compressionType);
void dump(String8& result) const;
String8 getTypeStr();
};
// Prepare multi-resolution
struct ResolutionSize {
uint32_t w;
uint32_t h;
};
struct ResolutionInfo {
uint32_t nNum;
ResolutionSize nResolution[3];
uint32_t nDSCYSliceSize[3];
uint32_t nDSCXSliceSize[3];
int nPanelType[3];
};
typedef struct FrameIntervalPowerHint {
int frameIntervalNs = 0;
int averageRefreshPeriodNs = 0;
} FrameIntervalPowerHint_t;
typedef struct NotifyExpectedPresentConfig {
int HeadsUpNs = 0;
int TimeoutNs = 0;
} NotifyExpectedPresentConfig_t;
typedef struct VrrConfig {
int minFrameIntervalNs = 0;
std::vector<FrameIntervalPowerHint_t> frameIntervalPowerHint;
NotifyExpectedPresentConfig_t notifyExpectedPresentConfig;
} VrrConfig_t;
typedef struct VrrSettings {
bool enabled;
NotifyExpectedPresentConfig_t notifyExpectedPresentConfig;
std::function<void(int)> configChangeCallback;
} VrrSettings_t;
typedef struct displayConfigs {
// HWC2_ATTRIBUTE_VSYNC_PERIOD
VsyncPeriodNanos vsyncPeriod;
// HWC2_ATTRIBUTE_WIDTH
uint32_t width;
// case HWC2_ATTRIBUTE_HEIGHT
uint32_t height;
// HWC2_ATTRIBUTE_DPI_X
uint32_t Xdpi;
// HWC2_ATTRIBUTE_DPI_Y
uint32_t Ydpi;
// HWC2_ATTRIBUTE_CONFIG_GROUP
uint32_t groupId;
std::optional<VrrConfig_t> vrrConfig;
/* internal use */
bool isOperationRateToBts;
int32_t refreshRate;
} displayConfigs_t;
struct DisplayControl {
/** Composition crop en/disable **/
bool enableCompositionCrop;
/** Resource assignment optimization for exynos composition **/
bool enableExynosCompositionOptimization;
/** Resource assignment optimization for client composition **/
bool enableClientCompositionOptimization;
/** Use G2D as much as possible **/
bool useMaxG2DSrc;
/** Low fps layer optimization **/
bool handleLowFpsLayers;
/** start m2mMPP before persentDisplay **/
bool earlyStartMPP;
/** Adjust display size of the layer having high priority */
bool adjustDisplayFrame;
/** setCursorPosition support **/
bool cursorSupport;
/** readback support **/
bool readbackSupport = false;
/** Reserve MPP regardless of plug state **/
bool forceReserveMPP = false;
/** Skip M2MMPP processing **/
bool skipM2mProcessing = true;
/** Enable multi-thread present **/
bool multiThreadedPresent = false;
};
class ExynosDisplay {
public:
const uint32_t mDisplayId;
const uint32_t mType;
const uint32_t mIndex;
String8 mDeconNodeName;
uint32_t mXres;
uint32_t mYres;
uint32_t mXdpi;
uint32_t mYdpi;
uint32_t mVsyncPeriod;
int32_t mRefreshRate;
int32_t mBtsFrameScanoutPeriod;
int32_t mBtsPendingOperationRatePeriod;
/* Constructor */
ExynosDisplay(uint32_t type, uint32_t index, ExynosDevice* device,
const std::string& displayName);
/* Destructor */
virtual ~ExynosDisplay();
ExynosDevice *mDevice;
const String8 mDisplayName;
const String8 mDisplayTraceName;
HwcMountOrientation mMountOrientation = HwcMountOrientation::ROT_0;
mutable Mutex mDisplayMutex;
/** State variables */
bool mPlugState;
std::optional<hwc2_power_mode_t> mPowerModeState;
hwc2_vsync_t mVsyncState;
bool mHasSingleBuffer;
bool mPauseDisplay = false;
DisplayControl mDisplayControl;
/**
* TODO : Should be defined as ExynosLayer type
* Layer list those sorted by z-order
*/
ExynosSortedLayer mLayers;
std::vector<ExynosLayer*> mIgnoreLayers;
ExynosResourceManager *mResourceManager;
/**
* Layer index, target buffer information for GLES.
*/
ExynosCompositionInfo mClientCompositionInfo;
/**
* Layer index, target buffer information for G2D.
*/
ExynosCompositionInfo mExynosCompositionInfo;
/**
* Geometry change info is described by bit map.
* This flag is cleared when resource assignment for all displays
* is done.
* Geometry changed to layer REFRESH_RATE_INDICATOR will be excluded.
*/
uint64_t mGeometryChanged;
/**
* The number of buffer updates in the current frame.
* Buffer update for layer REFRESH_RATE_INDICATOR will be excluded.
*/
uint32_t mBufferUpdates;
/**
* Rendering step information that is seperated by
* VALIDATED, ACCEPTED_CHANGE, PRESENTED.
*/
rendering_state mRenderingState;
/**
* Rendering step information that is called by client
*/
rendering_state mHWCRenderingState;
/**
* Window total bandwidth by enabled window, It's used as dynamic re-composition enable/disable.
*/
uint32_t mDisplayBW;
/**
* Mode information Dynamic re-composition feature.
* DEVICE_2_CLIENT: All layers are composited by GLES composition.
* CLIENT_2_DEVICE: Device composition.
*/
dynamic_recomp_mode mDynamicReCompMode;
bool mDREnable;
bool mDRDefault;
mutable Mutex mDRMutex;
nsecs_t mLastFpsTime;
uint64_t mFrameCount;
uint64_t mLastFrameCount;
uint64_t mErrorFrameCount;
uint64_t mLastModeSwitchTimeStamp;
uint64_t mLastUpdateTimeStamp;
uint64_t mUpdateEventCnt;
uint64_t mUpdateCallCnt;
/* default DMA for the display */
decon_idma_type mDefaultDMA;
/**
* DECON WIN_CONFIG information.
*/
exynos_dpu_data mDpuData;
/**
* Last win_config data is used as WIN_CONFIG skip decision or debugging.
*/
exynos_dpu_data mLastDpuData;
/**
* Restore release fenc from DECON.
*/
int mLastRetireFence;
bool mUseDpu;
/**
* Max Window number, It should be set by display module(chip)
*/
uint32_t mMaxWindowNum;
uint32_t mWindowNumUsed;
uint32_t mBaseWindowIndex;
// Priority
uint32_t mNumMaxPriorityAllowed;
int32_t mCursorIndex;
int32_t mColorTransformHint;
ExynosLowFpsLayerInfo mLowFpsLayerInfo;
// HDR capabilities
std::vector<int32_t> mHdrTypes;
float mMaxLuminance;
float mMaxAverageLuminance;
float mMinLuminance;
std::unique_ptr<BrightnessController> mBrightnessController;
/* For histogram */
std::unique_ptr<HistogramController> mHistogramController;
/* For debugging */
hwc_display_contents_1_t *mHWC1LayerList;
/* Support Multi-resolution scheme */
int mOldScalerMode;
int mNewScaledWidth;
int mNewScaledHeight;
int32_t mDeviceXres;
int32_t mDeviceYres;
ResolutionInfo mResolutionInfo;
std::map<uint32_t, displayConfigs_t> mDisplayConfigs;
// WCG
android_color_mode_t mColorMode;
// Skip present frame if there was no validate after power on
bool mSkipFrame;
hwc_vsync_period_change_constraints_t mVsyncPeriodChangeConstraints;
hwc_vsync_period_change_timeline_t mVsyncAppliedTimeLine;
hwc_request_state_t mConfigRequestState;
hwc2_config_t mDesiredConfig;
hwc2_config_t mActiveConfig = UINT_MAX;
hwc2_config_t mPendingConfig = UINT_MAX;
int64_t mLastVsyncTimestamp = 0;
void initDisplay();
int getId();
Mutex& getDisplayMutex() {return mDisplayMutex; };
int32_t setCompositionTargetExynosImage(uint32_t targetType, exynos_image *src_img, exynos_image *dst_img);
int32_t initializeValidateInfos();
int32_t addClientCompositionLayer(uint32_t layerIndex);
int32_t removeClientCompositionLayer(uint32_t layerIndex);
bool hasClientComposition();
int32_t addExynosCompositionLayer(uint32_t layerIndex, float totalUsedCapa);
bool isPowerModeOff() const;
bool isSecureContentPresenting() const;
/**
* Dynamic AFBC Control solution : To get the prepared information is applied to current or not.
*/
bool comparePreferedLayers();
/**
* @param *outLayer
*/
int32_t destroyLayer(hwc2_layer_t outLayer);
void destroyLayers();
ExynosLayer *checkLayer(hwc2_layer_t addr);
void checkIgnoreLayers();
virtual void doPreProcessing();
int checkLayerFps();
int switchDynamicReCompMode(dynamic_recomp_mode mode);
int checkDynamicReCompMode();
int handleDynamicReCompMode();
void updateBrightnessState();
/**
* @param compositionType
*/
int skipStaticLayers(ExynosCompositionInfo& compositionInfo);
int handleStaticLayers(ExynosCompositionInfo& compositionInfo);
int doPostProcessing();
int doExynosComposition();
int32_t configureOverlay(ExynosLayer *layer, exynos_win_config_data &cfg);
int32_t configureOverlay(ExynosCompositionInfo &compositionInfo);
int32_t configureHandle(ExynosLayer &layer, int fence_fd, exynos_win_config_data &cfg);
virtual int setWinConfigData();
virtual int setDisplayWinConfigData();
virtual int32_t validateWinConfigData();
virtual int deliverWinConfigData();
virtual int setReleaseFences();
virtual bool checkFrameValidation();
/**
* Display Functions for HWC 2.0
*/
/**
* Descriptor: HWC2_FUNCTION_ACCEPT_DISPLAY_CHANGES
* HWC2_PFN_ACCEPT_DISPLAY_CHANGES
**/
virtual int32_t acceptDisplayChanges();
/**
* Descriptor: HWC2_FUNCTION_CREATE_LAYER
* HWC2_PFN_CREATE_LAYER
*/
virtual int32_t createLayer(hwc2_layer_t* outLayer);
/**
* Descriptor: HWC2_FUNCTION_GET_ACTIVE_CONFIG
* HWC2_PFN_GET_ACTIVE_CONFIG
*/
virtual int32_t getActiveConfig(hwc2_config_t* outConfig);
/**
* Descriptor: HWC2_FUNCTION_GET_CHANGED_COMPOSITION_TYPES
* HWC2_PFN_GET_CHANGED_COMPOSITION_TYPES
*/
virtual int32_t getChangedCompositionTypes(
uint32_t* outNumElements, hwc2_layer_t* outLayers,
int32_t* /*hwc2_composition_t*/ outTypes);
/**
* Descriptor: HWC2_FUNCTION_GET_CLIENT_TARGET_SUPPORT
* HWC2_PFN_GET_CLIENT_TARGET_SUPPORT
*/
virtual int32_t getClientTargetSupport(
uint32_t width, uint32_t height,
int32_t /*android_pixel_format_t*/ format,
int32_t /*android_dataspace_t*/ dataspace);
/**
* Descriptor: HWC2_FUNCTION_GET_COLOR_MODES
* HWC2_PFN_GET_COLOR_MODES
*/
virtual int32_t getColorModes(
uint32_t* outNumModes,
int32_t* /*android_color_mode_t*/ outModes);
/* getDisplayAttribute(..., config, attribute, outValue)
* Descriptor: HWC2_FUNCTION_GET_DISPLAY_ATTRIBUTE
* HWC2_PFN_GET_DISPLAY_ATTRIBUTE
*/
virtual int32_t getDisplayAttribute(
hwc2_config_t config,
int32_t /*hwc2_attribute_t*/ attribute, int32_t* outValue);
/* getDisplayConfigs(..., outNumConfigs, outConfigs)
* Descriptor: HWC2_FUNCTION_GET_DISPLAY_CONFIGS
* HWC2_PFN_GET_DISPLAY_CONFIGS
*/
virtual int32_t getDisplayConfigs(
uint32_t* outNumConfigs,
hwc2_config_t* outConfigs);
/* getDisplayName(..., outSize, outName)
* Descriptor: HWC2_FUNCTION_GET_DISPLAY_NAME
* HWC2_PFN_GET_DISPLAY_NAME
*/
virtual int32_t getDisplayName(uint32_t* outSize, char* outName);
/* getDisplayRequests(..., outDisplayRequests, outNumElements, outLayers,
* outLayerRequests)
* Descriptor: HWC2_FUNCTION_GET_DISPLAY_REQUESTS
* HWC2_PFN_GET_DISPLAY_REQUESTS
*/
virtual int32_t getDisplayRequests(
int32_t* /*hwc2_display_request_t*/ outDisplayRequests,
uint32_t* outNumElements, hwc2_layer_t* outLayers,
int32_t* /*hwc2_layer_request_t*/ outLayerRequests);
/* getDisplayType(..., outType)
* Descriptor: HWC2_FUNCTION_GET_DISPLAY_TYPE
* HWC2_PFN_GET_DISPLAY_TYPE
*/
virtual int32_t getDisplayType(
int32_t* /*hwc2_display_type_t*/ outType);
/* getDozeSupport(..., outSupport)
* Descriptor: HWC2_FUNCTION_GET_DOZE_SUPPORT
* HWC2_PFN_GET_DOZE_SUPPORT
*/
virtual int32_t getDozeSupport(int32_t* outSupport);
/* getReleaseFences(..., outNumElements, outLayers, outFences)
* Descriptor: HWC2_FUNCTION_GET_RELEASE_FENCES
* HWC2_PFN_GET_RELEASE_FENCES
*/
virtual int32_t getReleaseFences(
uint32_t* outNumElements,
hwc2_layer_t* outLayers, int32_t* outFences);
enum {
SKIP_ERR_NONE = 0,
SKIP_ERR_CONFIG_DISABLED,
SKIP_ERR_FIRST_FRAME,
SKIP_ERR_GEOMETRY_CHAGNED,
SKIP_ERR_HAS_CLIENT_COMP,
SKIP_ERR_SKIP_STATIC_CHANGED,
SKIP_ERR_HAS_REQUEST,
SKIP_ERR_DISP_NOT_CONNECTED,
SKIP_ERR_DISP_NOT_POWER_ON,
SKIP_ERR_FORCE_VALIDATE,
SKIP_ERR_INVALID_CLIENT_TARGET_BUFFER
};
virtual int32_t canSkipValidate();
/* presentDisplay(..., outRetireFence)
* Descriptor: HWC2_FUNCTION_PRESENT_DISPLAY
* HWC2_PFN_PRESENT_DISPLAY
*/
virtual int32_t presentDisplay(int32_t* outRetireFence);
virtual int32_t presentPostProcessing();
/* setActiveConfig(..., config)
* Descriptor: HWC2_FUNCTION_SET_ACTIVE_CONFIG
* HWC2_PFN_SET_ACTIVE_CONFIG
*/
virtual int32_t setActiveConfig(hwc2_config_t config);
/* setClientTarget(..., target, acquireFence, dataspace)
* Descriptor: HWC2_FUNCTION_SET_CLIENT_TARGET
* HWC2_PFN_SET_CLIENT_TARGET
*/
virtual int32_t setClientTarget(
buffer_handle_t target,
int32_t acquireFence, int32_t /*android_dataspace_t*/ dataspace);
/* setColorTransform(..., matrix, hint)
* Descriptor: HWC2_FUNCTION_SET_COLOR_TRANSFORM
* HWC2_PFN_SET_COLOR_TRANSFORM
*/
virtual int32_t setColorTransform(
const float* matrix,
int32_t /*android_color_transform_t*/ hint);
/* setColorMode(..., mode)
* Descriptor: HWC2_FUNCTION_SET_COLOR_MODE
* HWC2_PFN_SET_COLOR_MODE
*/
virtual int32_t setColorMode(
int32_t /*android_color_mode_t*/ mode);
/* setOutputBuffer(..., buffer, releaseFence)
* Descriptor: HWC2_FUNCTION_SET_OUTPUT_BUFFER
* HWC2_PFN_SET_OUTPUT_BUFFER
*/
virtual int32_t setOutputBuffer(
buffer_handle_t buffer,
int32_t releaseFence);
virtual int clearDisplay(bool needModeClear = false);
/* setPowerMode(..., mode)
* Descriptor: HWC2_FUNCTION_SET_POWER_MODE
* HWC2_PFN_SET_POWER_MODE
*/
virtual int32_t setPowerMode(
int32_t /*hwc2_power_mode_t*/ mode);
/* setVsyncEnabled(..., enabled)
* Descriptor: HWC2_FUNCTION_SET_VSYNC_ENABLED
* HWC2_PFN_SET_VSYNC_ENABLED
*/
virtual int32_t setVsyncEnabled(
int32_t /*hwc2_vsync_t*/ enabled);
int32_t setVsyncEnabledInternal(
int32_t /*hwc2_vsync_t*/ enabled);
/* validateDisplay(..., outNumTypes, outNumRequests)
* Descriptor: HWC2_FUNCTION_VALIDATE_DISPLAY
* HWC2_PFN_VALIDATE_DISPLAY
*/
virtual int32_t validateDisplay(
uint32_t* outNumTypes, uint32_t* outNumRequests);
/* getHdrCapabilities(..., outNumTypes, outTypes, outMaxLuminance,
* outMaxAverageLuminance, outMinLuminance)
* Descriptor: HWC2_FUNCTION_GET_HDR_CAPABILITIES
*/
virtual int32_t getHdrCapabilities(uint32_t* outNumTypes, int32_t* /*android_hdr_t*/ outTypes, float* outMaxLuminance,
float* outMaxAverageLuminance, float* outMinLuminance);
virtual int32_t getRenderIntents(int32_t mode, uint32_t* outNumIntents,
int32_t* /*android_render_intent_v1_1_t*/ outIntents);
virtual int32_t setColorModeWithRenderIntent(int32_t /*android_color_mode_t*/ mode,
int32_t /*android_render_intent_v1_1_t */ intent);
/* HWC 2.3 APIs */
/* getDisplayIdentificationData(..., outPort, outDataSize, outData)
* Descriptor: HWC2_FUNCTION_GET_DISPLAY_IDENTIFICATION_DATA
* Parameters:
* outPort - the connector to which the display is connected;
* pointer will be non-NULL
* outDataSize - if outData is NULL, the size in bytes of the data which would
* have been returned; if outData is not NULL, the size of outData, which
* must not exceed the value stored in outDataSize prior to the call;
* pointer will be non-NULL
* outData - the EDID 1.3 blob identifying the display
*
* Returns HWC2_ERROR_NONE or one of the following errors:
* HWC2_ERROR_BAD_DISPLAY - an invalid display handle was passed in
*/
int32_t getDisplayIdentificationData(uint8_t* outPort,
uint32_t* outDataSize, uint8_t* outData);
/* getDisplayCapabilities(..., outCapabilities)
* Descriptor: HWC2_FUNCTION_GET_DISPLAY_CAPABILITIES
* Parameters:
* outNumCapabilities - if outCapabilities was nullptr, returns the number of capabilities
* if outCapabilities was not nullptr, returns the number of capabilities stored in
* outCapabilities, which must not exceed the value stored in outNumCapabilities prior
* to the call; pointer will be non-NULL
* outCapabilities - a list of supported capabilities.
*
* Returns HWC2_ERROR_NONE or one of the following errors:
* HWC2_ERROR_BAD_DISPLAY - an invalid display handle was passed in
*/
/* Capabilities
Invalid = HWC2_CAPABILITY_INVALID,
SidebandStream = HWC2_CAPABILITY_SIDEBAND_STREAM,
SkipClientColorTransform = HWC2_CAPABILITY_SKIP_CLIENT_COLOR_TRANSFORM,
PresentFenceIsNotReliable = HWC2_CAPABILITY_PRESENT_FENCE_IS_NOT_RELIABLE,
SkipValidate = HWC2_CAPABILITY_SKIP_VALIDATE,
*/
int32_t getDisplayCapabilities(uint32_t* outNumCapabilities,
uint32_t* outCapabilities);
/* getDisplayBrightnessSupport(displayToken)
* Descriptor: HWC2_FUNCTION_GET_DISPLAY_BRIGHTNESS_SUPPORT
* Parameters:
* outSupport - whether the display supports operations.
*
* Returns HWC2_ERROR_NONE or one of the following errors:
* HWC2_ERROR_BAD_DISPLAY when the display is invalid.
*/
int32_t getDisplayBrightnessSupport(bool* outSupport);
/* setDisplayBrightness(displayToken, brightnesss, waitPresent)
* Descriptor: HWC2_FUNCTION_SET_DISPLAY_BRIGHTNESS
* Parameters:
* brightness - a number between 0.0f (minimum brightness) and 1.0f (maximum brightness), or
* -1.0f to turn the backlight off.
* waitPresent - apply this brightness change at next Present time.
*
* Returns HWC2_ERROR_NONE or one of the following errors:
* HWC2_ERROR_BAD_DISPLAY when the display is invalid, or
* HWC2_ERROR_UNSUPPORTED when brightness operations are not supported, or
* HWC2_ERROR_BAD_PARAMETER when the brightness is invalid, or
* HWC2_ERROR_NO_RESOURCES when the brightness cannot be applied.
*/
virtual int32_t setDisplayBrightness(float brightness, bool waitPresent = false);
/* getDisplayConnectionType(..., outType)
* Descriptor: HWC2_FUNCTION_GET_DISPLAY_CONNECTION_TYPE
* Optional for all HWC2 devices
*
* Returns whether the given physical display is internal or external.
*
* Parameters:
* outType - the connection type of the display; pointer will be non-NULL
*
* Returns HWC2_ERROR_NONE or one of the following errors:
* HWC2_ERROR_BAD_DISPLAY when the display is invalid or virtual.
*/
int32_t getDisplayConnectionType(uint32_t* outType);
/* getDisplayVsyncPeriod(..., outVsyncPeriods)
* Descriptor: HWC2_FUNCTION_GET_DISPLAY_VSYNC_PERIOD
* Required for HWC2 devices for composer 2.4
*
* Retrieves which vsync period the display is currently using.
*
* If no display configuration is currently active, this function must
* return BAD_CONFIG. If a vsync period is about to change due to a
* setActiveConfigWithConstraints call, this function must return the current vsync period
* until the change has taken place.
*
* Parameters:
* outVsyncPeriod - the current vsync period of the display.
*
* Returns HWC2_ERROR_NONE or one of the following errors:
* HWC2_ERROR_BAD_DISPLAY - an invalid display handle was passed in
* HWC2_ERROR_BAD_CONFIG - no configuration is currently active
*/
int32_t getDisplayVsyncPeriod(hwc2_vsync_period_t* __unused outVsyncPeriod);
/* setActiveConfigWithConstraints(...,
* config,
* vsyncPeriodChangeConstraints,
* outTimeline)
* Descriptor: HWC2_FUNCTION_SET_ACTIVE_CONFIG_WITH_CONSTRAINTS
* Required for HWC2 devices for composer 2.4
*
* Sets the active configuration and the refresh rate for this display.
* If the new config shares the same config group as the current config,
* only the vsync period shall change.
* Upon returning, the given display configuration, except vsync period, must be active and
* remain so until either this function is called again or the display is disconnected.
* When the display starts to refresh at the new vsync period, onVsync_2_4 callback must be
* called with the new vsync period.
*
* Parameters:
* config - the new display configuration.
* vsyncPeriodChangeConstraints - constraints required for changing vsync period:
* desiredTimeNanos - the time in CLOCK_MONOTONIC after
* which the vsync period may change
* (i.e., the vsync period must not change
* before this time).
* seamlessRequired - if true, requires that the vsync period
* change must happen seamlessly without
* a noticeable visual artifact.
* When the conditions change and it may be
* possible to change the vsync period
* seamlessly, HWC2_CALLBACK_SEAMLESS_POSSIBLE
* callback must be called to indicate that
* caller should retry.
* outTimeline - the timeline for the vsync period change.
*
* Returns HWC2_ERROR_NONE or one of the following errors:
* HWC2_ERROR_BAD_DISPLAY - an invalid display handle was passed in.
* HWC2_ERROR_BAD_CONFIG - an invalid configuration handle passed in.
* HWC2_ERROR_SEAMLESS_NOT_ALLOWED - when seamlessRequired was true but config provided doesn't
* share the same config group as the current config.
* HWC2_ERROR_SEAMLESS_NOT_POSSIBLE - when seamlessRequired was true but the display cannot
* achieve the vsync period change without a noticeable
* visual artifact.
*/
int32_t setActiveConfigWithConstraints(hwc2_config_t __unused config,
hwc_vsync_period_change_constraints_t* __unused vsyncPeriodChangeConstraints,
hwc_vsync_period_change_timeline_t* __unused outTimeline);
/**
* setBootDisplayConfig(..., config)
* Descriptor: HWC2_FUNCTION_SET_BOOT_DISPLAY_CONFIG
* Optional for HWC2 devices
*
* Sets the display config in which the device boots.
* If the device is unable to boot in this config for any reason (example HDMI display
* changed), the implementation should try to find a config which matches the resolution
* and refresh-rate of this config. If no such config exists, the implementation's
* preferred display config should be used.
*
* See also:
* getPreferredBootDisplayConfig
*
* Parameters:
* config - is the new boot time config for the display.
*
* Returns HWC2_ERROR_NONE or one of the following errors:
* HWC2_ERROR_BAD_DISPLAY - when the display is invalid
* HWC2_ERROR_BAD_CONFIG - when the configuration is invalid
* HWC2_ERROR_UNSUPPORTED - when the display does not support boot display config
*/
virtual int32_t setBootDisplayConfig(int32_t config);
/**
* clearBootDisplayConfig(...)
* Descriptor: HWC2_FUNCTION_CLEAR_BOOT_DISPLAY_CONFIG
* Optional for HWC2 devices
*
* Clears the boot display config.
* The device should boot in the implementation's preferred display config.
*
* Returns HWC2_ERROR_NONE or one of the following errors:
* HWC2_ERROR_BAD_DISPLAY - when the display is invalid
* HWC2_ERROR_UNSUPPORTED - when the display does not support boot display config
*/
virtual int32_t clearBootDisplayConfig();
/**
* getPreferredBootDisplayConfig(..., config*)
* Descriptor: HWC2_FUNCTION_GET_PREFERRED_DISPLAY_CONFIG
* Optional for HWC2 devices
*
* Returns the implementation's preferred display config.
* This is display config used by the implementation at boot time, if the boot
* display config has not been requested yet, or if it has been previously cleared.
*
* See also:
* setBootDisplayConfig
*
* Parameters:
* outConfig - is the implementation's preferred display config
*
* Returns HWC2_ERROR_NONE or one of the following errors:
* HWC2_ERROR_BAD_DISPLAY - when the display is invalid
* HWC2_ERROR_BAD_CONFIG - when the configuration is invalid
* HWC2_ERROR_UNSUPPORTED - when the display does not support boot display config
*/
int32_t getPreferredBootDisplayConfig(int32_t* outConfig);
virtual int32_t getPreferredDisplayConfigInternal(int32_t* outConfig);
/* setAutoLowLatencyMode(displayToken, on)
* Descriptor: HWC2_FUNCTION_SET_AUTO_LOW_LATENCY_MODE
* Optional for HWC2 devices
*
* setAutoLowLatencyMode requests that the display goes into low latency mode. If the display
* is connected via HDMI 2.1, then Auto Low Latency Mode should be triggered. If the display is
* internally connected, then a custom low latency mode should be triggered (if available).
*
* Parameters:
* on - indicates whether to turn low latency mode on (=true) or off (=false)
*
* Returns HWC2_ERROR_NONE or one of the following errors:
* HWC2_ERROR_BAD_DISPLAY - when the display is invalid, or
* HWC2_ERROR_UNSUPPORTED - when the display does not support any low latency mode
*/
int32_t setAutoLowLatencyMode(bool __unused on);
/* getSupportedContentTypes(..., outSupportedContentTypes)
* Descriptor: HWC2_FUNCTION_GET_SUPPORTED_CONTENT_TYPES
* Optional for HWC2 devices
*
* getSupportedContentTypes returns a list of supported content types
* (as described in the definition of ContentType above).
* This list must not change after initialization.
*
* Parameters:
* outNumSupportedContentTypes - if outSupportedContentTypes was nullptr, returns the number
* of supported content types; if outSupportedContentTypes was not nullptr, returns the
* number of capabilities stored in outSupportedContentTypes, which must not exceed the
* value stored in outNumSupportedContentTypes prior to the call; pointer will be non-NULL
* outSupportedContentTypes - a list of supported content types.
*
* Returns HWC2_ERROR_NONE or one of the following errors:
* HWC2_ERROR_BAD_DISPLAY - an invalid display handle was passed in
*/
int32_t getSupportedContentTypes(uint32_t* __unused outNumSupportedContentTypes,
uint32_t* __unused outSupportedContentTypes);
/* setContentType(displayToken, contentType)
* Descriptor: HWC2_FUNCTION_SET_CONTENT_TYPE
* Optional for HWC2 devices
*
* setContentType instructs the display that the content being shown is of the given contentType
* (one of GRAPHICS, PHOTO, CINEMA, GAME).
*
* According to the HDMI 1.4 specification, supporting all content types is optional. Whether
* the display supports a given content type is reported by getSupportedContentTypes.
*
* Parameters:
* contentType - the type of content that is currently being shown on the display
*
* Returns HWC2_ERROR_NONE or one of the following errors:
* HWC2_ERROR_BAD_DISPLAY - when the display is invalid, or
* HWC2_ERROR_UNSUPPORTED - when the given content type is a valid content type, but is not
* supported on this display, or
* HWC2_ERROR_BAD_PARAMETER - when the given content type is invalid
*/
int32_t setContentType(int32_t /* hwc2_content_type_t */ __unused contentType);
/* getClientTargetProperty(..., outClientTargetProperty)
* Descriptor: HWC2_FUNCTION_GET_CLIENT_TARGET_PROPERTY
* Optional for HWC2 devices
*
* Retrieves the client target properties for which the hardware composer
* requests after the last call to validateDisplay. The client must set the
* properties of the client target to match the returned values.
* When this API is implemented, if client composition is needed, the hardware
* composer must return meaningful client target property with dataspace not
* setting to UNKNOWN.
* When the returned dataspace is set to UNKNOWN, it means hardware composer
* requests nothing, the client must ignore the returned client target property
* structrue.
*
* Parameters:
* outClientTargetProperty - the client target properties that hardware
* composer requests. If dataspace field is set to UNKNOWN, it means
* the hardware composer requests nothing, the client must ignore the
* returned client target property structure.
* outDimmingStage - where should the SDR dimming happen. HWC3 only.
* Returns HWC2_ERROR_NONE or one of the following errors:
* HWC2_ERROR_BAD_DISPLAY - an invalid display handle was passed in
* HWC2_ERROR_NOT_VALIDATED - validateDisplay has not been called for this
* display
*/
virtual int32_t getClientTargetProperty(
hwc_client_target_property_t* outClientTargetProperty,
HwcDimmingStage *outDimmingStage = nullptr);
/*
* HWC3
*
* Execute any pending brightness changes.
*/
int32_t flushDisplayBrightnessChange();
/*
* HWC3
*
* Get display mount orientation.
*
*/
int32_t getMountOrientation(HwcMountOrientation *orientation);
/*
* HWC3
*
* Retrieve the vrrConfig for the corresponding display configuration.
* If the configuration doesn't exist, return a nullptr.
*
*/
std::optional<VrrConfig_t> getVrrConfigs(hwc2_config_t config);
/* setActiveConfig MISCs */
bool isBadConfig(hwc2_config_t config);
bool needNotChangeConfig(hwc2_config_t config);
int32_t updateInternalDisplayConfigVariables(
hwc2_config_t config, bool updateVsync = true);
int32_t resetConfigRequestStateLocked(hwc2_config_t config);
int32_t updateConfigRequestAppliedTime();
int32_t updateVsyncAppliedTimeLine(int64_t actualChangeTime);
int32_t getDisplayVsyncPeriodInternal(
hwc2_vsync_period_t* outVsyncPeriod);
virtual int32_t doDisplayConfigInternal(hwc2_config_t config);
int32_t doDisplayConfigPostProcess(ExynosDevice *dev);
int32_t getConfigAppliedTime(const uint64_t desiredTime,
const uint64_t actualChangeTime,
int64_t &appliedTime, int64_t &refreshTime);
void updateBtsFrameScanoutPeriod(int32_t frameScanoutPeriod, bool configApplied = false);
void tryUpdateBtsFromOperationRate(bool beforeValidateDisplay);
uint32_t getBtsRefreshRate() const;
virtual void checkBtsReassignResource(const int32_t __unused vsyncPeriod,
const int32_t __unused btsVsyncPeriod) {}
/* TODO : TBD */
int32_t setCursorPositionAsync(uint32_t x_pos, uint32_t y_pos);
int32_t getReadbackBufferAttributes(int32_t* /*android_pixel_format_t*/ outFormat,
int32_t* /*android_dataspace_t*/ outDataspace);
int32_t setReadbackBuffer(buffer_handle_t buffer, int32_t releaseFence, bool requestedService = false);
void setReadbackBufferInternal(buffer_handle_t buffer, int32_t releaseFence, bool requestedService = false);
int32_t getReadbackBufferFence(int32_t* outFence);
/* This function is called by ExynosDisplayInterface class to set acquire fence*/
int32_t setReadbackBufferAcqFence(int32_t acqFence);
virtual void dump(String8& result);
virtual int32_t startPostProcessing();
void dumpConfig(const exynos_win_config_data &c);
void dumpConfig(String8 &result, const exynos_win_config_data &c);
void printConfig(exynos_win_config_data &c);
unsigned int getLayerRegion(ExynosLayer *layer,
hwc_rect *rect_area, uint32_t regionType);
int handleWindowUpdate();
bool windowUpdateExceptions();
/* For debugging */
void setHWC1LayerList(hwc_display_contents_1_t *contents) {mHWC1LayerList = contents;};
void traceLayerTypes();
bool validateExynosCompositionLayer();
void printDebugInfos(String8 &reason);
bool checkConfigChanged(const exynos_dpu_data &lastConfigsData,
const exynos_dpu_data &newConfigsData);
int checkConfigDstChanged(const exynos_dpu_data &lastConfigData,
const exynos_dpu_data &newConfigData, uint32_t index);
uint32_t getRestrictionIndex(int halFormat);
void closeFences();
void closeFencesForSkipFrame(rendering_state renderingState);
int32_t getLayerCompositionTypeForValidationType(uint32_t layerIndex);
void setHWCControl(uint32_t ctrl, int32_t val);
void setGeometryChanged(uint64_t changedBit);
void clearGeometryChanged();
virtual void setDDIScalerEnable(int width, int height);
virtual int getDDIScalerMode(int width, int height);
void increaseMPPDstBufIndex();
virtual void initDisplayInterface(uint32_t interfaceType);
virtual int32_t updateColorConversionInfo() { return NO_ERROR; };
virtual int32_t resetColorMappingInfo(ExynosMPPSource* /*mppSrc*/) { return NO_ERROR; }
virtual int32_t updatePresentColorConversionInfo() { return NO_ERROR; };
virtual bool checkRrCompensationEnabled() { return false; };
virtual bool isColorCalibratedByDevice() { return false; };
virtual int32_t getColorAdjustedDbv(uint32_t &) { return NO_ERROR; }
virtual int32_t SetCurrentPanelGammaSource(const displaycolor::DisplayType /* type */,
const PanelGammaSource& /* source */) {
return HWC2_ERROR_UNSUPPORTED;
}
virtual PanelGammaSource GetCurrentPanelGammaSource() const {
return PanelGammaSource::GAMMA_DEFAULT;
}
virtual void initLbe(){};
virtual bool isLbeSupported() { return false; }
virtual void setLbeState(LbeState __unused state) {}
virtual void setLbeAmbientLight(int __unused value) {}
virtual LbeState getLbeState() { return LbeState::OFF; }
int32_t checkPowerHalExtHintSupport(const std::string& mode);
virtual bool isLhbmSupported() { return false; }
virtual int32_t setLhbmState(bool __unused enabled) { return NO_ERROR; }
virtual bool getLhbmState() { return false; };
virtual void setEarlyWakeupDisplay() {}
virtual void setExpectedPresentTime(uint64_t __unused timestamp,
int __unused frameIntervalNs) {}
virtual uint64_t getPendingExpectedPresentTime() { return 0; }
virtual int getPendingFrameInterval() { return 0; }
virtual void applyExpectedPresentTime() {}
virtual int32_t getDisplayIdleTimerSupport(bool& outSupport);
virtual int32_t getDisplayMultiThreadedPresentSupport(bool& outSupport);
virtual int32_t setDisplayIdleTimer(const int32_t __unused timeoutMs) {
return HWC2_ERROR_UNSUPPORTED;
}
virtual void handleDisplayIdleEnter(const uint32_t __unused idleTeRefreshRate) {}
virtual PanelCalibrationStatus getPanelCalibrationStatus() {
return PanelCalibrationStatus::UNCALIBRATED;
}
virtual bool isDbmSupported() { return false; }
virtual int32_t setDbmState(bool __unused enabled) { return NO_ERROR; }
/* getDisplayPreAssignBit support mIndex up to 1.
It supports only dual LCD and 2 external displays */
inline uint32_t getDisplayPreAssignBit() {
uint32_t type = SECOND_DISPLAY_START_BIT * mIndex + mType;
return 1 << type;
}
void cleanupAfterClientDeath();
int32_t getRCDLayerSupport(bool& outSupport) const;
int32_t setDebugRCDLayerEnabled(bool enable);
/* ignore / accept brightness update requests */
virtual int32_t ignoreBrightnessUpdateRequests(bool ignore);
/* set brightness to specific nits value */
virtual int32_t setBrightnessNits(const float nits);
/* set brightness by dbv value */
virtual int32_t setBrightnessDbv(const uint32_t dbv);
virtual std::string getPanelSysfsPath() const { return std::string(); }
virtual void onVsync(int64_t __unused timestamp) { return; };
protected:
virtual bool getHDRException(ExynosLayer *layer);
virtual int32_t getActiveConfigInternal(hwc2_config_t* outConfig);
virtual int32_t setActiveConfigInternal(hwc2_config_t config, bool force);
void updateRefreshRateHint();
bool isFullScreenComposition();
public:
/**
* This will be initialized with differnt class
* that inherits ExynosDisplayInterface according to
* interface type.
*/
std::unique_ptr<ExynosDisplayInterface> mDisplayInterface;
void requestLhbm(bool on);
virtual int setMinIdleRefreshRate(const int __unused fps,
const RrThrottleRequester __unused requester) {
return NO_ERROR;
}
virtual int setRefreshRateThrottleNanos(const int64_t __unused delayNanos,
const RrThrottleRequester __unused requester) {
return NO_ERROR;
}
virtual void updateAppliedActiveConfig(const hwc2_config_t /*newConfig*/,
const int64_t /*ts*/) {}
virtual bool isConfigSettingEnabled() { return true; }
virtual void enableConfigSetting(bool /*en*/) {}
// is the hint session both enabled and supported
bool usePowerHintSession();
void setPeakRefreshRate(float rr) { mPeakRefreshRate = rr; }
uint32_t getPeakRefreshRate();
VsyncPeriodNanos getVsyncPeriod(const int32_t config);
uint32_t getRefreshRate(const int32_t config);
uint32_t getConfigId(const int32_t refreshRate, const int32_t width, const int32_t height);
// check if there are any dimmed layers
bool isMixedComposition();
bool isPriorFrameMixedCompostion() { return mPriorFrameMixedComposition; }
int lookupDisplayConfigs(const int32_t& width,
const int32_t& height,
const int32_t& fps,
const int32_t& vsyncRate,
int32_t* outConfig);
private:
bool skipStaticLayerChanged(ExynosCompositionInfo& compositionInfo);
bool shouldSignalNonIdle();
/// minimum possible dim rate in the case hbm peak is 1000 nits and norml
// display brightness is 2 nits
static constexpr float kGhbmMinDimRatio = 0.002;
/// consider HDR as full screen playback when its frame coverage
//exceeds this threshold.
static constexpr float kHdrFullScreen = 0.5;
uint32_t mHdrFullScrenAreaThreshold;
// peak refresh rate
float mPeakRefreshRate = -1.0f;
// track if the last frame is a mixed composition, to detect mixed
// composition to non-mixed composition transition.
bool mPriorFrameMixedComposition;
/* Display hint to notify power hal */
class PowerHalHintWorker : public Worker {
public:
PowerHalHintWorker(uint32_t displayId, const String8& displayTraceName);
virtual ~PowerHalHintWorker();
int Init();
void signalRefreshRate(hwc2_power_mode_t powerMode, int32_t refreshRate);
void signalNonIdle();
void signalActualWorkDuration(nsecs_t actualDurationNanos);
void signalTargetWorkDuration(nsecs_t targetDurationNanos);
void addBinderTid(pid_t tid);
void removeBinderTid(pid_t tid);
bool signalStartHintSession();
void trackThisThread();
// is the hint session both enabled and supported
bool usePowerHintSession();
// is it known if the hint session is enabled + supported yet
bool checkPowerHintSessionReady();
protected:
void Routine() override;
private:
static void BinderDiedCallback(void*);
int32_t connectPowerHal();
int32_t connectPowerHalExt();
int32_t checkPowerHalExtHintSupport(const std::string& mode);
int32_t sendPowerHalExtHint(const std::string& mode, bool enabled);
int32_t checkRefreshRateHintSupport(const int32_t refreshRate);
int32_t updateRefreshRateHintInternal(const hwc2_power_mode_t powerMode,
const int32_t refreshRate);
int32_t sendRefreshRateHint(const int32_t refreshRate, bool enabled);
void forceUpdateHints();
int32_t checkIdleHintSupport();
int32_t updateIdleHint(const int64_t deadlineTime, const bool forceUpdate);
bool needUpdateIdleHintLocked(int64_t& timeout) REQUIRES(mutex_);
// for adpf cpu hints
int32_t sendActualWorkDuration();
int32_t updateTargetWorkDuration();
// Update checking methods
bool needUpdateTargetWorkDurationLocked() REQUIRES(mutex_);
bool needSendActualWorkDurationLocked() REQUIRES(mutex_);
// is it known if the hint session is enabled + supported yet
bool checkPowerHintSessionReadyLocked();
// Hint session lifecycle management
int32_t startHintSession();
int32_t checkPowerHintSessionSupport();
bool mNeedUpdateRefreshRateHint;
// The last refresh rate hint that is still being enabled
// If all refresh rate hints are disabled, then mLastRefreshRateHint = 0
int mLastRefreshRateHint;
// support list of refresh rate hints
std::map<int32_t, bool> mRefreshRateHintSupportMap;
bool mIdleHintIsEnabled;
bool mForceUpdateIdleHint;
int64_t mIdleHintDeadlineTime;
// whether idle hint support is checked
bool mIdleHintSupportIsChecked;
// whether idle hint is supported
bool mIdleHintIsSupported;
String8 mDisplayTraceName;
std::string mIdleHintStr;
std::string mRefreshRateHintPrefixStr;
hwc2_power_mode_t mPowerModeState;
int32_t mRefreshRate;
uint32_t mConnectRetryCount;
bool isPowerHalExist() { return mConnectRetryCount < 10; }
ndk::ScopedAIBinder_DeathRecipient mDeathRecipient;
// for power HAL extension hints
std::shared_ptr<aidl::google::hardware::power::extension::pixel::IPowerExt>
mPowerHalExtAidl;
// for normal power HAL hints
std::shared_ptr<aidl::android::hardware::power::IPower> mPowerHalAidl;
// Max amount the error term can vary without causing an actual value report,
// as well as the target durations if not normalized
static constexpr const std::chrono::nanoseconds kAllowedDeviation = 300us;
// Target value used for initialization and normalization,
// the actual value does not really matter
static constexpr const std::chrono::nanoseconds kDefaultTarget = 50ms;
// Whether to normalize all the actual values as error terms relative to a constant
// target. This saves a binder call by not setting the target
static const bool sNormalizeTarget;
// Whether we should emit ATRACE_INT data for hint sessions
static const bool sTraceHintSessionData;
// Whether we use or disable the rate limiter for target and actual values
static const bool sUseRateLimiter;
std::shared_ptr<aidl::android::hardware::power::IPowerHintSession> mPowerHintSession;
// queue of actual durations waiting to be reported
std::vector<WorkDuration> mPowerHintQueue;
// display-specific binder thread tids
std::set<pid_t> mBinderTids;
// indicates that the tid list has changed, so the session must be rebuilt
bool mTidsUpdated = false;
static std::mutex sSharedDisplayMutex;
struct SharedDisplayData {
std::optional<bool> hintSessionEnabled;
std::optional<int32_t> hintSessionSupported;
};
// caches the output of usePowerHintSession to avoid sSharedDisplayMutex
std::atomic<std::optional<bool>> mUsePowerHintSession{std::nullopt};
// this lets us know if we can skip calling checkPowerHintSessionSupport
bool mHintSessionSupportChecked = false;
// used to indicate to all displays whether hint sessions are enabled/supported
static SharedDisplayData sSharedDisplayData GUARDED_BY(sSharedDisplayMutex);
// latest target that was signalled
nsecs_t mTargetWorkDuration = kDefaultTarget.count();
// last target duration reported to PowerHAL
nsecs_t mLastTargetDurationReported = kDefaultTarget.count();
// latest actual duration signalled
std::optional<nsecs_t> mActualWorkDuration;
// last error term reported to PowerHAL, used for rate limiting
std::optional<nsecs_t> mLastErrorSent;
// timestamp of the last report we sent, used to avoid stale sessions
nsecs_t mLastActualReportTimestamp = 0;
// amount of time after the last message was sent before the session goes stale
// actually 100ms but we use 80 here to ideally avoid going stale
static constexpr const std::chrono::nanoseconds kStaleTimeout = 80ms;
// An adjustable safety margin which moves the "target" earlier to allow flinger to
// go a bit over without dropping a frame, especially since we can't measure
// the exact time HWC finishes composition so "actual" durations are measured
// from the end of present() instead, which is a bit later.
static constexpr const std::chrono::nanoseconds kTargetSafetyMargin = 2ms;
};
// union here permits use as a key in the unordered_map without a custom hash
union AveragesKey {
struct {
uint16_t layers;
bool validated;
bool beforeReleaseFence;
};
uint32_t value;
AveragesKey(size_t layers, bool validated, bool beforeReleaseFence)
: layers(static_cast<uint16_t>(layers)),
validated(validated),
beforeReleaseFence(beforeReleaseFence) {}
operator uint32_t() const { return value; }
};
static const constexpr int kAveragesBufferSize = 3;
static const constexpr nsecs_t SIGNAL_TIME_PENDING = INT64_MAX;
static const constexpr nsecs_t SIGNAL_TIME_INVALID = -1;
std::unordered_map<uint32_t, RollingAverage<kAveragesBufferSize>> mRollingAverages;
// mPowerHalHint should be declared only after mDisplayId and mDisplayTraceName have been
// declared since mDisplayId and mDisplayTraceName are needed as the parameter of
// PowerHalHintWorker's constructor
PowerHalHintWorker mPowerHalHint;
std::optional<nsecs_t> mValidateStartTime;
nsecs_t mPresentStartTime;
std::optional<nsecs_t> mValidationDuration;
// cached value used to skip evaluation once set
std::optional<bool> mUsePowerHintSession;
// tracks the time right before we start to wait for the fence
std::optional<nsecs_t> mRetireFenceWaitTime;
// tracks the time right after we finish waiting for the fence
std::optional<nsecs_t> mRetireFenceAcquireTime;
// tracks the time when the retire fence previously signaled
std::optional<nsecs_t> mRetireFencePreviousSignalTime;
// tracks the expected present time of the last frame
std::optional<nsecs_t> mLastExpectedPresentTime;
// tracks the expected present time of the current frame
nsecs_t mExpectedPresentTime;
// set once at the start of composition to ensure consistency
bool mUsePowerHints = false;
nsecs_t getExpectedPresentTime(nsecs_t startTime);
nsecs_t getPredictedPresentTime(nsecs_t startTime);
nsecs_t getSignalTime(int32_t fd) const;
void updateAverages(nsecs_t endTime);
std::optional<nsecs_t> getPredictedDuration(bool duringValidation);
atomic_bool mDebugRCDLayerEnabled = true;
protected:
inline uint32_t getDisplayVsyncPeriodFromConfig(hwc2_config_t config) {
int32_t vsync_period;
getDisplayAttribute(config, HWC2_ATTRIBUTE_VSYNC_PERIOD, &vsync_period);
assert(vsync_period > 0);
return static_cast<uint32_t>(vsync_period);
}
inline int32_t getDisplayFrameScanoutPeriodFromConfig(hwc2_config_t config);
virtual void calculateTimeline(
hwc2_config_t config,
hwc_vsync_period_change_constraints_t* vsyncPeriodChangeConstraints,
hwc_vsync_period_change_timeline_t* outTimeline);
public:
/* Override for each display's meaning of 'enabled state'
* Primary : Power on, this function overrided in primary display module
* Exteranal : Plug-in, default */
virtual bool isEnabled() { return mPlugState; }
// Resource TDM (Time-Division Multiplexing)
std::map<std::pair<int32_t, int32_t>, DisplayTDMInfo> mDisplayTDMInfo;
class RotatingLogFileWriter {
public:
RotatingLogFileWriter(uint32_t maxFileCount, uint32_t thresholdSizePerFile,
std::string extension = ".txt")
: mMaxFileCount(maxFileCount),
mThresholdSizePerFile(thresholdSizePerFile),
mPrefixName(""),
mExtension(extension),
mLastFileIndex(-1),
mFile(nullptr) {}
~RotatingLogFileWriter() {
if (mFile) {
fclose(mFile);
}
}
bool chooseOpenedFile();
void write(const String8& content) {
if (mFile) {
fwrite(content.c_str(), 1, content.size(), mFile);
}
}
void flush() {
if (mFile) {
fflush(mFile);
}
}
void setPrefixName(const std::string& prefixName) { mPrefixName = prefixName; }
private:
FILE* openLogFile(const std::string& filename, const std::string& mode);
std::optional<nsecs_t> getLastModifiedTimestamp(const std::string& filename);
uint32_t mMaxFileCount;
uint32_t mThresholdSizePerFile;
std::string mPrefixName;
std::string mExtension;
int32_t mLastFileIndex;
FILE* mFile;
};
RotatingLogFileWriter mErrLogFileWriter;
RotatingLogFileWriter mDebugDumpFileWriter;
RotatingLogFileWriter mFenceFileWriter;
protected:
class OperationRateManager {
public:
OperationRateManager() {}
virtual ~OperationRateManager() {}
virtual int32_t onLowPowerMode(bool __unused enabled) { return 0; }
virtual int32_t onPeakRefreshRate(uint32_t __unused rate) { return 0; }
virtual int32_t onConfig(hwc2_config_t __unused cfg) { return 0; }
virtual int32_t onBrightness(uint32_t __unused dbv) { return 0; }
virtual int32_t onPowerMode(int32_t __unused mode) { return 0; }
virtual int32_t getTargetOperationRate() const { return 0; }
};
public:
std::unique_ptr<OperationRateManager> mOperationRateManager;
bool isOperationRateSupported() { return mOperationRateManager != nullptr; }
void handleTargetOperationRate();
bool mHpdStatus;
void invalidate();
virtual bool checkHotplugEventUpdated(bool &hpdStatus);
virtual void handleHotplugEvent(bool hpdStatus);
virtual void hotplug();
class RefreshRateIndicator {
public:
virtual ~RefreshRateIndicator() = default;
virtual int32_t init() { return NO_ERROR; }
virtual void updateRefreshRate(int __unused refreshRate) {}
virtual void checkOnPresentDisplay() {}
virtual void checkOnSetActiveConfig(int __unused refreshRate) {}
};
class SysfsBasedRRIHandler : public RefreshRateIndicator,
public DrmSysfsEventHandler,
public std::enable_shared_from_this<SysfsBasedRRIHandler> {
public:
SysfsBasedRRIHandler(ExynosDisplay* display);
virtual ~SysfsBasedRRIHandler();
int32_t init() override;
void updateRefreshRate(int refreshRate) override;
void checkOnPresentDisplay() override;
void handleSysfsEvent() override;
int getFd() override { return mFd.get(); }
private:
void updateRefreshRateLocked(int refreshRate) REQUIRES(mMutex);
ExynosDisplay* mDisplay;
int mLastRefreshRate GUARDED_BY(mMutex);
nsecs_t mLastCallbackTime GUARDED_BY(mMutex);
std::atomic_bool mIgnoringLastUpdate = false;
bool mCanIgnoreIncreaseUpdate GUARDED_BY(mMutex) = false;
UniqueFd mFd;
std::mutex mMutex;
static constexpr auto kRefreshRateStatePathFormat =
"/sys/class/backlight/panel%d-backlight/state";
};
class ActiveConfigBasedRRIHandler : public RefreshRateIndicator {
public:
ActiveConfigBasedRRIHandler(ExynosDisplay* display);
virtual ~ActiveConfigBasedRRIHandler() = default;
int32_t init() override;
void updateRefreshRate(int refreshRate) override;
void checkOnSetActiveConfig(int refreshRate) override;
private:
void updateVsyncPeriod(int vsyncPeriod);
ExynosDisplay* mDisplay;
int mLastRefreshRate;
};
std::shared_ptr<RefreshRateIndicator> mRefreshRateIndicatorHandler;
int32_t setRefreshRateChangedCallbackDebugEnabled(bool enabled);
nsecs_t getLastLayerUpdateTime();
bool needUpdateRRIndicator();
virtual void checkPreblendingRequirement(){};
void resetColorMappingInfoForClientComp();
void storePrevValidateCompositionType();
};
#endif //_EXYNOSDISPLAY_H