1 #include "ExynosPrimaryDisplay.h"
2 #include "ExynosHWCModule.h"
3 #include "ExynosHWCUtils.h"
4 #include "ExynosMPPModule.h"
6 #define DISPLAY_LOGD(msg, ...) ALOGD("[%s] " msg, mDisplayName.string(), ##__VA_ARGS__)
7 #define DISPLAY_LOGV(msg, ...) ALOGV("[%s] " msg, mDisplayName.string(), ##__VA_ARGS__)
8 #define DISPLAY_LOGI(msg, ...) ALOGI("[%s] " msg, mDisplayName.string(), ##__VA_ARGS__)
9 #define DISPLAY_LOGW(msg, ...) ALOGW("[%s] " msg, mDisplayName.string(), ##__VA_ARGS__)
10 #define DISPLAY_LOGE(msg, ...) ALOGE("[%s] " msg, mDisplayName.string(), ##__VA_ARGS__)
12 ExynosPrimaryDisplay::ExynosPrimaryDisplay(int numGSCs
, struct exynos5_hwc_composer_device_1_t
*pdev
) :
13 ExynosOverlayDisplay(numGSCs
, pdev
)
17 ExynosPrimaryDisplay::~ExynosPrimaryDisplay()
21 int ExynosPrimaryDisplay::getDeconWinMap(int overlayIndex
, int totalOverlays
)
26 void ExynosPrimaryDisplay::forceYuvLayersToFb(hwc_display_contents_1_t __unused
*contents
)
30 int ExynosPrimaryDisplay::getMPPForUHD(hwc_layer_1_t __unused
&layer
)
35 int ExynosPrimaryDisplay::getRGBMPPIndex(int index
)
40 bool ExynosPrimaryDisplay::isOverlaySupported(hwc_layer_1_t
&layer
, size_t index
, bool useVPPOverlay
,
41 ExynosMPPModule
** supportedInternalMPP
, ExynosMPPModule
** supportedExternalMPP
)
43 // Exynos755555oesn't have any VPP Overlays
44 return ExynosDisplay::isOverlaySupported(layer
, index
, false, supportedInternalMPP
, supportedExternalMPP
);
46 bool ExynosPrimaryDisplay::isYuvDmaAvailable(int format
, uint32_t dma
)
48 return (format
== HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M_FULL
&&
52 void ExynosPrimaryDisplay::assignWindows(hwc_display_contents_1_t
*contents
)
54 // call the ExynosDisplay default implementation of assignWindows()
55 ExynosDisplay::assignWindows(contents
);
57 // allocate the max bandwidth non-rgb layer to IDMA_G2
58 // consider only non-secure dma case - secure dma is already allocated to IDMA_G2
60 bool videoLayerFound
= 0, curDmaYuvFound
= 0, hasDRMlayer
= 0;
61 uint32_t videoLayerIndex
= 0, curDmaYuvIndex
= 0;
62 uint32_t mTemp
= 0, bandWidth
= 0;
63 int fbLayerIndex
= -1;
65 for (size_t i
= 0; i
< contents
->numHwLayers
; i
++) {
66 hwc_layer_1_t
&layer
= contents
->hwLayers
[i
];
71 private_handle_t
*handle
= private_handle_t::dynamicCast(layer
.handle
);
73 if (layer
.compositionType
== HWC_FRAMEBUFFER_TARGET
)
76 // If there is DRM layer available, it has to go to IDMA_G2 channel.
77 if (layer
.compositionType
== HWC_OVERLAY
&&
78 getDrmMode(handle
->flags
) == SECURE_DRM
&&
79 !(layer
.flags
& HWC_SKIP_RENDERING
)) {
85 // If no DRM layer, find non-rgb overlay layer which can be supported by IDMA_G2.
86 if ((layer
.compositionType
== HWC_OVERLAY
) &&
87 isYuvDmaAvailable(handle
->format
, IDMA_G2
) &&
88 !(layer
.flags
& HWC_SKIP_RENDERING
) &&
91 mTemp
= (layer
.sourceCropf
.right
- layer
.sourceCropf
.left
) *
92 (layer
.sourceCropf
.bottom
- layer
.sourceCropf
.top
);
93 if (mTemp
> bandWidth
) {
100 if (((layer
.compositionType
== HWC_OVERLAY
) ||
101 (layer
.compositionType
== HWC_FRAMEBUFFER_TARGET
)) &&
103 (mLayerInfos
[i
]->mDmaType
== IDMA_G2
)) {
109 if (curDmaYuvFound
&& videoLayerFound
) {
110 mTemp
= mLayerInfos
[videoLayerIndex
]->mDmaType
;
111 mLayerInfos
[videoLayerIndex
]->mDmaType
= mLayerInfos
[curDmaYuvIndex
]->mDmaType
;
112 mLayerInfos
[curDmaYuvIndex
]->mDmaType
= mTemp
;
115 if (videoLayerFound
&& !curDmaYuvFound
) {
116 if (prevfbTargetIdma
== IDMA_G2
) {
117 prevfbTargetIdma
= (enum decon_idma_type
) mLayerInfos
[videoLayerIndex
]->mDmaType
;
118 mLayerInfos
[videoLayerIndex
]->mDmaType
= IDMA_G2
;
121 mLayerInfos
[videoLayerIndex
]->mDmaType
= IDMA_G2
;
124 if (mFbNeeded
&& mFbWindow
< NUM_HW_WINDOWS
&& fbLayerIndex
>= 0)
125 prevfbTargetIdma
= (enum decon_idma_type
) mLayerInfos
[fbLayerIndex
]->mDmaType
;
128 int ExynosPrimaryDisplay::postMPPM2M(hwc_layer_1_t
&layer
, struct decon_win_config
*config
, int win_map
, int index
)
130 int dst_format
= mExternalMPPDstFormat
;
131 private_handle_t
*handle
= private_handle_t::dynamicCast(layer
.handle
);
132 ExynosMPPModule
*exynosMPP
= mLayerInfos
[index
]->mExternalMPP
;
134 if (exynosMPP
== NULL
) {
135 DISPLAY_LOGE("postMPPM2M is called but externMPP is NULL");
136 if (layer
.acquireFenceFd
>= 0)
137 close(layer
.acquireFenceFd
);
138 layer
.acquireFenceFd
= -1;
139 layer
.releaseFenceFd
= -1;
143 hwc_frect_t sourceCrop
= { 0, 0,
144 (float)WIDTH(layer
.displayFrame
), (float)HEIGHT(layer
.displayFrame
) };
145 int originalTransform
= layer
.transform
;
146 hwc_rect_t originalDisplayFrame
= layer
.displayFrame
;
148 /* OFF_Screen to ON_Screen changes */
149 if (getDrmMode(handle
->flags
) == SECURE_DRM
)
150 recalculateDisplayFrame(layer
, mXres
, mYres
);
152 if (mType
!= EXYNOS_VIRTUAL_DISPLAY
&&
153 (isFormatRgb(handle
->format
) ||
154 (isYuvDmaAvailable(handle
->format
, mLayerInfos
[index
]->mDmaType
) &&
155 WIDTH(layer
.displayFrame
) % getIDMAWidthAlign(handle
->format
) == 0 &&
156 HEIGHT(layer
.displayFrame
) % getIDMAHeightAlign(handle
->format
) == 0)))
157 dst_format
= handle
->format
;
159 int err
= exynosMPP
->processM2M(layer
, dst_format
, &sourceCrop
);
161 /* Restore displayFrame*/
162 layer
.displayFrame
= originalDisplayFrame
;
165 DISPLAY_LOGE("failed to configure MPP (type:%u, index:%u) for layer %u",
166 exynosMPP
->mType
, exynosMPP
->mIndex
, index
);
170 buffer_handle_t dst_buf
= exynosMPP
->mDstBuffers
[exynosMPP
->mCurrentBuf
];
171 private_handle_t
*dst_handle
=
172 private_handle_t::dynamicCast(dst_buf
);
173 int fence
= exynosMPP
->mDstConfig
.releaseFenceFd
;
174 hwc_frect originalCrop
= layer
.sourceCropf
;
176 /* ExtMPP out is the input of Decon
177 * and Trsform was processed by ExtMPP
179 layer
.sourceCropf
= sourceCrop
;
181 configureHandle(dst_handle
, index
, layer
, fence
, config
[win_map
]);
183 /* Restore sourceCropf and transform */
184 layer
.sourceCropf
= originalCrop
;
185 layer
.transform
= originalTransform
;
189 void ExynosPrimaryDisplay::handleStaticLayers(hwc_display_contents_1_t
*contents
,
190 struct decon_win_config_data
&win_data
, int __unused tot_ovly_wins
)
192 unsigned int bitmap
= 0;
193 bool incorrect_mapping
= false;
195 ExynosDisplay::handleStaticLayers(contents
, win_data
, tot_ovly_wins
);
197 if (mLastFbWindow
>= NUM_HW_WINDOWS
) {
198 DISPLAY_LOGE("handleStaticLayers:: invalid mLastFbWindow(%d)", mLastFbWindow
);
202 win_data
.config
[mLastFbWindow
].idma_type
= prevfbTargetIdma
;
204 for (size_t i
= 0; i
< NUM_HW_WINDOWS
; i
++) {
205 if (win_data
.config
[i
].state
== win_data
.config
[i
].DECON_WIN_STATE_BUFFER
) {
206 if (bitmap
& (1 << win_data
.config
[i
].idma_type
)) {
207 ALOGE("handleStaticLayers: Channel-%d is mapped to multiple windows\n", win_data
.config
[i
].idma_type
);
208 incorrect_mapping
= true;
211 bitmap
|= 1 << win_data
.config
[i
].idma_type
;
215 if (incorrect_mapping
) {
216 android::String8 result
;
219 ALOGE("%s", result
.string());
221 dumpLayerInfo(result
);
222 ALOGE("%s", result
.string());
223 ALOGE("Display Config:");
224 dump_win_config(&win_data
.config
[0]);
228 void ExynosPrimaryDisplay::dump_win_config(struct decon_win_config
*config
)
231 struct decon_win_config
*cfg
;
232 const char *state
[] = { "DSBL", "COLR", "BUFF", "UPDT" };
233 const char *blending
[] = { "NOBL", "PMUL", "COVR" };
234 const char *idma
[] = { "G0", "G1", "V0", "V1", "VR0", "VR1", "G2" };
236 for (win
= 0; win
< MAX_DECON_WIN
; win
++) {
239 if (cfg
->state
== cfg
->DECON_WIN_STATE_DISABLED
)
242 if (cfg
->state
== cfg
->DECON_WIN_STATE_COLOR
) {
243 ALOGE("Win[%d]: %s, C(%d), Dst(%d,%d,%d,%d) "
245 win
, state
[cfg
->state
], cfg
->color
,
246 cfg
->dst
.x
, cfg
->dst
.y
,
247 cfg
->dst
.x
+ cfg
->dst
.w
,
248 cfg
->dst
.y
+ cfg
->dst
.h
,
251 ALOGE("Win[%d]: %s,(%d,%d,%d), F(%d) P(%d)"
252 " A(%d), %s, %s, fmt(%d) Src(%d,%d,%d,%d,f_w=%d,f_h=%d) ->"
253 " Dst(%d,%d,%d,%d,f_w=%d,f_h=%d) T(%d,%d,%d,%d) B(%d,%d,%d,%d)\n",
254 win
, state
[cfg
->state
], cfg
->fd_idma
[0],
255 cfg
->fd_idma
[1], cfg
->fd_idma
[2],
256 cfg
->fence_fd
, cfg
->protection
,
257 cfg
->plane_alpha
, blending
[cfg
->blending
],
258 idma
[cfg
->idma_type
], cfg
->format
,
259 cfg
->src
.x
, cfg
->src
.y
, cfg
->src
.x
+ cfg
->src
.w
, cfg
->src
.y
+ cfg
->src
.h
,
260 cfg
->src
.f_w
, cfg
->src
.f_h
,
261 cfg
->dst
.x
, cfg
->dst
.y
, cfg
->dst
.x
+ cfg
->dst
.w
, cfg
->dst
.y
+ cfg
->dst
.h
,
262 cfg
->dst
.f_w
, cfg
->dst
.f_h
,
263 cfg
->transparent_area
.x
, cfg
->transparent_area
.y
,
264 cfg
->transparent_area
.w
, cfg
->transparent_area
.h
,
265 cfg
->covered_opaque_area
.x
, cfg
->covered_opaque_area
.y
,
266 cfg
->covered_opaque_area
.w
, cfg
->covered_opaque_area
.h
);
271 int ExynosPrimaryDisplay::handleWindowUpdate(hwc_display_contents_1_t __unused
*contents
,
272 struct decon_win_config __unused
*config
)
275 int updatedWinCnt
= 0;
277 int bitsPerPixel
= 0;
278 size_t winUpdateInfoIdx
;
279 hwc_rect updateRect
= {this->mXres
, this->mYres
, 0, 0};
280 hwc_rect currentRect
= {0, 0, 0, 0};
281 bool burstLengthCheckDone
= false;
282 int alignAdjustment
= 0;
283 int intersectionWidth
= 0;
285 char value
[PROPERTY_VALUE_MAX
];
286 property_get("debug.hwc.winupdate", value
, NULL
);
288 if (!(!strcmp(value
, "1") || !strcmp(value
, "true")))
289 return -eWindowUpdateDisabled
;
291 if (DECON_WIN_UPDATE_IDX
< 0)
292 return -eWindowUpdateInvalidIndex
;
293 winUpdateInfoIdx
= DECON_WIN_UPDATE_IDX
;
295 if (contents
->flags
& HWC_GEOMETRY_CHANGED
)
296 return -eWindowUpdateGeometryChanged
;
298 for (size_t i
= 0; i
< contents
->numHwLayers
; i
++) {
299 if (contents
->hwLayers
[i
].compositionType
== HWC_FRAMEBUFFER
)
302 if (!mFbNeeded
&& contents
->hwLayers
[i
].compositionType
== HWC_FRAMEBUFFER_TARGET
)
304 int32_t windowIndex
= mLayerInfos
[i
]->mWindowIndex
;
305 if (config
[windowIndex
].state
!= config
[windowIndex
].DECON_WIN_STATE_DISABLED
) {
308 if (winConfigChanged(&config
[windowIndex
], &this->mLastConfigData
.config
[windowIndex
])) {
311 currentRect
.left
= config
[windowIndex
].dst
.x
;
312 currentRect
.right
= config
[windowIndex
].dst
.x
+ config
[windowIndex
].dst
.w
;
313 currentRect
.top
= config
[windowIndex
].dst
.y
;
314 currentRect
.bottom
= config
[windowIndex
].dst
.y
+ config
[windowIndex
].dst
.h
;
316 if (hwcHasApiVersion((hwc_composer_device_1_t
*)mHwc
, HWC_DEVICE_API_VERSION_1_5
))
318 private_handle_t
*handle
= NULL
;
319 hwc_rect damageRect
= {0, 0, 0, 0};
320 hwc_layer_1_t
&layer
= contents
->hwLayers
[i
];
322 handle
= private_handle_t::dynamicCast(layer
.handle
);
323 getLayerRegion(layer
, damageRect
, eDamageRegion
);
325 if (handle
&& !isScaled(layer
) && !isRotated(layer
)
326 && !(!(damageRect
.left
) && !(damageRect
.top
) && !(damageRect
.right
) && !(damageRect
.bottom
))) {
327 HLOGD("[WIN_UPDATE][surfaceDamage] layer w(%4d) h(%4d), dirty (%4d, %4d) - (%4d, %4d)",
328 handle
->width
, handle
->height
, damageRect
.left
, damageRect
.top
, damageRect
.right
, damageRect
.bottom
);
330 currentRect
.left
= config
[windowIndex
].dst
.x
- (int32_t)layer
.sourceCropf
.left
+ damageRect
.left
;
331 currentRect
.right
= config
[windowIndex
].dst
.x
- (int32_t)layer
.sourceCropf
.left
+ damageRect
.right
;
332 currentRect
.top
= config
[windowIndex
].dst
.y
- (int32_t)layer
.sourceCropf
.top
+ damageRect
.top
;
333 currentRect
.bottom
= config
[windowIndex
].dst
.y
- (int32_t)layer
.sourceCropf
.top
+ damageRect
.bottom
;
338 if ((currentRect
.left
> currentRect
.right
) || (currentRect
.top
> currentRect
.bottom
)) {
339 HLOGD("[WIN_UPDATE] window(%d) layer(%d) invalid region (%4d, %4d) - (%4d, %4d)",
340 i
, layerIdx
, currentRect
.left
, currentRect
.top
, currentRect
.right
, currentRect
.bottom
);
341 return -eWindowUpdateInvalidRegion
;
343 HLOGD("[WIN_UPDATE] Updated Window(%d) Layer(%d) (%4d, %4d) - (%4d, %4d)",
344 windowIndex
, i
, currentRect
.left
, currentRect
.top
, currentRect
.right
, currentRect
.bottom
);
345 updateRect
= expand(updateRect
, currentRect
);
349 if (updatedWinCnt
== 0)
350 return -eWindowUpdateNotUpdated
;
352 updateRect
.left
= ALIGN_DOWN(updateRect
.left
, WINUPDATE_X_ALIGNMENT
);
353 updateRect
.right
= updateRect
.left
+ ALIGN_UP(WIDTH(updateRect
), WINUPDATE_W_ALIGNMENT
);
355 if (HEIGHT(updateRect
) < WINUPDATE_MIN_HEIGHT
) {
356 if (updateRect
.top
+ WINUPDATE_MIN_HEIGHT
<= mYres
)
357 updateRect
.bottom
= updateRect
.top
+ WINUPDATE_MIN_HEIGHT
;
359 updateRect
.top
= updateRect
.bottom
- WINUPDATE_MIN_HEIGHT
;
362 if ((100 * (WIDTH(updateRect
) * HEIGHT(updateRect
)) / (this->mXres
* this->mYres
)) > WINUPDATE_THRESHOLD
)
363 return -eWindowUpdateOverThreshold
;
365 alignAdjustment
= max(WINUPDATE_X_ALIGNMENT
, WINUPDATE_W_ALIGNMENT
);
368 burstLengthCheckDone
= true;
370 for (size_t i
= 0; i
< contents
->numHwLayers
; i
++) {
371 if (contents
->hwLayers
[i
].compositionType
== HWC_FRAMEBUFFER
)
373 if (!mFbNeeded
&& contents
->hwLayers
[i
].compositionType
== HWC_FRAMEBUFFER_TARGET
)
375 int32_t windowIndex
= mLayerInfos
[i
]->mWindowIndex
;
376 if (config
[windowIndex
].state
!= config
[windowIndex
].DECON_WIN_STATE_DISABLED
) {
377 enum decon_pixel_format fmt
= config
[windowIndex
].format
;
379 if (fmt
== DECON_PIXEL_FORMAT_RGBA_5551
|| fmt
== DECON_PIXEL_FORMAT_RGB_565
)
381 else if (fmt
== DECON_PIXEL_FORMAT_NV12
|| fmt
== DECON_PIXEL_FORMAT_NV21
||
382 fmt
== DECON_PIXEL_FORMAT_NV12M
|| fmt
== DECON_PIXEL_FORMAT_NV21M
)
387 currentRect
.left
= config
[windowIndex
].dst
.x
;
388 currentRect
.right
= config
[windowIndex
].dst
.x
+ config
[windowIndex
].dst
.w
;
389 currentRect
.top
= config
[windowIndex
].dst
.y
;
390 currentRect
.bottom
= config
[windowIndex
].dst
.y
+ config
[windowIndex
].dst
.h
;
392 intersectionWidth
= WIDTH(intersection(currentRect
, updateRect
));
394 HLOGV("[WIN_UPDATE] win[%d] left(%d) right(%d) intersection(%d)", windowIndex
, currentRect
.left
, currentRect
.right
, intersectionWidth
);
396 if (intersectionWidth
!= 0 && (size_t)((intersectionWidth
* bitsPerPixel
) / 8) < BURSTLEN_BYTES
) {
397 HLOGV("[WIN_UPDATE] win[%d] insufficient burst length ((%d)*(%d)/8) < %d", windowIndex
, intersectionWidth
, bitsPerPixel
, BURSTLEN_BYTES
);
398 burstLengthCheckDone
= false;
404 if (burstLengthCheckDone
)
406 HLOGD("[WIN_UPDATE] Adjusting update width. current left(%d) right(%d)", updateRect
.left
, updateRect
.right
);
407 if (updateRect
.left
>= alignAdjustment
) {
408 updateRect
.left
-= alignAdjustment
;
409 } else if (updateRect
.right
+ alignAdjustment
<= this->mXres
) {
410 updateRect
.right
+= alignAdjustment
;
412 DISPLAY_LOGD("[WIN_UPDATE] Error during update width adjustment");
413 return -eWindowUpdateAdjustmentFail
;
417 config
[winUpdateInfoIdx
].state
= config
[winUpdateInfoIdx
].DECON_WIN_STATE_UPDATE
;
418 config
[winUpdateInfoIdx
].dst
.x
= updateRect
.left
;
419 config
[winUpdateInfoIdx
].dst
.y
= updateRect
.top
;
420 config
[winUpdateInfoIdx
].dst
.w
= ALIGN_UP(WIDTH(updateRect
), WINUPDATE_W_ALIGNMENT
);
421 config
[winUpdateInfoIdx
].dst
.h
= HEIGHT(updateRect
);
423 HLOGD("[WIN_UPDATE] UpdateRegion cfg (%4d, %4d) w(%4d) h(%4d) updatedWindowCnt(%d)",
424 config
[winUpdateInfoIdx
].dst
.x
, config
[winUpdateInfoIdx
].dst
.y
, config
[winUpdateInfoIdx
].dst
.w
, config
[winUpdateInfoIdx
].dst
.h
, updatedWinCnt
);
426 /* Disable block mode if window update region is not full screen */
427 if ((config
[winUpdateInfoIdx
].dst
.x
!= 0) || (config
[winUpdateInfoIdx
].dst
.y
!= 0) ||
428 (config
[winUpdateInfoIdx
].dst
.w
!= (uint32_t)mXres
) || (config
[winUpdateInfoIdx
].dst
.h
!= (uint32_t)mXres
)) {
429 for (size_t i
= 0; i
< NUM_HW_WINDOWS
; i
++) {
430 memset(&config
[i
].transparent_area
, 0, sizeof(config
[i
].transparent_area
));
431 memset(&config
[i
].covered_opaque_area
, 0, sizeof(config
[i
].covered_opaque_area
));
438 int ExynosPrimaryDisplay::getIDMAWidthAlign(int format
)
440 if (isFormatRgb(format
))
446 int ExynosPrimaryDisplay::getIDMAHeightAlign(int format
)
448 if (isFormatRgb(format
))