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