summaryrefslogtreecommitdiff
path: root/libhwc2.1/libdevice/ExynosDisplay.h
blob: 51286ad7367b1a54e868830065f49170b7ae0b26 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
/*
 * 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 VrrThrottleRequester : uint32_t {
    PIXEL_DISP = 0,
    TEST,
    LHBM,
    BRIGHTNESS,
    MAX,
};

enum class DispIdleTimerRequester : uint32_t {
    SF = 0,
    VRR_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 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;
} 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;
        uint32_t mBtsVsyncPeriod;

        int                     mPanelType;
        int                     mPsrMode;

        /* 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);

        /* 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 updateBtsVsyncPeriod(uint32_t vsyncPeriod, bool configApplied = false);
        uint32_t getBtsRefreshRate() const;
        virtual void checkBtsReassignResource(const uint32_t __unused vsyncPeriod,
                                              const uint32_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) {}
        virtual uint64_t getPendingExpectedPresentTime() { 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);

    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 VrrThrottleRequester __unused requester) {
            return NO_ERROR;
        }
        virtual int setRefreshRateThrottleNanos(const int64_t __unused delayNanos,
                                                const VrrThrottleRequester __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,
                                 int32_t* outConfig);

    private:
        bool skipStaticLayerChanged(ExynosCompositionInfo& compositionInfo);

        bool skipSignalIdle();

        /// 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, uint32_t vsyncPeriod);
            void signalIdle();
            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(int refreshRate);
            int32_t updateRefreshRateHintInternal(hwc2_power_mode_t powerMode,
                                                  uint32_t vsyncPeriod);
            int32_t sendRefreshRateHint(int refreshRate, bool enabled);
            void forceUpdateHints();

            int32_t checkIdleHintSupport();
            int32_t updateIdleHint(int64_t deadlineTime, 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<int, 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;
            uint32_t mVsyncPeriod;

            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);
        }

        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() { 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 RefreshRateIndicatorHandler : public DrmSysfsEventHandler {
        public:
            RefreshRateIndicatorHandler(ExynosDisplay* display);
            int32_t init();
            virtual void handleSysfsEvent() override;
            virtual int getFd() override { return mFd.get(); };
            bool isIgnoringLastUpdate() { return mIgnoringLastUpdate; }
            void updateRefreshRate(int refreshRate);

        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";
        };

        std::shared_ptr<RefreshRateIndicatorHandler> mRefreshRateIndicatorHandler;
        int32_t setRefreshRateChangedCallbackDebugEnabled(bool enabled);
        void updateRefreshRateIndicator();
        nsecs_t getLastLayerUpdateTime();
        bool needUpdateRRIndicator();
        virtual void checkPreblendingRequirement(){};

        void resetColorMappingInfoForClientComp();
        void storePrevValidateCompositionType();
};

#endif //_EXYNOSDISPLAY_H