1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef _EXYNOSDISPLAYDRMINTERFACE_H
18 #define _EXYNOSDISPLAYDRMINTERFACE_H
19 
20 #include <drm/samsung_drm.h>
21 #include <utils/Condition.h>
22 #include <utils/Mutex.h>
23 #include <xf86drmMode.h>
24 
25 #include <list>
26 #include <unordered_map>
27 
28 #include "ExynosDisplay.h"
29 #include "ExynosDisplayInterface.h"
30 #include "ExynosHWC.h"
31 #include "ExynosMPP.h"
32 #include "drmconnector.h"
33 #include "drmcrtc.h"
34 #include "histogram/histogram.h"
35 #include "vsyncworker.h"
36 
37 /* Max plane number of buffer object */
38 #define HWC_DRM_BO_MAX_PLANES 4
39 
40 /* Monitor Descriptor data is 13 bytes in VESA EDID Standard */
41 #define MONITOR_DESCRIPTOR_DATA_LENGTH 13
42 
43 #ifndef HWC_FORCE_PANIC_PATH
44 #define HWC_FORCE_PANIC_PATH "/d/dpu/panic"
45 #endif
46 
47 using namespace android;
48 
49 class ExynosDevice;
50 
51 template <typename T>
52 using DrmArray = std::array<T, HWC_DRM_BO_MAX_PLANES>;
53 
54 class DisplayConfigGroupIdGenerator {
55 public:
56     DisplayConfigGroupIdGenerator() = default;
57     ~DisplayConfigGroupIdGenerator() = default;
58 
59     // Vrr will utilize the last two parameters. In the case of non-vrr, they are automatically set
60     // to 0. Avoid using this class with a mix of Vrr and non-Vrr settings, as doing so may yield
61     // unexpected results.
62     int getGroupId(int width, int height, int minFrameInterval = 0, int vsyncPeriod = 0) {
63         const auto &key = std::make_tuple(width, height, minFrameInterval, vsyncPeriod);
64         if (groups_.count(key) > 0) {
65             return groups_[key];
66         }
67         size_t last_id = groups_.size();
68         groups_[key] = last_id;
69         return last_id;
70     }
71 
72 private:
73     std::map<std::tuple<int, int, int, int>, int> groups_;
74 };
75 
76 class FramebufferManager {
77     public:
FramebufferManager()78         FramebufferManager(){};
79         ~FramebufferManager();
80         void init(int drmFd);
81 
82         // get buffer for provided config, if a buffer with same config is already cached it will be
83         // reused otherwise one will be allocated. returns fbId that can be used to attach to the
84         // plane, any buffers allocated/reused with this call will be bound to the corresponding
85         // layer. Those fbIds will be cleaned up once the layer was destroyed.
86         int32_t getBuffer(const exynos_win_config_data &config, uint32_t &fbId);
87 
88         void checkShrink();
89 
90         void cleanup(const ExynosLayer *layer);
91         void destroyAllSecureBuffers();
92         int32_t uncacheLayerBuffers(const ExynosLayer* layer,
93                                     const std::vector<buffer_handle_t>& buffers);
94 
95         // The flip function is to help clean up the cached fbIds of destroyed
96         // layers after the previous fdIds were update successfully on the
97         // screen.
98         // This should be called after the frame update.
99         void flip(const bool hasSecureBuffer);
100 
101         // release all currently tracked buffers, this can be called for example when display is turned
102         // off
103         void releaseAll();
104 
105     private:
106         // this struct should contain elements that can be used to identify framebuffer more easily
107         struct Framebuffer {
108             struct BufferDesc {
109                 uint64_t bufferId;
110                 int drmFormat;
111                 bool isSecure;
112                 bool operator==(const Framebuffer::BufferDesc &rhs) const {
113                     return (bufferId == rhs.bufferId && drmFormat == rhs.drmFormat &&
114                             isSecure == rhs.isSecure);
115                 }
116                 bool operator<(const Framebuffer::BufferDesc& rhs) const {
117                     if (bufferId != rhs.bufferId) {
118                         return bufferId < rhs.bufferId;
119                     }
120                     if (drmFormat != rhs.drmFormat) {
121                         return drmFormat < rhs.drmFormat;
122                     }
123                     return isSecure < rhs.isSecure;
124                 }
125             };
126             struct SolidColorDesc {
127                 uint32_t width;
128                 uint32_t height;
129                 bool operator==(const Framebuffer::SolidColorDesc &rhs) const {
130                     return (width == rhs.width && height == rhs.height);
131                 }
132             };
133 
FramebufferFramebuffer134             explicit Framebuffer(int fd, uint32_t fb, BufferDesc desc)
135                   : drmFd(fd), fbId(fb), bufferDesc(desc){};
FramebufferFramebuffer136             explicit Framebuffer(int fd, uint32_t fb, SolidColorDesc desc)
137                   : drmFd(fd), fbId(fb), colorDesc(desc){};
~FramebufferFramebuffer138             ~Framebuffer() { drmModeRmFB(drmFd, fbId); };
139             int drmFd;
140             uint32_t fbId;
141             union {
142                 BufferDesc bufferDesc;
143                 SolidColorDesc colorDesc;
144             };
145         };
146         using FBList = std::list<std::unique_ptr<Framebuffer>>;
147 
148         template <class UnaryPredicate>
149         uint32_t findCachedFbId(const ExynosLayer* layer, const bool isSecureBuffer,
150                                 UnaryPredicate predicate);
151         int addFB2WithModifiers(uint32_t state, uint32_t width, uint32_t height, uint32_t drmFormat,
152                                 const DrmArray<uint32_t> &handles,
153                                 const DrmArray<uint32_t> &pitches,
154                                 const DrmArray<uint32_t> &offsets,
155                                 const DrmArray<uint64_t> &modifier, uint32_t *buf_id,
156                                 uint32_t flags);
157         bool validateLayerInfo(uint32_t state, uint32_t pixel_format,
158                                const DrmArray<uint32_t> &handles,
159                                const DrmArray<uint64_t> &modifier);
160         uint32_t getBufHandleFromFd(int fd);
161         void freeBufHandle(uint32_t handle);
162         void removeFBsThreadRoutine();
163 
164         void markInuseLayerLocked(const ExynosLayer* layer, const bool isSecureBuffer)
165                 REQUIRES(mMutex);
166         void destroyUnusedLayersLocked() REQUIRES(mMutex);
167         void destroyAllSecureBuffersLocked() REQUIRES(mMutex);
168 
169         int mDrmFd = -1;
170 
171         // mCachedLayerBuffers map keep the relationship between Layer and FBList.
172         // mCachedSecureLayerBuffers map keep the relationship between secure
173         // Layer and FBList. The map entry will be deleted once the layer is destroyed.
174         std::map<const ExynosLayer *, FBList> mCachedLayerBuffers;
175         std::map<const ExynosLayer*, FBList> mCachedSecureLayerBuffers;
176 
177         // mCleanBuffers list keeps fbIds of destroyed layers. Those fbIds will
178         // be destroyed in mRmFBThread thread.
179         FBList mCleanBuffers;
180 
181         // mCacheShrinkPending is set when we want to clean up unused layers
182         // in mCachedLayerBuffers. When the flag is set, mCachedLayersInuse will
183         // keep in-use layers in this frame update. Those unused layers will be
184         // freed at the end of the update. mCacheSecureShrinkPending is same to
185         // mCacheShrinkPending but for mCachedSecureLayerBuffers.
186         // TODO: have a better way to maintain inuse layers
187         bool mCacheShrinkPending = false;
188         bool mCacheSecureShrinkPending = false;
189         std::set<const ExynosLayer *> mCachedLayersInuse;
190         std::set<const ExynosLayer*> mCachedSecureLayersInuse;
191 
192         std::thread mRmFBThread;
193         bool mRmFBThreadRunning = false;
194         Condition mFlipDone;
195         Mutex mMutex;
196 
197         static constexpr size_t MAX_CACHED_LAYERS = 16;
198         static constexpr size_t MAX_CACHED_SECURE_LAYERS = 1;
199         static constexpr size_t MAX_CACHED_BUFFERS_PER_LAYER = 32;
200         static constexpr size_t MAX_CACHED_SECURE_BUFFERS_PER_LAYER = 3;
201 };
202 
203 template <class UnaryPredicate>
findCachedFbId(const ExynosLayer * layer,const bool isSecureBuffer,UnaryPredicate predicate)204 uint32_t FramebufferManager::findCachedFbId(const ExynosLayer* layer, const bool isSecureBuffer,
205                                             UnaryPredicate predicate) {
206     Mutex::Autolock lock(mMutex);
207     markInuseLayerLocked(layer, isSecureBuffer);
208     const auto& cachedBuffers =
209             (!isSecureBuffer) ? mCachedLayerBuffers[layer] : mCachedSecureLayerBuffers[layer];
210     const auto it = std::find_if(cachedBuffers.begin(), cachedBuffers.end(), predicate);
211     return (it != cachedBuffers.end()) ? (*it)->fbId : 0;
212 }
213 
214 class ExynosDisplayDrmInterface :
215     public ExynosDisplayInterface,
216     public VsyncCallback
217 {
218     public:
219         class DrmModeAtomicReq {
220             public:
221                 DrmModeAtomicReq(ExynosDisplayDrmInterface *displayInterface);
222                 ~DrmModeAtomicReq();
223 
224                 DrmModeAtomicReq(const DrmModeAtomicReq&) = delete;
225                 DrmModeAtomicReq& operator=(const DrmModeAtomicReq&) = delete;
226 
pset()227                 drmModeAtomicReqPtr pset() { return mPset; };
savePset()228                 void savePset() {
229                     if (mSavedPset) {
230                         drmModeAtomicFree(mSavedPset);
231                     }
232                     mSavedPset = drmModeAtomicDuplicate(mPset);
233                 }
restorePset()234                 void restorePset() {
235                     if (mPset) {
236                         drmModeAtomicFree(mPset);
237                     }
238                     mPset = mSavedPset;
239                     mSavedPset = NULL;
240                 }
241 
setError(int err)242                 void setError(int err) { mError = err; };
getError()243                 int getError() { return mError; };
244                 int32_t atomicAddProperty(const uint32_t id,
245                         const DrmProperty &property,
246                         uint64_t value, bool optional = false);
247                 String8& dumpAtomicCommitInfo(String8 &result, bool debugPrint = false);
248                 int commit(uint32_t flags, bool loggingForDebug = false);
addOldBlob(uint32_t blob_id)249                 void addOldBlob(uint32_t blob_id) {
250                     mOldBlobs.push_back(blob_id);
251                 };
destroyOldBlobs()252                 int destroyOldBlobs() {
253                     for (auto &blob : mOldBlobs) {
254                         int ret = mDrmDisplayInterface->mDrmDevice->DestroyPropertyBlob(blob);
255                         if (ret) {
256                             HWC_LOGE(mDrmDisplayInterface->mExynosDisplay,
257                                     "Failed to destroy old blob after commit %d", ret);
258                             return ret;
259                         }
260                     }
261                     mOldBlobs.clear();
262                     return NO_ERROR;
263                 };
264                 void dumpDrmAtomicCommitMessage(int err);
265 
setAckCallback(std::function<void ()> callback)266                 void setAckCallback(std::function<void()> callback) {
267                     mAckCallback = std::move(callback);
268                 };
269 
270             private:
271                 drmModeAtomicReqPtr mPset;
272                 drmModeAtomicReqPtr mSavedPset;
273                 int mError = 0;
274                 ExynosDisplayDrmInterface *mDrmDisplayInterface = NULL;
275                 /* Destroy old blobs after commit */
276                 std::vector<uint32_t> mOldBlobs;
drmFd()277                 int drmFd() const { return mDrmDisplayInterface->mDrmDevice->fd(); }
278 
279                 std::function<void()> mAckCallback;
280 
281                 static constexpr uint32_t kAllowDumpDrmAtomicMessageTimeMs = 5000U;
282                 static constexpr const char* kDrmModuleParametersDebugNode =
283                         "/sys/module/drm/parameters/debug";
284                 static constexpr const int kEnableDrmAtomicMessage = 16;
285                 static constexpr const int kDisableDrmDebugMessage = 0;
286 
287         };
288         class ExynosVsyncCallback {
289             public:
enableVSync(bool enable)290                 void enableVSync(bool enable) {
291                     mVsyncEnabled = enable;
292                     resetVsyncTimeStamp();
293                 };
getVSyncEnabled()294                 bool getVSyncEnabled() { return mVsyncEnabled; };
setDesiredVsyncPeriod(uint64_t period)295                 void setDesiredVsyncPeriod(uint64_t period) {
296                     mDesiredVsyncPeriod = period;
297                     resetVsyncTimeStamp();
298                 };
getDesiredVsyncPeriod()299                 uint64_t getDesiredVsyncPeriod() { return mDesiredVsyncPeriod;};
getVsyncTimeStamp()300                 uint64_t getVsyncTimeStamp() { return mVsyncTimeStamp; };
getVsyncPeriod()301                 uint64_t getVsyncPeriod() { return mVsyncPeriod; };
302                 bool Callback(int display, int64_t timestamp);
resetVsyncTimeStamp()303                 void resetVsyncTimeStamp() { mVsyncTimeStamp = 0; };
resetDesiredVsyncPeriod()304                 void resetDesiredVsyncPeriod() { mDesiredVsyncPeriod = 0;};
305 
306                 // Sets the vsync period to sync with ExynosDisplay::setActiveConfig.
307                 // Note: Vsync period updates should typically be done through Callback.
setVsyncPeriod(const uint64_t & period)308                 void setVsyncPeriod(const uint64_t& period) { mVsyncPeriod = period; }
setTransientDuration(const int & transientDuration)309                 void setTransientDuration(const int& transientDuration) {
310                     mTransientDuration = transientDuration;
311                 }
setModeSetFence(const int fence)312                 void setModeSetFence(const int fence) {
313                     std::lock_guard<std::mutex> lock(mFenceMutex);
314                     if (mModeSetFence != -1) {
315                         close(mModeSetFence);
316                         mModeSetFence = -1;
317                     }
318                     mModeSetFence = fence;
319                 }
320 
321             private:
322                 bool mVsyncEnabled = false;
323                 uint64_t mVsyncTimeStamp = 0;
324                 uint64_t mVsyncPeriod = 0;
325                 uint64_t mDesiredVsyncPeriod = 0;
326                 int mModeSetFence = -1;
327                 int mTransientDuration = 0;
328                 std::mutex mFenceMutex;
329         };
330         void Callback(int display, int64_t timestamp) override;
331 
332         ExynosDisplayDrmInterface(ExynosDisplay *exynosDisplay);
333         ~ExynosDisplayDrmInterface();
334         virtual void init(ExynosDisplay *exynosDisplay);
335         virtual int32_t setPowerMode(int32_t mode);
336         virtual int32_t setLowPowerMode() override;
isDozeModeAvailable()337         virtual bool isDozeModeAvailable() const {
338             return mDozeDrmMode.h_display() > 0 && mDozeDrmMode.v_display() > 0;
339         };
340         virtual int32_t setVsyncEnabled(uint32_t enabled);
341         virtual int32_t getDisplayConfigs(
342                 uint32_t* outNumConfigs,
343                 hwc2_config_t* outConfigs);
344         virtual void dumpDisplayConfigs();
345         virtual bool supportDataspace(int32_t dataspace);
346         virtual int32_t getColorModes(uint32_t* outNumModes, int32_t* outModes);
347         virtual int32_t setColorMode(int32_t mode);
348         virtual int32_t setActiveConfig(hwc2_config_t config);
349         virtual int32_t setCursorPositionAsync(uint32_t x_pos, uint32_t y_pos);
350         virtual int32_t updateHdrCapabilities();
351         virtual int32_t deliverWinConfigData();
352         virtual int32_t clearDisplay(bool needModeClear = false);
353         virtual int32_t disableSelfRefresh(uint32_t disable);
354         virtual int32_t setForcePanic();
getDisplayFd()355         virtual int getDisplayFd() { return mDrmDevice->fd(); };
356         virtual int32_t initDrmDevice(DrmDevice *drmDevice);
357         virtual int getDrmDisplayId(uint32_t type, uint32_t index);
getMaxWindowNum()358         virtual uint32_t getMaxWindowNum() { return mMaxWindowNum; };
359         virtual int32_t getReadbackBufferAttributes(int32_t* /*android_pixel_format_t*/ outFormat,
360                 int32_t* /*android_dataspace_t*/ outDataspace);
361         virtual int32_t getDisplayIdentificationData(uint8_t* outPort,
362                 uint32_t* outDataSize, uint8_t* outData);
363         virtual bool needRefreshOnLP();
364 
365         /* For HWC 2.4 APIs */
366         virtual int32_t getDisplayVsyncPeriod(
367                 hwc2_vsync_period_t* outVsyncPeriod);
368         virtual int32_t getConfigChangeDuration();
369         virtual int32_t getVsyncAppliedTime(hwc2_config_t config,
370                 int64_t* actualChangeTime);
371         virtual int32_t setActiveConfigWithConstraints(
372                 hwc2_config_t config, bool test = false);
373 
setDisplayColorSetting(ExynosDisplayDrmInterface::DrmModeAtomicReq __unused & drmReq)374         virtual int32_t setDisplayColorSetting(
375                 ExynosDisplayDrmInterface::DrmModeAtomicReq __unused &drmReq) {
376             return NO_ERROR;
377         }
setPlaneColorSetting(ExynosDisplayDrmInterface::DrmModeAtomicReq & drmReq,const std::unique_ptr<DrmPlane> & plane,const exynos_win_config_data & config,uint32_t & solidColor)378         virtual int32_t setPlaneColorSetting(
379                 ExynosDisplayDrmInterface::DrmModeAtomicReq &drmReq,
380                 const std::unique_ptr<DrmPlane> &plane,
381                 const exynos_win_config_data& config,
382                 uint32_t &solidColor)
383         { return NO_ERROR;};
384         virtual void destroyLayer(ExynosLayer *layer) override;
385 
386         /* For HWC 3.0 APIs */
387         virtual int32_t getDisplayIdleTimerSupport(bool &outSupport);
388         virtual int32_t getDefaultModeId(int32_t *modeId) override;
389 
390         virtual int32_t waitVBlank();
getDesiredRefreshRate()391         float getDesiredRefreshRate() { return mDesiredModeState.mode.v_refresh(); }
getOperationRate()392         int32_t getOperationRate() {
393             if (mExynosDisplay->mOperationRateManager) {
394                     return mExynosDisplay->mOperationRateManager->getTargetOperationRate();
395             }
396             return 0;
397         }
398 
399         /* For Histogram */
setDisplayHistogramSetting(ExynosDisplayDrmInterface::DrmModeAtomicReq & drmReq)400         virtual int32_t setDisplayHistogramSetting(
401                 ExynosDisplayDrmInterface::DrmModeAtomicReq &drmReq) {
402             return NO_ERROR;
403         }
404 
405         /* For Histogram Multi Channel support */
406         int32_t setHistogramChannelConfigBlob(ExynosDisplayDrmInterface::DrmModeAtomicReq& drmReq,
407                                               uint8_t channelId, uint32_t blobId);
408         int32_t clearHistogramChannelConfigBlob(ExynosDisplayDrmInterface::DrmModeAtomicReq& drmReq,
409                                                 uint8_t channelId);
410         enum class HistogramChannelIoctl_t {
411             /* send the histogram data request by calling histogram_channel_request_ioctl */
412             REQUEST = 0,
413 
414             /* cancel the histogram data request by calling histogram_channel_cancel_ioctl */
415             CANCEL,
416         };
417         int32_t sendHistogramChannelIoctl(HistogramChannelIoctl_t control, uint32_t blobId) const;
418 
419         enum class ContextHistogramIoctl_t {
420             /* send the histogram event request by calling histogram_event_request_ioctl */
421             REQUEST = 0,
422             /* send the histogram event request by calling histogram_event_cancel_ioctl */
423             CANCEL,
424         };
425         int32_t sendContextHistogramIoctl(ContextHistogramIoctl_t control, uint32_t blobId) const;
426 
getFrameCount()427         int32_t getFrameCount() { return mFrameCounter; }
registerHistogramInfo(const std::shared_ptr<IDLHistogram> & info)428         virtual void registerHistogramInfo(const std::shared_ptr<IDLHistogram> &info) { return; }
setHistogramControl(hidl_histogram_control_t enabled)429         virtual int32_t setHistogramControl(hidl_histogram_control_t enabled) { return NO_ERROR; }
setHistogramData(void * bin)430         virtual int32_t setHistogramData(void *bin) { return NO_ERROR; }
getActiveModeHDisplay()431         int32_t getActiveModeHDisplay() { return mActiveModeState.mode.h_display(); }
getActiveModeVDisplay()432         int32_t getActiveModeVDisplay() { return mActiveModeState.mode.v_display(); }
getActiveModeId()433         uint32_t getActiveModeId() { return mActiveModeState.mode.id(); }
getPanelFullResolutionHSize()434         int32_t getPanelFullResolutionHSize() { return mPanelFullResolutionHSize; }
getPanelFullResolutionVSize()435         int32_t getPanelFullResolutionVSize() { return mPanelFullResolutionVSize; }
getCrtcId()436         uint32_t getCrtcId() { return mDrmCrtc->id(); }
437         int32_t triggerClearDisplayPlanes();
438 
439         virtual void setXrrSettings(const XrrSettings_t& settings) override;
isVrrSupported()440         bool isVrrSupported() const { return mXrrSettings.versionInfo.isVrr(); }
isMrrV2()441         bool isMrrV2() const {
442             return (!mXrrSettings.versionInfo.isVrr()) &&
443                     (mXrrSettings.versionInfo.minorVersion == 2);
444         }
445 
446         void handleDrmPropertyUpdate(uint32_t connector_id, uint32_t prop_id);
447 
448         /* store the manufacturer info and product id from EDID
449          * - Manufacturer ID is stored in EDID byte 8 and 9.
450          * - Manufacturer product ID is stored in EDID byte 10 and 11.
451          */
452         virtual void setManufacturerInfo(uint8_t edid8, uint8_t edid9) override;
getManufacturerInfo()453         virtual uint32_t getManufacturerInfo() override { return mManufacturerInfo; }
454         virtual void setProductId(uint8_t edid10, uint8_t edid11) override;
getProductId()455         virtual uint32_t getProductId() override { return mProductId; }
456 
457         // This function will swap crtc/decon assigned to this display, with the crtc/decon of
458         // the provided |anotherDisplay|. It is used on foldable devices, where decon0/1 support
459         // color management, but decon2 doesn't, to re-assign the decon0/1 of a powered off primary
460         // display for the external display. When the external display is disconnected, this
461         // function is called again with the same |anotherDisplay| parameter to restore the
462         // original crtc/decon assignment of the external and primary display.
463         // See b/329034082 for details.
464         virtual int32_t swapCrtcs(ExynosDisplay* anotherDisplay) override;
465         // After swapCrtcs has been successfully done, this function will return the display, whose
466         // crtc/decon this display is currently using.
467         virtual ExynosDisplay* borrowedCrtcFrom() override;
468 
469         virtual int32_t uncacheLayerBuffers(const ExynosLayer* __unused layer,
470                                             const std::vector<buffer_handle_t>& buffers) override;
471 
472     protected:
473         enum class HalMipiSyncType : uint32_t {
474             HAL_MIPI_CMD_SYNC_REFRESH_RATE = 0,
475             HAL_MIPI_CMD_SYNC_LHBM,
476             HAL_MIPI_CMD_SYNC_GHBM,
477             HAL_MIPI_CMD_SYNC_BL,
478             HAL_MIPI_CMD_SYNC_OP_RATE,
479         };
480 
481         struct ModeState {
482             enum ModeStateType {
483                 MODE_STATE_NONE = 0U,
484                 MODE_STATE_REFRESH_RATE = 1U << 0,
485                 MODE_STATE_RESOLUTION = 1U << 1,
486                 MODE_STATE_FORCE_MODE_SET = 1U << 2,
487             };
488             DrmMode mode;
489             uint32_t blob_id = 0;
490             uint32_t old_blob_id = 0;
setModeModeState491             void setMode(const DrmMode newMode, const uint32_t modeBlob,
492                     DrmModeAtomicReq &drmReq) {
493                 if (newMode.v_refresh() != mode.v_refresh()) {
494                     mModeState |= ModeStateType::MODE_STATE_REFRESH_RATE;
495                 }
496                 if (isFullModeSwitch(newMode)) {
497                     mModeState |= ModeStateType::MODE_STATE_RESOLUTION;
498                 }
499 
500                 drmReq.addOldBlob(old_blob_id);
501                 mode = newMode;
502                 old_blob_id = blob_id;
503                 blob_id = modeBlob;
504             };
resetModeState505             void reset() {
506                 *this = {};
507             };
applyModeState508             void apply(ModeState &toModeState, DrmModeAtomicReq &drmReq) {
509                 toModeState.setMode(mode, blob_id, drmReq);
510                 drmReq.addOldBlob(old_blob_id);
511                 reset();
512             };
513 
514             int32_t mModeState = ModeStateType::MODE_STATE_NONE;
forceModeSetModeState515             void forceModeSet() { mModeState |= ModeStateType::MODE_STATE_FORCE_MODE_SET; }
clearPendingModeStateModeState516             void clearPendingModeState() { mModeState = ModeStateType::MODE_STATE_NONE; }
needsModeSetModeState517             bool needsModeSet() const { return mModeState != ModeStateType::MODE_STATE_NONE; }
isSeamlessModeState518             bool isSeamless() const { return !(mModeState & ModeStateType::MODE_STATE_RESOLUTION); }
isFullModeSwitchModeState519             bool isFullModeSwitch(const DrmMode &newMode) {
520                 if ((mode.h_display() != newMode.h_display()) ||
521                     (mode.v_display() != newMode.v_display()))
522                     return true;
523                 return false;
524             }
525         };
526         int32_t createModeBlob(const DrmMode &mode, uint32_t &modeBlob);
527         int32_t setDisplayMode(DrmModeAtomicReq& drmReq, const uint32_t& modeBlob,
528                                const uint32_t& modeId);
529         int32_t clearDisplayMode(DrmModeAtomicReq &drmReq);
530         int32_t clearDisplayPlanes(DrmModeAtomicReq &drmReq);
531         int32_t choosePreferredConfig();
532         int getDeconChannel(ExynosMPP *otfMPP);
533         /*
534          * This function adds FB and gets new fb id if fbId is 0,
535          * if fbId is not 0, this reuses fbId.
536          */
537         int32_t setupCommitFromDisplayConfig(DrmModeAtomicReq &drmReq,
538                 const exynos_win_config_data &config,
539                 const uint32_t configIndex,
540                 const std::unique_ptr<DrmPlane> &plane,
541                 uint32_t &fbId);
542 
543         int32_t setupPartialRegion(DrmModeAtomicReq &drmReq);
544         void parseBlendEnums(const DrmProperty &property);
545         void parseStandardEnums(const DrmProperty &property);
546         void parseTransferEnums(const DrmProperty &property);
547         void parseRangeEnums(const DrmProperty &property);
548         void parseColorModeEnums(const DrmProperty &property);
549         void parseMipiSyncEnums(const DrmProperty &property);
550         void updateMountOrientation();
551         void parseRCDId(const DrmProperty &property);
552 
553         int32_t setupWritebackCommit(DrmModeAtomicReq &drmReq);
554         int32_t clearWritebackCommit(DrmModeAtomicReq &drmReq);
555 
556     private:
557         int32_t updateColorSettings(DrmModeAtomicReq &drmReq, uint64_t dqeEnabled);
558         int32_t getLowPowerDrmModeModeInfo();
559         int32_t setActiveDrmMode(DrmMode const &mode);
setMaxWindowNum(uint32_t num)560         void setMaxWindowNum(uint32_t num) { mMaxWindowNum = num; };
561         int32_t getSpecialChannelId(uint32_t planeId);
562 
563     protected:
564         struct PartialRegionState {
565             struct drm_clip_rect partial_rect = {0, 0, 0, 0};
566             uint32_t blob_id = 0;
isUpdatedPartialRegionState567             bool isUpdated(drm_clip_rect rect) {
568                 return ((partial_rect.x1 != rect.x1) ||
569                         (partial_rect.y1 != rect.y1) ||
570                         (partial_rect.x2 != rect.x2) ||
571                         (partial_rect.y2 != rect.y2));
572             };
573         };
574 
575         struct BlockingRegionState {
576             struct decon_win_rect mRegion;
577             uint32_t mBlobId = 0;
578 
579             inline bool operator==(const decon_win_rect &rhs) const {
580                 return mRegion.x == rhs.x && mRegion.y == rhs.y && mRegion.w == rhs.w &&
581                         mRegion.h == rhs.h;
582             }
583             inline bool operator!=(const decon_win_rect &rhs) const { return !(*this == rhs); }
584         };
585 
586         class DrmReadbackInfo {
587             public:
588                 void init(DrmDevice *drmDevice, uint32_t displayId);
~DrmReadbackInfo()589                 ~DrmReadbackInfo() {
590                     if (mDrmDevice == NULL)
591                         return;
592                     if (mOldFbId > 0)
593                         drmModeRmFB(mDrmDevice->fd(), mOldFbId);
594                     if (mFbId > 0)
595                         drmModeRmFB(mDrmDevice->fd(), mFbId);
596                 }
getWritebackConnector()597                 DrmConnector* getWritebackConnector() { return mWritebackConnector; };
setFbId(uint32_t fbId)598                 void setFbId(uint32_t fbId) {
599                     if ((mDrmDevice != NULL) && (mOldFbId > 0))
600                         drmModeRmFB(mDrmDevice->fd(), mOldFbId);
601                     mOldFbId = mFbId;
602                     mFbId = fbId;
603                 }
604                 void pickFormatDataspace();
605                 static constexpr uint32_t PREFERRED_READBACK_FORMAT =
606                     HAL_PIXEL_FORMAT_RGBA_8888;
607                 uint32_t mReadbackFormat = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
608                 bool mNeedClearReadbackCommit = false;
609             private:
610                 DrmDevice *mDrmDevice = NULL;
611                 DrmConnector *mWritebackConnector = NULL;
612                 uint32_t mFbId = 0;
613                 uint32_t mOldFbId = 0;
614                 std::vector<uint32_t> mSupportedFormats;
615         };
616         DrmDevice *mDrmDevice;
617         DrmCrtc *mDrmCrtc;
618         DrmConnector *mDrmConnector;
619         VSyncWorker mDrmVSyncWorker;
620         ExynosVsyncCallback mVsyncCallback;
621         ModeState mActiveModeState;
622         ModeState mDesiredModeState;
623         PartialRegionState mPartialRegionState;
624         BlockingRegionState mBlockState;
625         /* Mapping plane id to ExynosMPP, key is plane id */
626         std::unordered_map<uint32_t, ExynosMPP*> mExynosMPPsForPlane;
627 
628         ExynosDisplay* mBorrowedCrtcFrom = nullptr;
629 
630         DrmEnumParser::MapHal2DrmEnum mBlendEnums;
631         DrmEnumParser::MapHal2DrmEnum mStandardEnums;
632         DrmEnumParser::MapHal2DrmEnum mTransferEnums;
633         DrmEnumParser::MapHal2DrmEnum mRangeEnums;
634         DrmEnumParser::MapHal2DrmEnum mColorModeEnums;
635         DrmEnumParser::MapHal2DrmEnum mMipiSyncEnums;
636 
637         DrmReadbackInfo mReadbackInfo;
638         FramebufferManager mFBManager;
639         std::array<uint8_t, MONITOR_DESCRIPTOR_DATA_LENGTH> mMonitorDescription;
640         nsecs_t mLastDumpDrmAtomicMessageTime;
641         bool mIsResolutionSwitchInProgress = false;
642 
643     private:
644         int32_t getDisplayFakeEdid(uint8_t &outPort, uint32_t &outDataSize, uint8_t *outData);
645 
646         String8 mDisplayTraceName;
647         DrmMode mDozeDrmMode;
648         uint32_t mMaxWindowNum = 0;
649         int32_t mFrameCounter = 0;
650         int32_t mPanelFullResolutionHSize = 0;
651         int32_t mPanelFullResolutionVSize = 0;
652 
653         // Vrr related settings.
654         XrrSettings_t mXrrSettings;
655 
656         /**
657          * retrievePanelFullResolution
658          *
659          * Retrieve the panel full resolution by looking into the modes of the mDrmConnector
660          * and store the full resolution info in mPanelFullResolutionHSize (x component) and
661          * mPanelFullResolutionVSize (y component).
662          *
663          * Note: this function will be called only once in initDrmDevice()
664          */
665         void retrievePanelFullResolution();
666 
667         const uint8_t kEDIDManufacturerIDByte1 = 8;
668         const uint8_t kEDIDManufacturerIDByte2 = 9;
669         const uint8_t kEDIDProductIDByte1 = 10;
670         const uint8_t kEDIDProductIDByte2 = 11;
671         uint32_t mManufacturerInfo;
672         uint32_t mProductId;
673         bool mIsFirstClean = true;
674 
675     public:
676         virtual bool readHotplugStatus();
677         virtual int readHotplugErrorCode();
678         virtual void resetHotplugErrorCode();
679 };
680 
681 #endif
682