1 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
4 #define LOG_TAG "display"
5 #include "ExynosDisplay.h"
6 #include "ExynosHWCUtils.h"
7 #include "ExynosMPPModule.h"
8 #include "ExynosHWCDebug.h"
9 #include <utils/misc.h>
10 #include <utils/Trace.h>
12 #if defined(USES_DUAL_DISPLAY)
13 #include "ExynosSecondaryDisplayModule.h"
16 int getGCD(int a
, int b
)
21 return getGCD(b
, a
%b
);
24 int getLCM(int a
, int b
)
26 return (a
*b
)/getGCD(a
,b
);
29 bool frameChanged(decon_frame
*f1
, decon_frame
*f2
)
31 return f1
->x
!= f2
->x
||
39 bool winConfigChanged(decon_win_config
*c1
, decon_win_config
*c2
)
41 return c1
->state
!= c2
->state
||
42 c1
->fd_idma
[0] != c2
->fd_idma
[0] ||
43 c1
->fd_idma
[1] != c2
->fd_idma
[1] ||
44 c1
->fd_idma
[2] != c2
->fd_idma
[2] ||
45 frameChanged(&c1
->src
, &c2
->src
) ||
46 frameChanged(&c1
->dst
, &c2
->dst
) ||
47 c1
->format
!= c2
->format
||
48 c1
->blending
!= c2
->blending
||
49 c1
->plane_alpha
!= c2
->plane_alpha
;
52 void ExynosDisplay::dumpConfig(decon_win_config
&c
)
54 DISPLAY_LOGD(eDebugWinConfig
, "\tstate = %u", c
.state
);
55 if (c
.state
== c
.DECON_WIN_STATE_COLOR
) {
56 DISPLAY_LOGD(eDebugWinConfig
, "\t\tcolor = %u", c
.color
);
57 } else if (c
.state
!= c
.DECON_WIN_STATE_DISABLED
) {
58 DISPLAY_LOGD(eDebugWinConfig
, "\t\tfd = %d, dma = %u "
59 "src_f_w = %u, src_f_h = %u, src_x = %d, src_y = %d, src_w = %u, src_h = %u, "
60 "dst_f_w = %u, dst_f_h = %u, dst_x = %d, dst_y = %d, dst_w = %u, dst_h = %u, "
61 "format = %u, blending = %u, protection = %u, transparent(x:%d, y:%d, w:%d, h:%d)",
62 c
.fd_idma
[0], c
.idma_type
,
63 c
.src
.f_w
, c
.src
.f_h
, c
.src
.x
, c
.src
.y
, c
.src
.w
, c
.src
.h
,
64 c
.dst
.f_w
, c
.dst
.f_h
, c
.dst
.x
, c
.dst
.y
, c
.dst
.w
, c
.dst
.h
,
65 c
.format
, c
.blending
, c
.protection
,
66 c
.transparent_area
.x
, c
.transparent_area
.y
, c
.transparent_area
.w
, c
.transparent_area
.h
);
70 void ExynosDisplay::dumpConfig(decon_win_config
&c
, android::String8
& result
)
72 result
.appendFormat("\tstate = %u", c
.state
);
73 if (c
.state
== c
.DECON_WIN_STATE_COLOR
) {
74 result
.appendFormat("\t\tcolor = %u", c
.color
);
76 result
.appendFormat("\t\tfd = %d, dma = %u "
77 "src_f_w = %u, src_f_h = %u, src_x = %d, src_y = %d, src_w = %u, src_h = %u, "
78 "dst_f_w = %u, dst_f_h = %u, dst_x = %d, dst_y = %d, dst_w = %u, dst_h = %u, "
79 "format = %u, blending = %u, protection = %u, transparent(x:%d, y:%d, w:%d, h:%d)",
80 c
.fd_idma
[0], c
.idma_type
,
81 c
.src
.f_w
, c
.src
.f_h
, c
.src
.x
, c
.src
.y
, c
.src
.w
, c
.src
.h
,
82 c
.dst
.f_w
, c
.dst
.f_h
, c
.dst
.x
, c
.dst
.y
, c
.dst
.w
, c
.dst
.h
,
83 c
.format
, c
.blending
, c
.protection
,
84 c
.transparent_area
.x
, c
.transparent_area
.y
, c
.transparent_area
.w
, c
.transparent_area
.h
);
88 enum decon_pixel_format
halFormatToS3CFormat(int format
)
91 case HAL_PIXEL_FORMAT_RGBA_8888
:
92 return DECON_PIXEL_FORMAT_RGBA_8888
;
93 case HAL_PIXEL_FORMAT_RGBX_8888
:
94 return DECON_PIXEL_FORMAT_RGBX_8888
;
95 case HAL_PIXEL_FORMAT_RGB_565
:
96 return DECON_PIXEL_FORMAT_RGB_565
;
97 case HAL_PIXEL_FORMAT_BGRA_8888
:
98 return DECON_PIXEL_FORMAT_BGRA_8888
;
99 #ifdef EXYNOS_SUPPORT_BGRX_8888
100 case HAL_PIXEL_FORMAT_BGRX_8888
:
101 return DECON_PIXEL_FORMAT_BGRX_8888
;
103 case HAL_PIXEL_FORMAT_EXYNOS_YV12_M
:
104 return DECON_PIXEL_FORMAT_YVU420M
;
105 case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_P_M
:
106 return DECON_PIXEL_FORMAT_YUV420M
;
107 case HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M
:
108 case HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M_FULL
:
109 return DECON_PIXEL_FORMAT_NV21M
;
110 case HAL_PIXEL_FORMAT_YCrCb_420_SP
:
111 return DECON_PIXEL_FORMAT_NV21
;
112 case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M
:
113 case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_PRIV
:
114 case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_S10B
:
115 return DECON_PIXEL_FORMAT_NV12M
;
116 #ifdef DECON_PIXEL_FORMAT_NV12N_10B
117 case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_S10B
:
118 return DECON_PIXEL_FORMAT_NV12N_10B
;
120 #ifdef DECON_PIXEL_FORMAT_NV12N
121 case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN
:
122 return DECON_PIXEL_FORMAT_NV12N
;
125 return DECON_PIXEL_FORMAT_MAX
;
129 int S3CFormatToHalFormat(enum decon_pixel_format format
)
132 case DECON_PIXEL_FORMAT_RGBA_8888
:
133 return HAL_PIXEL_FORMAT_RGBA_8888
;
134 case DECON_PIXEL_FORMAT_RGBX_8888
:
135 return HAL_PIXEL_FORMAT_RGBX_8888
;
136 case DECON_PIXEL_FORMAT_RGB_565
:
137 return HAL_PIXEL_FORMAT_RGB_565
;
138 case DECON_PIXEL_FORMAT_BGRA_8888
:
139 return HAL_PIXEL_FORMAT_BGRA_8888
;
140 #ifdef EXYNOS_SUPPORT_BGRX_8888
141 case DECON_PIXEL_FORMAT_BGRX_8888
:
142 return HAL_PIXEL_FORMAT_BGRX_8888
;
144 case DECON_PIXEL_FORMAT_YVU420M
:
145 return HAL_PIXEL_FORMAT_EXYNOS_YV12_M
;
146 case DECON_PIXEL_FORMAT_YUV420M
:
147 return HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_P_M
;
148 /* HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M_FULL ?? */
149 case DECON_PIXEL_FORMAT_NV21M
:
150 return HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M
;
151 case DECON_PIXEL_FORMAT_NV21
:
152 return HAL_PIXEL_FORMAT_YCrCb_420_SP
;
153 /* HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_PRIV, HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_S10B */
154 case DECON_PIXEL_FORMAT_NV12M
:
155 return HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M
;
156 #ifdef DECON_PIXEL_FORMAT_NV12N
157 case DECON_PIXEL_FORMAT_NV12N
:
158 return HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN
;
160 #ifdef DECON_PIXEL_FORMAT_NV12N_10B
161 case DECON_PIXEL_FORMAT_NV12N_10B
:
162 return HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_S10B
;
169 bool isFormatSupported(int format
)
171 return halFormatToS3CFormat(format
) < DECON_PIXEL_FORMAT_MAX
;
174 enum decon_blending
halBlendingToS3CBlending(int32_t blending
)
177 case HWC_BLENDING_NONE
:
178 return DECON_BLENDING_NONE
;
179 case HWC_BLENDING_PREMULT
:
180 return DECON_BLENDING_PREMULT
;
181 case HWC_BLENDING_COVERAGE
:
182 return DECON_BLENDING_COVERAGE
;
185 return DECON_BLENDING_MAX
;
189 bool isBlendingSupported(int32_t blending
)
191 return halBlendingToS3CBlending(blending
) < DECON_BLENDING_MAX
;
194 #define NUMA(a) (sizeof(a) / sizeof(a [0]))
195 const char *deconFormat2str(uint32_t format
)
197 android::String8 result
;
199 for (unsigned int n1
= 0; n1
< NUMA(deconFormat
); n1
++) {
200 if (format
== deconFormat
[n1
].format
) {
201 return deconFormat
[n1
].desc
;
205 result
.appendFormat("? %08x", format
);
209 enum vpp_rotate
halTransformToHWRot(uint32_t halTransform
)
211 switch (halTransform
) {
212 case HAL_TRANSFORM_FLIP_H
:
213 return VPP_ROT_YFLIP
;
214 case HAL_TRANSFORM_FLIP_V
:
215 return VPP_ROT_XFLIP
;
216 case HAL_TRANSFORM_ROT_180
:
218 case HAL_TRANSFORM_ROT_90
:
220 case (HAL_TRANSFORM_ROT_90
|HAL_TRANSFORM_FLIP_H
):
222 * HAL: HAL_TRANSFORM_FLIP_H -> HAL_TRANSFORM_ROT_90
223 * VPP: ROT_90 -> XFLIP
225 return VPP_ROT_90_XFLIP
;
226 case (HAL_TRANSFORM_ROT_90
|HAL_TRANSFORM_FLIP_V
):
228 * HAL: HAL_TRANSFORM_FLIP_V -> HAL_TRANSFORM_ROT_90
229 * VPP: ROT_90 -> YFLIP
231 return VPP_ROT_90_YFLIP
;
232 case HAL_TRANSFORM_ROT_270
:
235 return VPP_ROT_NORMAL
;
239 ExynosDisplay::ExynosDisplay(int __unused numGSCs
)
242 mPanelType(PANEL_LEGACY
),
243 mDSCHSliceNum(WINUPDATE_DSC_H_SLICE_NUM
),
244 mDSCYSliceSize(WINUPDATE_DSC_Y_SLICE_SIZE
),
253 mGrallocModule(NULL
),
254 mLastFbWindow(NO_FB_NEEDED
),
255 mVirtualOverlayFlag(0),
256 mBypassSkipStaticLayer(false),
259 mHasDrmSurface(false),
265 mForceOverlayLayerIndex(-1),
269 mMaxWindowOverlapCnt(NUM_HW_WINDOWS
),
270 mUseSecureDMA(false),
271 mExternalMPPDstFormat(HAL_PIXEL_FORMAT_RGBX_8888
),
272 mSkipStaticInitFlag(false),
274 mLastRetireFenceFd(-1),
275 mFbPreAssigned(false),
276 mActiveConfigIndex(0),
279 memset(mLastMPPMap
, 0, sizeof(mLastMPPMap
));
280 memset(mLastHandles
, 0, sizeof(mLastHandles
));
281 memset(&mLastConfigData
, 0, sizeof(mLastConfigData
));
282 memset(mLastLayerHandles
, 0, sizeof(mLastLayerHandles
));
283 memset(&mFbUpdateRegion
, 0, sizeof(mFbUpdateRegion
));
285 mPreProcessedInfo
.mHasDrmSurface
= false;
286 mCheckIntMPP
= new ExynosMPPModule(NULL
, MPP_VGR
, 0);
288 mWinData
= (struct decon_win_config_data
*)malloc(sizeof(*mWinData
));
289 if (mWinData
== NULL
)
290 DISPLAY_LOGE("Fail to allocate mWinData");
292 ExynosDisplay::ExynosDisplay(uint32_t type
, struct exynos5_hwc_composer_device_1_t
*pdev
)
295 mPanelType(PANEL_LEGACY
),
296 mDSCHSliceNum(WINUPDATE_DSC_H_SLICE_NUM
),
297 mDSCYSliceSize(WINUPDATE_DSC_Y_SLICE_SIZE
),
306 mGrallocModule(NULL
),
307 mLastFbWindow(NO_FB_NEEDED
),
308 mVirtualOverlayFlag(0),
309 mBypassSkipStaticLayer(false),
312 mHasDrmSurface(false),
318 mForceOverlayLayerIndex(-1),
322 mMaxWindowOverlapCnt(NUM_HW_WINDOWS
),
323 mUseSecureDMA(false),
324 mExternalMPPDstFormat(HAL_PIXEL_FORMAT_RGBX_8888
),
325 mSkipStaticInitFlag(false),
327 mLastRetireFenceFd(-1),
328 mFbPreAssigned(false),
329 mActiveConfigIndex(0),
332 memset(mLastMPPMap
, 0, sizeof(mLastMPPMap
));
333 memset(mLastHandles
, 0, sizeof(mLastHandles
));
334 memset(&mLastConfigData
, 0, sizeof(mLastConfigData
));
335 memset(mLastLayerHandles
, 0, sizeof(mLastLayerHandles
));
338 case EXYNOS_VIRTUAL_DISPLAY
:
339 mDisplayName
= android::String8("VirtualDisplay");
341 case EXYNOS_EXTERNAL_DISPLAY
:
342 mDisplayName
= android::String8("ExternalDisplay");
344 case EXYNOS_PRIMARY_DISPLAY
:
345 mDisplayName
= android::String8("PrimaryDisplay");
347 #if defined(USES_DUAL_DISPLAY)
348 case EXYNOS_SECONDARY_DISPLAY
:
349 mDisplayName
= android::String8("SecondaryDisplay");
353 mDisplayName
= android::String8("Unknown");
356 memset(&mFbUpdateRegion
, 0, sizeof(mFbUpdateRegion
));
358 mPreProcessedInfo
.mHasDrmSurface
= false;
359 mCheckIntMPP
= new ExynosMPPModule(NULL
, MPP_VGR
, 0);
361 mWinData
= (struct decon_win_config_data
*)malloc(sizeof(*mWinData
));
362 if (mWinData
== NULL
)
363 DISPLAY_LOGE("Fail to allocate mWinData");
366 ExynosDisplay::~ExynosDisplay()
368 if (!mLayerInfos
.isEmpty()) {
369 for (size_t i
= 0; i
< mLayerInfos
.size(); i
++) {
370 delete mLayerInfos
[i
];
374 if (mCheckIntMPP
!= NULL
) {
379 if (mWinData
!= NULL
)
383 int ExynosDisplay::prepare(hwc_display_contents_1_t
*contents
)
386 DISPLAY_LOGD(eDebugDefault
, "preparing %u layers for FIMD", contents
->numHwLayers
);
389 skipStaticLayers(contents
);
391 if (mVirtualOverlayFlag
)
395 mFbWindow
= NO_FB_NEEDED
;
400 int ExynosDisplay::set(hwc_display_contents_1_t
*contents
)
402 hwc_layer_1_t
*fb_layer
= NULL
;
405 if (mFbWindow
!= NO_FB_NEEDED
) {
406 if (contents
->numHwLayers
>= 1 &&
407 contents
->hwLayers
[contents
->numHwLayers
- 1].compositionType
== HWC_FRAMEBUFFER_TARGET
)
408 fb_layer
= &contents
->hwLayers
[contents
->numHwLayers
- 1];
410 if (CC_UNLIKELY(!fb_layer
)) {
411 DISPLAY_LOGE("framebuffer target expected, but not provided");
414 DISPLAY_LOGD(eDebugDefault
, "framebuffer target buffer:");
415 dumpLayer(eDebugDefault
, fb_layer
);
421 fence
= postFrame(contents
);
426 #if defined(USES_DUAL_DISPLAY)
427 if (mType
!= EXYNOS_SECONDARY_DISPLAY
)
431 fence
= clearDisplay();
435 * WIN_CONFIG is skipped, not error
438 if (mLastRetireFenceFd
>= 0) {
439 int dup_fd
= dup(mLastRetireFenceFd
);
442 mLastRetireFenceFd
= dup_fd
;
443 dupFence(fence
, contents
);
445 DISPLAY_LOGW("mLastRetireFenceFd dup failed: %s", strerror(errno
));
446 mLastRetireFenceFd
= -1;
449 ALOGE("WIN_CONFIG is skipped, but mLastRetireFenceFd is not valid");
452 mLastRetireFenceFd
= fence
;
453 dupFence(fence
, contents
);
455 #if defined(USES_DUAL_DISPLAY)
462 void ExynosDisplay::dupFence(int fence
, hwc_display_contents_1_t
*contents
)
464 if (contents
== NULL
)
467 for (size_t i
= 0; i
< contents
->numHwLayers
; i
++) {
468 hwc_layer_1_t
&layer
= contents
->hwLayers
[i
];
469 private_handle_t
*handle
= NULL
;
470 if (layer
.handle
!= NULL
)
471 handle
= private_handle_t::dynamicCast(layer
.handle
);
473 if ((mVirtualOverlayFlag
== true) && (layer
.compositionType
== HWC_OVERLAY
) &&
474 ((handle
!= NULL
) && (getDrmMode(handle
->flags
) == NO_DRM
)) &&
475 (mFirstFb
<= i
) && (i
<= mLastFb
))
478 if (!(layer
.flags
& HWC_SKIP_RENDERING
) && ((layer
.compositionType
== HWC_OVERLAY
) ||
479 ((mFbNeeded
== true || this->mVirtualOverlayFlag
) && layer
.compositionType
== HWC_FRAMEBUFFER_TARGET
))) {
480 int dup_fd
= dup(fence
);
481 DISPLAY_LOGD(eDebugFence
, "%d layer[type: %d, dst: %d, %d, %d, %d] fence is duplicated(%d)",
482 i
, layer
.compositionType
,
483 layer
.displayFrame
.left
, layer
.displayFrame
.top
,
484 layer
.displayFrame
.right
, layer
.displayFrame
.bottom
,
487 DISPLAY_LOGW("release fence dup failed: %s", strerror(errno
));
488 if (mLayerInfos
[i
]->mInternalMPP
!= NULL
) {
489 ExynosMPPModule
*exynosMPP
= mLayerInfos
[i
]->mInternalMPP
;
490 if (mLayerInfos
[i
]->mInternalMPP
->mDstBufFence
[0] >= 0)
491 close(mLayerInfos
[i
]->mInternalMPP
->mDstBufFence
[0]);
492 exynosMPP
->mDstBufFence
[0] = dup(fence
);
494 if (mLayerInfos
[i
]->mExternalMPP
!= NULL
) {
495 ExynosMPPModule
*exysnosMPP
= mLayerInfos
[i
]->mExternalMPP
;
496 if (exysnosMPP
->mDstBufFence
[exysnosMPP
->mCurrentBuf
] >= 0) {
497 close (exysnosMPP
->mDstBufFence
[exysnosMPP
->mCurrentBuf
]);
498 exysnosMPP
->mDstBufFence
[exysnosMPP
->mCurrentBuf
] = -1;
500 exysnosMPP
->mDstBufFence
[exysnosMPP
->mCurrentBuf
] = dup_fd
;
501 exysnosMPP
->mCurrentBuf
= (exysnosMPP
->mCurrentBuf
+ 1) % exysnosMPP
->mNumAvailableDstBuffers
;
503 if (this->mVirtualOverlayFlag
&& (layer
.compositionType
== HWC_FRAMEBUFFER_TARGET
)) {
504 if (layer
.releaseFenceFd
>= 0)
505 close(layer
.releaseFenceFd
);
507 layer
.releaseFenceFd
= dup_fd
;
512 #if defined(USES_DUAL_DISPLAY)
513 if (mType
== EXYNOS_SECONDARY_DISPLAY
)
514 contents
->retireFenceFd
= dup(fence
);
516 contents
->retireFenceFd
= fence
;
518 contents
->retireFenceFd
= fence
;
522 void ExynosDisplay::dump(android::String8
& result
)
525 " type | handle | color | blend | pa | format | position | size | intMPP | extMPP \n"
526 "----------+--------------|----------+-------+----+---------------+---------------+----------------------------------\n");
527 // 8_______ | 12__________ | 8_______ | 5____ | 2_ | 13___________ | [5____,5____] | [5____,5____] | [2_,2_] | [2_,2_]\n"
529 for (size_t i
= 0; i
< NUM_HW_WINDOWS
; i
++) {
530 struct decon_win_config
&config
= mLastConfigData
.config
[i
];
531 if ((config
.state
== config
.DECON_WIN_STATE_DISABLED
) &&
532 (mLastMPPMap
[i
].internal_mpp
.type
== -1) &&
533 (mLastMPPMap
[i
].external_mpp
.type
== -1)){
534 result
.appendFormat(" %8s | %12s | %8s | %5s | %2s | %13s | %13s | %13s",
535 "OVERLAY", "-", "-", "-", "-", "-", "-", "-");
538 if (config
.state
== config
.DECON_WIN_STATE_COLOR
)
539 result
.appendFormat(" %8s | %12s | %8x | %5s | %2s | %13s", "COLOR",
540 "-", config
.color
, "-", "-", "-");
542 result
.appendFormat(" %8s | %12" PRIxPTR
" | %8s | %5x | %2x | %13s",
543 mLastFbWindow
== i
? "FB" : "OVERLAY",
544 intptr_t(mLastHandles
[i
]),
545 "-", config
.blending
, config
.plane_alpha
, deconFormat2str(config
.format
));
547 result
.appendFormat(" | [%5d,%5d] | [%5u,%5u]", config
.dst
.x
, config
.dst
.y
,
548 config
.dst
.w
, config
.dst
.h
);
550 if (mLastMPPMap
[i
].internal_mpp
.type
== -1) {
551 result
.appendFormat(" | [%2s,%2s]", "-", "-");
553 result
.appendFormat(" | [%2d,%2d]", mLastMPPMap
[i
].internal_mpp
.type
, mLastMPPMap
[i
].internal_mpp
.index
);
556 if (mLastMPPMap
[i
].external_mpp
.type
== -1) {
557 result
.appendFormat(" | [%2s,%2s]", "-", "-");
559 result
.appendFormat(" | [%2d,%2d]", mLastMPPMap
[i
].external_mpp
.type
, mLastMPPMap
[i
].external_mpp
.index
);
565 void ExynosDisplay::freeMPP()
569 void ExynosDisplay::doPreProcessing(hwc_display_contents_1_t
* contents
)
571 mPreProcessedInfo
.mHasDrmSurface
= false;
572 mForceOverlayLayerIndex
= -1;
573 this->mHasDrmSurface
= false;
575 mLayersNeedScaling
= false;
577 for (size_t i
= 0; i
< contents
->numHwLayers
; i
++) {
578 hwc_layer_1_t
&layer
= contents
->hwLayers
[i
];
580 private_handle_t
*h
= private_handle_t::dynamicCast(layer
.handle
);
581 if (h
->flags
& GRALLOC_USAGE_PROTECTED
) {
582 mPreProcessedInfo
.mHasDrmSurface
= true;
583 this->mHasDrmSurface
= true;
584 mForceOverlayLayerIndex
= i
;
586 if (!isFormatRgb(h
->format
)) {
590 mLayersNeedScaling
= true;
595 void ExynosDisplay::allocateLayerInfos(hwc_display_contents_1_t
* contents
)
597 if (contents
== NULL
)
600 if (!mLayerInfos
.isEmpty()) {
601 for (size_t i
= 0; i
< mLayerInfos
.size(); i
++) {
602 delete mLayerInfos
[i
];
607 for (size_t i
= 0; i
< contents
->numHwLayers
; i
++) {
608 ExynosLayerInfo
*layerInfo
= new ExynosLayerInfo();
609 memset(layerInfo
, 0, sizeof(ExynosLayerInfo
));
610 layerInfo
->mDmaType
= -1;
611 mLayerInfos
.push(layerInfo
);
614 mForceFb
= mHwc
->force_gpu
;
616 doPreProcessing(contents
);
619 void ExynosDisplay::dumpLayerInfo(android::String8
& result
)
621 if (!mLayerInfos
.isEmpty()) {
623 " type | CheckOverlayFlag | CheckMPPFlag | Comp | mWinIndex | mDmaType | mIntMPP | mExtMPP \n"
624 "------------+------------------+--------------+------+-----------+----------+-----------+----------\n");
625 // 10________ | 8_______ | 8_______ | 3__ | 9________ | 8_______ | [3__, 2_] | [3__, 2_]\n"
626 for (size_t i
= 0; i
< mLayerInfos
.size(); i
++) {
627 unsigned int type
= mLayerInfos
[i
]->compositionType
;
628 static char const* compositionTypeName
[] = {
635 if (type
>= NELEM(compositionTypeName
))
636 type
= NELEM(compositionTypeName
) - 1;
638 " %10s | 0x%8x | 0x%8x | %1s | %9d | %8d",
639 compositionTypeName
[type
],
640 mLayerInfos
[i
]->mCheckOverlayFlag
, mLayerInfos
[i
]->mCheckMPPFlag
,
641 mLayerInfos
[i
]->mCompressed
? "Y" : "N",
642 mLayerInfos
[i
]->mWindowIndex
, mLayerInfos
[i
]->mDmaType
);
644 if (mLayerInfos
[i
]->mInternalMPP
== NULL
)
645 result
.appendFormat(" | [%3s, %2s]", "-", "-");
647 result
.appendFormat(" | [%3s, %2d]", mLayerInfos
[i
]->mInternalMPP
->getName().string(), mLayerInfos
[i
]->mInternalMPP
->mIndex
);
650 if (mLayerInfos
[i
]->mExternalMPP
== NULL
)
651 result
.appendFormat(" | [%3s, %2s]", "-", "-");
653 result
.appendFormat(" | [%3s, %2d]", mLayerInfos
[i
]->mExternalMPP
->getName().string(), mLayerInfos
[i
]->mExternalMPP
->mIndex
);
661 bool ExynosDisplay::handleTotalBandwidthOverload(hwc_display_contents_1_t
*contents
)
663 bool changed
= false;
665 if (mHwc
->totPixels
>= FIMD_TOTAL_BW_LIMIT
) {
668 for (int i
= mFirstFb
- 1; i
>= 0; i
--) {
669 if (mForceOverlayLayerIndex
== 0 && i
== 0)
671 hwc_layer_1_t
&layer
= contents
->hwLayers
[i
];
672 layer
.compositionType
= HWC_FRAMEBUFFER
;
673 mLayerInfos
[i
]->compositionType
= layer
.compositionType
;
674 mLayerInfos
[i
]->mCheckOverlayFlag
|= eInsufficientBandwidth
;
675 mLayerInfos
[i
]->mInternalMPP
= NULL
;
676 mLayerInfos
[i
]->mExternalMPP
= NULL
;
677 mFirstFb
= (size_t)i
;
678 mHwc
->totPixels
-= WIDTH(layer
.displayFrame
) * HEIGHT(layer
.displayFrame
);
679 if (mHwc
->totPixels
< FIMD_TOTAL_BW_LIMIT
)
682 if (mHwc
->totPixels
>= FIMD_TOTAL_BW_LIMIT
) {
683 for (size_t i
= mLastFb
+ 1; i
< contents
->numHwLayers
- 1; i
++) {
684 hwc_layer_1_t
&layer
= contents
->hwLayers
[i
];
685 layer
.compositionType
= HWC_FRAMEBUFFER
;
686 mLayerInfos
[i
]->compositionType
= layer
.compositionType
;
687 mLayerInfos
[i
]->mCheckOverlayFlag
|= eInsufficientBandwidth
;
688 mLayerInfos
[i
]->mInternalMPP
= NULL
;
689 mLayerInfos
[i
]->mExternalMPP
= NULL
;
691 mHwc
->totPixels
-= WIDTH(layer
.displayFrame
) * HEIGHT(layer
.displayFrame
);
692 if (mHwc
->totPixels
< FIMD_TOTAL_BW_LIMIT
)
697 for (size_t i
= 0; i
< contents
->numHwLayers
; i
++) {
698 hwc_layer_1_t
&layer
= contents
->hwLayers
[i
];
699 if (layer
.compositionType
== HWC_OVERLAY
&&
700 mForceOverlayLayerIndex
!= (int)i
) {
701 layer
.compositionType
= HWC_FRAMEBUFFER
;
702 mLastFb
= max(mLastFb
, i
);
703 mLayerInfos
[i
]->compositionType
= layer
.compositionType
;
704 mLayerInfos
[i
]->mCheckOverlayFlag
|= eInsufficientBandwidth
;
705 mLayerInfos
[i
]->mInternalMPP
= NULL
;
706 mLayerInfos
[i
]->mExternalMPP
= NULL
;
709 mHwc
->totPixels
+= mXres
* mYres
;
711 mHwc
->totPixels
-= WIDTH(layer
.displayFrame
) * HEIGHT(layer
.displayFrame
);
712 if (mHwc
->totPixels
< FIMD_TOTAL_BW_LIMIT
)
716 if (mForceOverlayLayerIndex
== 0)
727 int ExynosDisplay::clearDisplay()
729 struct decon_win_config_data win_data
;
730 memset(&win_data
, 0, sizeof(win_data
));
732 int ret
= ioctl(this->mDisplayFd
, S3CFB_WIN_CONFIG
, &win_data
);
733 LOG_ALWAYS_FATAL_IF(ret
< 0,
734 "%s ioctl S3CFB_WIN_CONFIG failed to clear screen: %s",
735 mDisplayName
.string(), strerror(errno
));
736 // the causes of an empty config failing are all unrecoverable
738 return win_data
.fence
;
741 int ExynosDisplay::getCompModeSwitch()
743 unsigned int tot_win_size
= 0, updateFps
= 0;
744 unsigned int lcd_size
= this->mXres
* this->mYres
;
745 uint64_t TimeStampDiff
;
748 if (!mHwc
->hwc_ctrl
.dynamic_recomp_mode
) {
749 mHwc
->LastModeSwitchTimeStamp
= 0;
750 mHwc
->CompModeSwitch
= NO_MODE_SWITCH
;
754 /* initialize the Timestamps */
755 if (!mHwc
->LastModeSwitchTimeStamp
) {
756 mHwc
->LastModeSwitchTimeStamp
= mHwc
->LastUpdateTimeStamp
;
757 mHwc
->CompModeSwitch
= NO_MODE_SWITCH
;
761 /* If video layer is there, skip the mode switch */
762 if (mYuvLayers
|| mLayersNeedScaling
) {
763 if (mHwc
->CompModeSwitch
!= HWC_2_GLES
) {
766 mHwc
->CompModeSwitch
= GLES_2_HWC
;
767 mHwc
->updateCallCnt
= 0;
768 mHwc
->LastModeSwitchTimeStamp
= mHwc
->LastUpdateTimeStamp
;
769 DISPLAY_LOGI("[DYNAMIC_RECOMP] GLES_2_HWC by video layer");
774 /* Mode Switch is not required if total pixels are not more than the threshold */
775 if ((uint32_t)mHwc
->incomingPixels
<= lcd_size
* HWC_FIMD_BW_TH
) {
776 if (mHwc
->CompModeSwitch
!= HWC_2_GLES
) {
779 mHwc
->CompModeSwitch
= GLES_2_HWC
;
780 mHwc
->updateCallCnt
= 0;
781 mHwc
->LastModeSwitchTimeStamp
= mHwc
->LastUpdateTimeStamp
;
782 DISPLAY_LOGI("[DYNAMIC_RECOMP] GLES_2_HWC by BW check");
788 * There will be at least one composition call per one minute (because of time update)
789 * To minimize the analysis overhead, just analyze it once in a second
791 TimeStampDiff
= systemTime(SYSTEM_TIME_MONOTONIC
) - mHwc
->LastModeSwitchTimeStamp
;
794 * previous CompModeSwitch was GLES_2_HWC: check fps every 250ms from LastModeSwitchTimeStamp
795 * previous CompModeSwitch was HWC_2_GLES: check immediately
797 if ((mHwc
->CompModeSwitch
!= HWC_2_GLES
) && (TimeStampDiff
< (VSYNC_INTERVAL
* 15))) {
800 mHwc
->LastModeSwitchTimeStamp
= mHwc
->LastUpdateTimeStamp
;
801 if ((mHwc
->update_event_cnt
!= 1) && // This is not called by hwc_update_stat_thread
802 (mHwc
->CompModeSwitch
== HWC_2_GLES
) && (mHwc
->updateCallCnt
== 1)) {
803 DISPLAY_LOGI("[DYNAMIC_RECOMP] first frame after HWC_2_GLES");
804 updateFps
= HWC_FPS_TH
;
806 Temp
= (VSYNC_INTERVAL
* 60) / TimeStampDiff
;
807 updateFps
= (int)(mHwc
->updateCallCnt
* Temp
+ 0.5);
809 mHwc
->updateCallCnt
= 0;
812 * If FPS is lower than HWC_FPS_TH, try to switch the mode to GLES
814 if (updateFps
< HWC_FPS_TH
) {
815 if (mHwc
->CompModeSwitch
!= HWC_2_GLES
) {
816 mHwc
->CompModeSwitch
= HWC_2_GLES
;
817 DISPLAY_LOGI("[DYNAMIC_RECOMP] HWC_2_GLES by low FPS(%d)", updateFps
);
823 if (mHwc
->CompModeSwitch
== HWC_2_GLES
) {
824 mHwc
->CompModeSwitch
= GLES_2_HWC
;
825 DISPLAY_LOGI("[DYNAMIC_RECOMP] GLES_2_HWC by high FPS(%d)", updateFps
);
835 int32_t ExynosDisplay::getDisplayAttributes(const uint32_t attribute
, uint32_t __unused config
)
838 case HWC_DISPLAY_VSYNC_PERIOD
:
839 return this->mVsyncPeriod
;
841 case HWC_DISPLAY_WIDTH
:
842 #if defined(USES_DUAL_DISPLAY)
843 if ((mType
== EXYNOS_PRIMARY_DISPLAY
) || (mType
== EXYNOS_SECONDARY_DISPLAY
))
844 return this->mXres
/2;
851 case HWC_DISPLAY_HEIGHT
:
854 case HWC_DISPLAY_DPI_X
:
857 case HWC_DISPLAY_DPI_Y
:
861 DISPLAY_LOGE("unknown display attribute %u", attribute
);
866 bool ExynosDisplay::isOverlaySupportedByIDMA(hwc_layer_1_t __unused
&layer
, size_t __unused index
)
868 if (isCompressed(layer
))
874 void ExynosDisplay::getIDMAMinSize(hwc_layer_1_t __unused
&layer
, int *w
, int *h
)
880 bool ExynosDisplay::isOverlaySupported(hwc_layer_1_t
&layer
, size_t index
, bool useVPPOverlay
,
881 ExynosMPPModule
** supportedInternalMPP
, ExynosMPPModule
** supportedExternalMPP
)
885 ExynosMPPModule
* transitionInternalMPP
= NULL
;
886 private_handle_t
*handle
= NULL
;
887 int handleFormat
= 0;
888 bool firstFrameFramebufferTarget
= false;
890 DISPLAY_LOGD(eDebugOverlaySupported
, "isOverlaySupported:: index(%d), useVPPOverlay(%d)", index
, useVPPOverlay
);
892 if (layer
.flags
& HWC_SKIP_LAYER
) {
893 mLayerInfos
[index
]->mCheckOverlayFlag
|= eSkipLayer
;
894 DISPLAY_LOGD(eDebugOverlaySupported
, "\tlayer %u: skipping", index
);
898 if (!layer
.planeAlpha
)
901 if (index
== 0 && layer
.planeAlpha
< 255) {
902 DISPLAY_LOGD(eDebugOverlaySupported
, "\tlayer %u: eUnsupportedPlaneAlpha", index
);
903 mLayerInfos
[index
]->mCheckOverlayFlag
|= eUnsupportedPlaneAlpha
;
908 handle
= private_handle_t::dynamicCast(layer
.handle
);
909 handleFormat
= handle
->format
;
912 if ((layer
.compositionType
!= HWC_FRAMEBUFFER_TARGET
) && !handle
) {
913 DISPLAY_LOGD(eDebugOverlaySupported
, "\tlayer %u: handle is NULL, type is %d", index
, layer
.compositionType
);
914 mLayerInfos
[index
]->mCheckOverlayFlag
|= eInvalidHandle
;
918 if (!handle
&& (layer
.compositionType
== HWC_FRAMEBUFFER_TARGET
)) {
919 firstFrameFramebufferTarget
= true;
920 handleFormat
= HAL_PIXEL_FORMAT_RGBA_8888
;
923 if (handle
&& (getDrmMode(handle
->flags
) == NO_DRM
) &&
924 (isFloat(layer
.sourceCropf
.left
) || isFloat(layer
.sourceCropf
.top
) ||
925 isFloat(layer
.sourceCropf
.right
- layer
.sourceCropf
.left
) ||
926 isFloat(layer
.sourceCropf
.bottom
- layer
.sourceCropf
.top
))) {
927 if (isSourceCropfSupported(layer
) == false)
931 if (!isBlendingSupported(layer
.blending
)) {
932 DISPLAY_LOGD(eDebugOverlaySupported
, "\tlayer %u: blending %d not supported", index
, layer
.blending
);
933 mLayerInfos
[index
]->mCheckOverlayFlag
|= eUnsupportedBlending
;
937 int32_t bpp
= formatToBpp(handleFormat
);
938 int32_t left
= max(layer
.displayFrame
.left
, 0);
939 int32_t right
= min(layer
.displayFrame
.right
, mXres
);
940 uint32_t visible_width
= 0;
943 ((layer
.displayFrame
.left
% 2 != 0) || (layer
.displayFrame
.right
% 2 != 0))) {
944 DISPLAY_LOGD(eDebugOverlaySupported
, "\tlayer %u: eNotAlignedDstPosition", index
);
945 mLayerInfos
[index
]->mCheckOverlayFlag
|= eNotAlignedDstPosition
;
949 visible_width
= (right
- left
) * bpp
/ 8;
950 if (visible_width
< BURSTLEN_BYTES
) {
951 #ifdef USE_DRM_BURST_LEN
952 if (handle
&& (getDrmMode(handle
->flags
) != NO_DRM
)) {
953 if (visible_width
< DRM_BURSTLEN_BYTES
) {
954 DISPLAY_LOGD(eDebugOverlaySupported
, "\tlayer %u: visible area is too narrow", index
);
955 mLayerInfos
[index
]->mCheckOverlayFlag
|= eUnsupportedDstWidth
;
960 DISPLAY_LOGD(eDebugOverlaySupported
, "\tlayer %u: visible area is too narrow", index
);
961 mLayerInfos
[index
]->mCheckOverlayFlag
|= eUnsupportedDstWidth
;
963 #ifdef USE_DRM_BURST_LEN
968 if (!isProcessingRequired(layer
) && !useVPPOverlay
)
971 hwc_layer_1_t extMPPOutLayer
= layer
;
972 int originalHandleFormt
= handleFormat
;
973 int dst_format
= handleFormat
;
974 bool isBothMPPUsed
= isBothMPPProcessingRequired(layer
, &extMPPOutLayer
);
975 DISPLAY_LOGD(eDebugOverlaySupported
, "isOverlaySupported:: index(%d), isBothMPPUsed(%d)", index
, isBothMPPUsed
);
978 if ((*supportedInternalMPP
!= NULL
) && (*supportedExternalMPP
!= NULL
))
981 if ((*supportedInternalMPP
!= NULL
) || (*supportedExternalMPP
!= NULL
&& !useVPPOverlay
))
985 if (*supportedExternalMPP
== NULL
&& isBothMPPUsed
)
987 /* extMPPOutLayer is output of ExtMPP
988 * The output of ExtMPP is the input of IntMPP
990 if (!isFormatRgb(handleFormat
) &&
991 (WIDTH(extMPPOutLayer
.displayFrame
) % mCheckIntMPP
->getCropWidthAlign(layer
) != 0 ||
992 HEIGHT(extMPPOutLayer
.displayFrame
) % mCheckIntMPP
->getCropHeightAlign(layer
) != 0 ||
993 !(mCheckIntMPP
->isFormatSupportedByMPP(handleFormat
)) ||
994 !(mCheckIntMPP
->isCSCSupportedByMPP(handleFormat
, HAL_PIXEL_FORMAT_RGBX_8888
, layer
.dataSpace
))))
995 dst_format
= mExternalMPPDstFormat
;
997 /* extMPPOutLayer is output of ExtMPP */
998 for (size_t i
= 0; i
< mExternalMPPs
.size(); i
++)
1000 ExynosMPPModule
* externalMPP
= mExternalMPPs
[i
];
1001 if (externalMPP
->mState
== MPP_STATE_FREE
) {
1002 ret
= externalMPP
->isProcessingSupported(extMPPOutLayer
, dst_format
);
1004 *supportedExternalMPP
= externalMPP
;
1007 mLayerInfos
[index
]->mCheckMPPFlag
|= -ret
;
1012 /* Can't find valid externalMPP */
1013 if (*supportedExternalMPP
== NULL
) {
1014 DISPLAY_LOGD(eDebugOverlaySupported
, "\tlayer %u: Can't find valid externalMPP", index
);
1015 mLayerInfos
[index
]->mCheckOverlayFlag
|= eInsufficientMPP
;
1019 if (*supportedInternalMPP
== NULL
) {
1020 for (size_t i
= 0; i
< mInternalMPPs
.size(); i
++)
1022 ExynosMPPModule
* internalMPP
= mInternalMPPs
[i
];
1023 hwc_layer_1_t extMPPTempOutLayer
= extMPPOutLayer
;
1024 if (isBothMPPUsed
) {
1025 if (internalMPP
->mType
== MPP_VPP_G
)
1027 /* extMPPOutLayer is output of ExtMPP
1028 * The output of ExtMPP is the input of IntMPP
1030 if (!isFormatRgb(handleFormat
) &&
1031 (WIDTH(extMPPTempOutLayer
.displayFrame
) % internalMPP
->getCropWidthAlign(layer
) != 0 ||
1032 HEIGHT(extMPPTempOutLayer
.displayFrame
) % internalMPP
->getCropHeightAlign(layer
) != 0 ||
1033 !(internalMPP
->isFormatSupportedByMPP(handleFormat
))))
1034 dst_format
= mExternalMPPDstFormat
;
1036 extMPPTempOutLayer
.sourceCropf
.left
= extMPPOutLayer
.displayFrame
.left
;
1037 extMPPTempOutLayer
.sourceCropf
.top
= extMPPOutLayer
.displayFrame
.top
;
1038 extMPPTempOutLayer
.sourceCropf
.right
= extMPPOutLayer
.displayFrame
.right
;
1039 extMPPTempOutLayer
.sourceCropf
.bottom
= extMPPOutLayer
.displayFrame
.bottom
;
1040 extMPPTempOutLayer
.displayFrame
.left
= layer
.displayFrame
.left
;
1041 extMPPTempOutLayer
.displayFrame
.top
= layer
.displayFrame
.top
;
1042 extMPPTempOutLayer
.displayFrame
.right
= layer
.displayFrame
.right
;
1043 extMPPTempOutLayer
.displayFrame
.bottom
= layer
.displayFrame
.bottom
;
1044 ((private_handle_t
*)extMPPTempOutLayer
.handle
)->format
= dst_format
;
1045 extMPPTempOutLayer
.transform
= 0;
1047 ExynosDisplay
*addedDisplay
= (mHwc
->hdmi_hpd
? (ExynosDisplay
*)mHwc
->externalDisplay
: (ExynosDisplay
*)mHwc
->virtualDisplay
);
1048 ExynosDisplay
*otherDisplay
= (mType
? (ExynosDisplay
*)mHwc
->primaryDisplay
: addedDisplay
);
1051 * If MPP was assigned to other Device in previous frame
1052 * then doesn't assign it untill it is cleared
1054 if ((internalMPP
->mState
== MPP_STATE_FREE
) &&
1055 (internalMPP
->mDisplay
== NULL
|| internalMPP
->mDisplay
== this)) {
1056 /* InternalMPP doesn't need to check dst_format. Set dst_format with source format */
1057 if (firstFrameFramebufferTarget
)
1060 ret
= internalMPP
->isProcessingSupported(extMPPTempOutLayer
, ((private_handle_t
*)extMPPTempOutLayer
.handle
)->format
);
1061 handle
->format
= originalHandleFormt
;
1064 *supportedInternalMPP
= internalMPP
;
1067 mLayerInfos
[index
]->mCheckMPPFlag
|= -ret
;
1069 } else if (internalMPP
->wasUsedByDisplay(otherDisplay
)) {
1070 DISPLAY_LOGD(eDebugOverlaySupported
, "\tlayer %u: internalMPP[%d, %d] was used by other device", index
, internalMPP
->mType
, internalMPP
->mIndex
);
1071 if (transitionInternalMPP
== NULL
)
1072 transitionInternalMPP
= internalMPP
;
1075 handle
->format
= originalHandleFormt
;
1079 if ((*supportedInternalMPP
== NULL
) && (useVPPOverlay
== true) && !isProcessingRequired(layer
)) {
1080 DISPLAY_LOGD(eDebugOverlaySupported
, "\tlayer %u: eInsufficientMPP", index
);
1081 mLayerInfos
[index
]->mCheckOverlayFlag
|= eInsufficientMPP
;
1082 if (transitionInternalMPP
!= NULL
) {
1083 DISPLAY_LOGD(eDebugOverlaySupported
, "\tlayer %u: internalMPP[%d, %d] transition is started", index
, transitionInternalMPP
->mType
, transitionInternalMPP
->mIndex
);
1084 transitionInternalMPP
->startTransition(this);
1089 /* Can't find valid internalMPP */
1090 if (isBothMPPProcessingRequired(layer
) && *supportedInternalMPP
== NULL
) {
1091 DISPLAY_LOGD(eDebugOverlaySupported
, "\tlayer %u: Can't find valid internalMPP", index
);
1092 if (transitionInternalMPP
!= NULL
) {
1093 DISPLAY_LOGD(eDebugOverlaySupported
, "\tlayer %u: internalMPP[%d, %d] transition is started", index
, transitionInternalMPP
->mType
, transitionInternalMPP
->mIndex
);
1094 transitionInternalMPP
->startTransition(this);
1096 mLayerInfos
[index
]->mCheckOverlayFlag
|= eInsufficientMPP
;
1100 if (*supportedExternalMPP
== NULL
) {
1101 for (size_t i
= 0; i
< mExternalMPPs
.size(); i
++)
1103 ExynosMPPModule
* externalMPP
= mExternalMPPs
[i
];
1104 int dst_format
= handleFormat
;
1105 if (!isFormatRgb(handleFormat
))
1106 dst_format
= mExternalMPPDstFormat
;
1108 if (externalMPP
->mState
== MPP_STATE_FREE
) {
1109 if (firstFrameFramebufferTarget
)
1112 ret
= externalMPP
->isProcessingSupported(layer
, dst_format
);
1114 *supportedExternalMPP
= externalMPP
;
1119 mLayerInfos
[index
]->mCheckMPPFlag
|= -ret
;
1125 if (*supportedExternalMPP
!= NULL
&& useVPPOverlay
== true && *supportedInternalMPP
== NULL
) {
1126 int originalHandleFormt
= handleFormat
;
1127 dst_format
= handleFormat
;
1128 if (!isFormatRgb(handleFormat
))
1129 dst_format
= mExternalMPPDstFormat
;
1130 for (size_t i
= 0; i
< mInternalMPPs
.size(); i
++)
1132 extMPPOutLayer
= layer
;
1133 /* extMPPOutLayer is output of ExtMPP
1134 * The output of ExtMPP is the input of IntMPP
1136 extMPPOutLayer
.sourceCropf
.left
= layer
.displayFrame
.left
;
1137 extMPPOutLayer
.sourceCropf
.top
= layer
.displayFrame
.top
;
1138 extMPPOutLayer
.sourceCropf
.right
= layer
.displayFrame
.right
;
1139 extMPPOutLayer
.sourceCropf
.bottom
= layer
.displayFrame
.bottom
;
1140 extMPPOutLayer
.transform
= 0;
1142 ((private_handle_t
*)extMPPOutLayer
.handle
)->format
= dst_format
;
1143 ExynosMPPModule
* internalMPP
= mInternalMPPs
[i
];
1146 * If MPP was assigned to other Device in previous frame
1147 * then doesn't assign it untill it is cleared
1149 if ((internalMPP
->mState
== MPP_STATE_FREE
) &&
1150 (internalMPP
->mDisplay
== NULL
|| internalMPP
->mDisplay
== this)) {
1151 if (firstFrameFramebufferTarget
)
1154 ret
= internalMPP
->isProcessingSupported(extMPPOutLayer
, ((private_handle_t
*)extMPPOutLayer
.handle
)->format
);
1155 handle
->format
= originalHandleFormt
;
1158 *supportedInternalMPP
= internalMPP
;
1161 mLayerInfos
[index
]->mCheckMPPFlag
|= -ret
;
1164 ExynosDisplay
*addedDisplay
= (mHwc
->hdmi_hpd
? (ExynosDisplay
*)mHwc
->externalDisplay
: (ExynosDisplay
*)mHwc
->virtualDisplay
);
1165 ExynosDisplay
*otherDisplay
= (mType
? (ExynosDisplay
*)mHwc
->primaryDisplay
: addedDisplay
);
1166 if (firstFrameFramebufferTarget
) {
1167 if ((internalMPP
->wasUsedByDisplay(otherDisplay
)) && (transitionInternalMPP
== NULL
))
1168 transitionInternalMPP
= internalMPP
;
1170 if ((internalMPP
->wasUsedByDisplay(otherDisplay
)) &&
1171 ((transitionInternalMPP
== NULL
) ||
1172 ((transitionInternalMPP
->isProcessingSupported(extMPPOutLayer
, ((private_handle_t
*)extMPPOutLayer
.handle
)->format
) < 0) &&
1173 (internalMPP
->isProcessingSupported(extMPPOutLayer
, ((private_handle_t
*)extMPPOutLayer
.handle
)->format
) > 0))))
1174 transitionInternalMPP
= internalMPP
;
1179 handle
->format
= originalHandleFormt
;
1183 /* Transit display for next frame */
1184 if ((*supportedInternalMPP
== NULL
) && (transitionInternalMPP
!= NULL
)) {
1185 DISPLAY_LOGD(eDebugOverlaySupported
, "\tlayer %u: internalMPP[%d, %d] transition is started", index
, transitionInternalMPP
->mType
, transitionInternalMPP
->mIndex
);
1186 transitionInternalMPP
->startTransition(this);
1189 /* Can't find valid MPP */
1190 DISPLAY_LOGD(eDebugOverlaySupported
, "\tlayer %u: can't find valid MPP", index
);
1191 mLayerInfos
[index
]->mCheckOverlayFlag
|= eInsufficientMPP
;
1196 void ExynosDisplay::configureHandle(private_handle_t
*handle
, size_t index
,
1197 hwc_layer_1_t
&layer
, int fence_fd
, decon_win_config
&cfg
)
1204 #ifdef HWC_SET_OPAQUE
1205 if ((layer
.flags
& HWC_SET_OPAQUE
) && handle
&& (handle
->format
== HAL_PIXEL_FORMAT_RGBA_8888
)
1206 && (layer
.compositionType
== HWC_OVERLAY
)) {
1207 handle
->format
= HAL_PIXEL_FORMAT_RGBX_8888
;
1211 hwc_frect_t
&sourceCrop
= layer
.sourceCropf
;
1212 hwc_rect_t
&displayFrame
= layer
.compositionType
== HWC_FRAMEBUFFER_TARGET
? mFbUpdateRegion
: layer
.displayFrame
;
1213 int32_t blending
= layer
.blending
;
1214 int32_t planeAlpha
= layer
.planeAlpha
;
1216 uint32_t w
= WIDTH(displayFrame
);
1217 uint32_t h
= HEIGHT(displayFrame
);
1218 uint8_t bpp
= formatToBpp(handle
->format
);
1219 uint32_t offset
= ((uint32_t)sourceCrop
.top
* handle
->stride
+ (uint32_t)sourceCrop
.left
) * bpp
/ 8;
1220 ExynosMPPModule
* internalMPP
= mLayerInfos
[index
]->mInternalMPP
;
1221 ExynosMPPModule
* externalMPP
= mLayerInfos
[index
]->mExternalMPP
;
1223 #ifdef USES_DECON_AFBC_DECODER
1224 cfg
.compression
= isCompressed(layer
);
1227 if (displayFrame
.left
< 0) {
1228 unsigned int crop
= -displayFrame
.left
;
1229 DISPLAY_LOGD(eDebugWinConfig
, "layer off left side of screen; cropping %u pixels from left edge",
1233 offset
+= crop
* bpp
/ 8;
1235 x
= displayFrame
.left
;
1238 if (displayFrame
.right
> this->mXres
) {
1239 unsigned int crop
= displayFrame
.right
- this->mXres
;
1240 DISPLAY_LOGD(eDebugWinConfig
, "layer off right side of screen; cropping %u pixels from right edge",
1245 if (displayFrame
.top
< 0) {
1246 unsigned int crop
= -displayFrame
.top
;
1247 DISPLAY_LOGD(eDebugWinConfig
, "layer off top side of screen; cropping %u pixels from top edge",
1251 offset
+= handle
->stride
* crop
* bpp
/ 8;
1253 y
= displayFrame
.top
;
1256 if (displayFrame
.bottom
> this->mYres
) {
1257 int crop
= displayFrame
.bottom
- this->mYres
;
1258 DISPLAY_LOGD(eDebugWinConfig
, "layer off bottom side of screen; cropping %u pixels from bottom edge",
1263 cfg
.fd_idma
[0] = handle
->fd
;
1264 cfg
.fd_idma
[1] = handle
->fd1
;
1265 cfg
.fd_idma
[2] = handle
->fd2
;
1266 if (mLayerInfos
[index
]->mDmaType
== -1) {
1267 cfg
.state
= cfg
.DECON_WIN_STATE_DISABLED
;
1269 cfg
.state
= cfg
.DECON_WIN_STATE_BUFFER
;
1270 cfg
.idma_type
= (decon_idma_type
)mLayerInfos
[index
]->mDmaType
;
1276 cfg
.dst
.f_w
= mXres
;
1277 cfg
.dst
.f_h
= mYres
;
1278 cfg
.format
= halFormatToS3CFormat(handle
->format
);
1280 cfg
.src
.f_w
= handle
->stride
;
1281 cfg
.src
.f_h
= handle
->vstride
;
1282 if (handle
->format
== HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_PRIV
) {
1283 if (handle
->fd2
>= 0) {
1284 void *metaData
= NULL
;
1285 int interlacedType
= -1;
1286 metaData
= mmap(0, 64, PROT_READ
|PROT_WRITE
, MAP_SHARED
, handle
->fd2
, 0);
1288 interlacedType
= *(int *)metaData
;
1290 interlacedType
= -1;
1292 if (interlacedType
== V4L2_FIELD_INTERLACED_TB
||
1293 interlacedType
== V4L2_FIELD_INTERLACED_BT
) {
1294 cfg
.src
.f_w
= handle
->stride
* 2;
1295 cfg
.src
.f_h
= handle
->vstride
/ 2;
1298 munmap(metaData
, 64);
1302 cfg
.src
.x
= (int)sourceCrop
.left
;
1303 cfg
.src
.y
= (int)sourceCrop
.top
;
1310 if (internalMPP
!= NULL
) {
1311 if (cfg
.src
.f_w
> (unsigned int)internalMPP
->getMaxWidth(layer
))
1312 cfg
.src
.f_w
= (unsigned int)internalMPP
->getMaxWidth(layer
);
1313 if (cfg
.src
.f_h
> (unsigned int)internalMPP
->getMaxHeight(layer
))
1314 cfg
.src
.f_h
= (unsigned int)internalMPP
->getMaxHeight(layer
);
1315 cfg
.src
.f_w
= ALIGN_DOWN((unsigned int)cfg
.src
.f_w
, internalMPP
->getSrcWidthAlign(layer
));
1316 cfg
.src
.f_h
= ALIGN_DOWN((unsigned int)cfg
.src
.f_h
, internalMPP
->getSrcHeightAlign(layer
));
1318 cfg
.src
.x
= ALIGN((unsigned int)sourceCrop
.left
, internalMPP
->getSrcXOffsetAlign(layer
));
1319 cfg
.src
.y
= ALIGN((unsigned int)sourceCrop
.top
, internalMPP
->getSrcYOffsetAlign(layer
));
1322 cfg
.src
.w
= WIDTH(sourceCrop
) - (cfg
.src
.x
- (uint32_t)sourceCrop
.left
);
1323 if (cfg
.src
.x
+ cfg
.src
.w
> cfg
.src
.f_w
)
1324 cfg
.src
.w
= cfg
.src
.f_w
- cfg
.src
.x
;
1325 cfg
.src
.h
= HEIGHT(sourceCrop
) - (cfg
.src
.y
- (uint32_t)sourceCrop
.top
);
1326 if (cfg
.src
.y
+ cfg
.src
.h
> cfg
.src
.f_h
)
1327 cfg
.src
.h
= cfg
.src
.f_h
- cfg
.src
.y
;
1329 if (internalMPP
!= NULL
) {
1330 if (cfg
.src
.w
> (unsigned int)internalMPP
->getMaxCropWidth(layer
))
1331 cfg
.src
.w
= (unsigned int)internalMPP
->getMaxCropWidth(layer
);
1332 if (cfg
.src
.h
> (unsigned int)internalMPP
->getMaxCropHeight(layer
))
1333 cfg
.src
.h
= (unsigned int)internalMPP
->getMaxCropHeight(layer
);
1334 cfg
.src
.w
= ALIGN_DOWN(cfg
.src
.w
, internalMPP
->getCropWidthAlign(layer
));
1335 cfg
.src
.h
= ALIGN_DOWN(cfg
.src
.h
, internalMPP
->getCropHeightAlign(layer
));
1338 if (isSrcCropFloat(layer
.sourceCropf
))
1340 if (internalMPP
!= NULL
) {
1341 exynos_mpp_img srcImg
;
1342 internalMPP
->adjustSourceImage(layer
, srcImg
);
1343 cfg
.src
.f_w
= srcImg
.fw
;
1344 cfg
.src
.f_h
= srcImg
.fh
;
1345 cfg
.src
.x
= srcImg
.x
;
1346 cfg
.src
.y
= srcImg
.y
;
1347 cfg
.src
.w
= srcImg
.w
;
1348 cfg
.src
.h
= srcImg
.h
;
1350 if (externalMPP
== NULL
)
1351 ALOGE("float sourceCrop should be handled by MPP");
1354 ALOGD("x = %7.1f, 0x%8x", sourceCrop
.left
, cfg
.src
.x
);
1355 ALOGD("y = %7.1f, 0x%8x", sourceCrop
.top
, cfg
.src
.y
);
1356 ALOGD("w = %7.1f, 0x%8x", sourceCrop
.right
- sourceCrop
.left
, cfg
.src
.w
);
1357 ALOGD("h = %7.1f, 0x%8x", sourceCrop
.bottom
- sourceCrop
.top
, cfg
.src
.h
);
1361 cfg
.blending
= halBlendingToS3CBlending(blending
);
1362 cfg
.fence_fd
= fence_fd
;
1363 cfg
.plane_alpha
= 255;
1364 if (planeAlpha
&& (planeAlpha
< 255)) {
1365 cfg
.plane_alpha
= planeAlpha
;
1367 if (mLayerInfos
[index
]->mInternalMPP
) {
1368 cfg
.vpp_parm
.rot
= (vpp_rotate
)halTransformToHWRot(layer
.transform
);
1369 cfg
.vpp_parm
.eq_mode
= isFullRangeColor(layer
) ? BT_601_WIDE
: BT_601_NARROW
;
1371 if ((!mLayerInfos
[index
]->mExternalMPP
&&
1372 (mHwc
->mS3DMode
== S3D_MODE_READY
|| mHwc
->mS3DMode
== S3D_MODE_RUNNING
) &&
1373 !isFormatRgb(handle
->format
)) &&
1374 mType
== EXYNOS_PRIMARY_DISPLAY
) {
1375 int S3DFormat
= getS3DFormat(mHwc
->mHdmiPreset
);
1376 if (S3DFormat
== S3D_SBS
)
1378 else if (S3DFormat
== S3D_TB
)
1382 /* transparent region coordinates is on source buffer */
1383 //getLayerRegion(layer, cfg.transparent_area, eTransparentRegion);
1384 cfg
.transparent_area
.x
+= cfg
.dst
.x
;
1385 cfg
.transparent_area
.y
+= cfg
.dst
.y
;
1387 /* opaque region coordinates is on screen */
1388 //getLayerRegion(layer, cfg.covered_opaque_area, eCoveredOpaqueRegion);
1390 if (isOpaque
&& (handle
->format
== HAL_PIXEL_FORMAT_RGBX_8888
)) {
1391 handle
->format
= HAL_PIXEL_FORMAT_RGBA_8888
;
1396 void ExynosDisplay::configureOverlay(hwc_layer_1_t
*layer
, size_t index
, decon_win_config
&cfg
)
1398 if (layer
->compositionType
== HWC_BACKGROUND
) {
1399 hwc_color_t color
= layer
->backgroundColor
;
1400 cfg
.state
= cfg
.DECON_WIN_STATE_COLOR
;
1401 cfg
.color
= (color
.r
<< 16) | (color
.g
<< 8) | color
.b
;
1404 cfg
.dst
.w
= this->mXres
;
1405 cfg
.dst
.h
= this->mYres
;
1408 private_handle_t
*handle
= private_handle_t::dynamicCast(layer
->handle
);
1409 hwc_frect_t originalCrop
= layer
->sourceCropf
;
1410 if (layer
->compositionType
== HWC_FRAMEBUFFER_TARGET
) {
1411 /* Adjust FbUpdateRegion */
1412 int minCropWidth
= 0;
1413 int minCropHeight
= 0;
1414 int cropWidthAlign
= 1;
1415 if (mLayerInfos
[index
]->mInternalMPP
!= NULL
) {
1416 minCropWidth
= mLayerInfos
[index
]->mInternalMPP
->getMinWidth(*layer
);
1417 minCropHeight
= mLayerInfos
[index
]->mInternalMPP
->getMinHeight(*layer
);
1418 cropWidthAlign
= mLayerInfos
[index
]->mInternalMPP
->getCropWidthAlign(*layer
);
1420 getIDMAMinSize(*layer
, &minCropWidth
, &minCropHeight
);
1422 #if defined(USES_DUAL_DISPLAY)
1423 int32_t minLeftPosition
= (mType
!= EXYNOS_SECONDARY_DISPLAY
)? 0:(mXres
/2);
1424 int32_t maxRightPosition
= (mType
== EXYNOS_PRIMARY_DISPLAY
)?(mXres
/2):mXres
;
1426 int32_t minLeftPosition
= 0;
1427 int32_t maxRightPosition
= mXres
;
1429 if (mFbUpdateRegion
.left
< minLeftPosition
) mFbUpdateRegion
.left
= minLeftPosition
;
1430 if (mFbUpdateRegion
.right
< minLeftPosition
) mFbUpdateRegion
.right
= minLeftPosition
;
1431 if (mFbUpdateRegion
.left
> maxRightPosition
) mFbUpdateRegion
.left
= maxRightPosition
;
1432 if (mFbUpdateRegion
.right
> maxRightPosition
) mFbUpdateRegion
.right
= maxRightPosition
;
1433 if (mFbUpdateRegion
.top
< 0) mFbUpdateRegion
.top
= 0;
1434 if (mFbUpdateRegion
.bottom
< 0) mFbUpdateRegion
.bottom
= 0;
1435 if (mFbUpdateRegion
.top
> mYres
) mFbUpdateRegion
.top
= mYres
;
1436 if (mFbUpdateRegion
.bottom
> mYres
) mFbUpdateRegion
.bottom
= mYres
;
1438 if ((WIDTH(mFbUpdateRegion
) % cropWidthAlign
) != 0) {
1439 mFbUpdateRegion
.left
= ALIGN_DOWN(mFbUpdateRegion
.left
, cropWidthAlign
);
1440 mFbUpdateRegion
.right
= ALIGN_UP(mFbUpdateRegion
.right
, cropWidthAlign
);
1442 if (WIDTH(mFbUpdateRegion
) < minCropWidth
) {
1443 #if defined(USES_DUAL_DISPLAY)
1444 if (mFbUpdateRegion
.left
+ minCropWidth
<= maxRightPosition
)
1445 mFbUpdateRegion
.right
= mFbUpdateRegion
.left
+ minCropWidth
;
1447 mFbUpdateRegion
.left
= mFbUpdateRegion
.right
- minCropWidth
;
1449 if (mFbUpdateRegion
.left
+ minCropWidth
<= mXres
)
1450 mFbUpdateRegion
.right
= mFbUpdateRegion
.left
+ minCropWidth
;
1452 mFbUpdateRegion
.left
= mFbUpdateRegion
.right
- minCropWidth
;
1455 if (HEIGHT(mFbUpdateRegion
) < minCropHeight
) {
1456 if (mFbUpdateRegion
.top
+ minCropHeight
<= mYres
)
1457 mFbUpdateRegion
.bottom
= mFbUpdateRegion
.top
+ minCropHeight
;
1459 mFbUpdateRegion
.top
= mFbUpdateRegion
.bottom
- minCropHeight
;
1462 if ((mFbUpdateRegion
.left
>= minLeftPosition
) && (mFbUpdateRegion
.top
>= 0) &&
1463 (mFbUpdateRegion
.right
<= maxRightPosition
) && (mFbUpdateRegion
.bottom
<= mYres
)) {
1464 #ifdef USES_DUAL_DISPLAY
1465 if (mType
== EXYNOS_SECONDARY_DISPLAY
) {
1466 layer
->sourceCropf
.left
= (double)mFbUpdateRegion
.left
- (mXres
/2);
1467 layer
->sourceCropf
.right
= (double)mFbUpdateRegion
.right
- (mXres
/2);
1469 layer
->sourceCropf
.left
= (double)mFbUpdateRegion
.left
;
1470 layer
->sourceCropf
.right
= (double)mFbUpdateRegion
.right
;
1473 layer
->sourceCropf
.left
= (double)mFbUpdateRegion
.left
;
1474 layer
->sourceCropf
.right
= (double)mFbUpdateRegion
.right
;
1476 layer
->sourceCropf
.top
= (double)mFbUpdateRegion
.top
;
1477 layer
->sourceCropf
.bottom
= (double)mFbUpdateRegion
.bottom
;
1479 mFbUpdateRegion
= layer
->displayFrame
;
1482 configureHandle(handle
, index
, *layer
, layer
->acquireFenceFd
, cfg
);
1483 layer
->sourceCropf
= originalCrop
;
1486 int ExynosDisplay::handleWindowUpdate(hwc_display_contents_1_t __unused
*contents
,
1487 struct decon_win_config __unused
*config
)
1490 int updatedWinCnt
= 0;
1491 int totalWinCnt
= 0;
1492 int bitsPerPixel
= 0;
1493 size_t winUpdateInfoIdx
;
1494 hwc_rect updateRect
= {this->mXres
, this->mYres
, 0, 0};
1495 hwc_rect currentRect
= {0, 0, 0, 0};
1496 bool burstLengthCheckDone
= false;
1497 int alignAdjustment
= 1;
1498 int intersectionWidth
= 0;
1504 #if defined(USES_DUAL_DISPLAY)
1505 return -eWindowUpdateDisabled
;
1509 char value
[PROPERTY_VALUE_MAX
];
1510 property_get("debug.hwc.winupdate", value
, "1");
1512 if (!(!strcmp(value
, "1") || !strcmp(value
, "true")))
1513 return -eWindowUpdateDisabled
;
1515 if (DECON_WIN_UPDATE_IDX
< 0)
1516 return -eWindowUpdateInvalidIndex
;
1517 winUpdateInfoIdx
= DECON_WIN_UPDATE_IDX
;
1519 if (contents
->flags
& HWC_GEOMETRY_CHANGED
)
1520 return -eWindowUpdateGeometryChanged
;
1522 if (mPanelType
== PANEL_DSC
) {
1523 xAlign
= this->mXres
/ mDSCHSliceNum
;
1524 wAlign
= this->mXres
/ mDSCHSliceNum
;
1525 yAlign
= mDSCYSliceSize
;
1526 hAlign
= mDSCYSliceSize
;
1528 xAlign
= WINUPDATE_X_ALIGNMENT
;
1529 wAlign
= WINUPDATE_W_ALIGNMENT
;
1534 for (size_t i
= 0; i
< contents
->numHwLayers
; i
++) {
1535 if (contents
->hwLayers
[i
].compositionType
== HWC_FRAMEBUFFER
)
1538 if (!mFbNeeded
&& contents
->hwLayers
[i
].compositionType
== HWC_FRAMEBUFFER_TARGET
)
1540 int32_t windowIndex
= mLayerInfos
[i
]->mWindowIndex
;
1541 if ((windowIndex
< 0) || (windowIndex
> MAX_DECON_WIN
))
1542 return -eWindowUpdateInvalidConfig
;
1544 if (config
[windowIndex
].state
!= config
[windowIndex
].DECON_WIN_STATE_DISABLED
) {
1547 if (winConfigChanged(&config
[windowIndex
], &this->mLastConfigData
.config
[windowIndex
])) {
1550 currentRect
.left
= config
[windowIndex
].dst
.x
;
1551 currentRect
.right
= config
[windowIndex
].dst
.x
+ config
[windowIndex
].dst
.w
;
1552 currentRect
.top
= config
[windowIndex
].dst
.y
;
1553 currentRect
.bottom
= config
[windowIndex
].dst
.y
+ config
[windowIndex
].dst
.h
;
1555 if (hwcHasApiVersion((hwc_composer_device_1_t
*)mHwc
, HWC_DEVICE_API_VERSION_1_5
))
1557 private_handle_t
*handle
= NULL
;
1558 hwc_rect damageRect
= {0, 0, 0, 0};
1559 hwc_layer_1_t
&layer
= contents
->hwLayers
[i
];
1561 handle
= private_handle_t::dynamicCast(layer
.handle
);
1562 unsigned int damageRegionMod
= getLayerRegion(layer
, damageRect
, eDamageRegion
);
1564 if (damageRegionMod
== eDamageRegionSkip
)
1567 if (handle
&& !isScaled(layer
) && !isRotated(layer
) && (damageRegionMod
== eDamageRegionPartial
)) {
1568 DISPLAY_LOGD(eDebugWindowUpdate
, "[WIN_UPDATE][surfaceDamage] layer w(%4d) h(%4d), dirty (%4d, %4d) - (%4d, %4d)",
1569 handle
->width
, handle
->height
, damageRect
.left
, damageRect
.top
, damageRect
.right
, damageRect
.bottom
);
1571 currentRect
.left
= config
[windowIndex
].dst
.x
- (int32_t)layer
.sourceCropf
.left
+ damageRect
.left
;
1572 currentRect
.right
= config
[windowIndex
].dst
.x
- (int32_t)layer
.sourceCropf
.left
+ damageRect
.right
;
1573 currentRect
.top
= config
[windowIndex
].dst
.y
- (int32_t)layer
.sourceCropf
.top
+ damageRect
.top
;
1574 currentRect
.bottom
= config
[windowIndex
].dst
.y
- (int32_t)layer
.sourceCropf
.top
+ damageRect
.bottom
;
1575 adjustRect(currentRect
, mXres
, mYres
);
1580 if ((currentRect
.left
> currentRect
.right
) || (currentRect
.top
> currentRect
.bottom
)) {
1581 DISPLAY_LOGD(eDebugWindowUpdate
, "[WIN_UPDATE] window(%d) layer(%d) invalid region (%4d, %4d) - (%4d, %4d)",
1582 i
, layerIdx
, currentRect
.left
, currentRect
.top
, currentRect
.right
, currentRect
.bottom
);
1583 return -eWindowUpdateInvalidRegion
;
1585 DISPLAY_LOGD(eDebugWindowUpdate
, "[WIN_UPDATE] Updated Window(%d) Layer(%d) (%4d, %4d) - (%4d, %4d)",
1586 windowIndex
, i
, currentRect
.left
, currentRect
.top
, currentRect
.right
, currentRect
.bottom
);
1587 updateRect
= expand(updateRect
, currentRect
);
1591 if (updatedWinCnt
== 0)
1592 return -eWindowUpdateNotUpdated
;
1594 /* Alignment check */
1595 for (size_t i
= 0; i
< contents
->numHwLayers
; i
++) {
1596 if (contents
->hwLayers
[i
].compositionType
== HWC_FRAMEBUFFER
)
1599 if (!mFbNeeded
&& contents
->hwLayers
[i
].compositionType
== HWC_FRAMEBUFFER_TARGET
)
1602 int32_t windowIndex
= mLayerInfos
[i
]->mWindowIndex
;
1603 currentRect
.left
= config
[windowIndex
].dst
.x
;
1604 currentRect
.right
= config
[windowIndex
].dst
.x
+ config
[windowIndex
].dst
.w
;
1605 currentRect
.top
= config
[windowIndex
].dst
.y
;
1606 currentRect
.bottom
= config
[windowIndex
].dst
.y
+ config
[windowIndex
].dst
.h
;
1608 if ((config
[windowIndex
].state
!= config
[windowIndex
].DECON_WIN_STATE_DISABLED
) &&
1609 intersect(currentRect
, updateRect
)) {
1610 private_handle_t
*handle
= NULL
;
1611 hwc_layer_1_t
&layer
= contents
->hwLayers
[i
];
1613 handle
= private_handle_t::dynamicCast(layer
.handle
);
1615 return -eWindowUpdateInvalidConfig
;
1617 int originalFormat
= handle
->format
;
1618 int originalTransform
= layer
.transform
;
1619 if (mLayerInfos
[i
]->mInternalMPP
!= NULL
) {
1620 /* VPP scaling case */
1621 if ((config
[windowIndex
].src
.w
!= config
[windowIndex
].dst
.w
) ||
1622 (config
[windowIndex
].src
.h
!= config
[windowIndex
].dst
.h
))
1623 return -eWindowUpdateUnsupportedUseCase
;
1625 handle
->format
= S3CFormatToHalFormat(config
[windowIndex
].format
);
1626 if (handle
->format
>= 0) {
1627 /* rotation was handled by externalMPP */
1628 if (mLayerInfos
[i
]->mExternalMPP
!= NULL
)
1629 layer
.transform
= 0;
1630 xAlign
= getLCM(xAlign
, mLayerInfos
[i
]->mInternalMPP
->getSrcXOffsetAlign(layer
));
1631 yAlign
= getLCM(yAlign
, mLayerInfos
[i
]->mInternalMPP
->getSrcYOffsetAlign(layer
));
1632 wAlign
= getLCM(wAlign
, mLayerInfos
[i
]->mInternalMPP
->getCropWidthAlign(layer
));
1633 hAlign
= getLCM(hAlign
, mLayerInfos
[i
]->mInternalMPP
->getCropHeightAlign(layer
));
1635 handle
->format
= originalFormat
;
1636 layer
.transform
= originalTransform
;
1637 return -eWindowUpdateInvalidConfig
;
1640 handle
->format
= originalFormat
;
1641 layer
.transform
= originalTransform
;
1645 updateRect
.left
= ALIGN_DOWN(updateRect
.left
, xAlign
);
1646 updateRect
.top
= ALIGN_DOWN(updateRect
.top
, yAlign
);
1648 if (HEIGHT(updateRect
) < WINUPDATE_MIN_HEIGHT
) {
1649 if (updateRect
.top
+ WINUPDATE_MIN_HEIGHT
<= mYres
)
1650 updateRect
.bottom
= updateRect
.top
+ WINUPDATE_MIN_HEIGHT
;
1652 updateRect
.top
= updateRect
.bottom
- WINUPDATE_MIN_HEIGHT
;
1655 if ((100 * (WIDTH(updateRect
) * HEIGHT(updateRect
)) / (this->mXres
* this->mYres
)) > WINUPDATE_THRESHOLD
)
1656 return -eWindowUpdateOverThreshold
;
1658 alignAdjustment
= getLCM(alignAdjustment
, xAlign
);
1659 alignAdjustment
= getLCM(alignAdjustment
, wAlign
);
1662 burstLengthCheckDone
= true;
1663 updateRect
.left
= ALIGN_DOWN(updateRect
.left
, xAlign
);
1664 if ((WIDTH(updateRect
) % wAlign
) != 0)
1665 updateRect
.right
= updateRect
.left
+ ALIGN_DOWN(WIDTH(updateRect
), wAlign
) + wAlign
;
1666 updateRect
.top
= ALIGN_DOWN(updateRect
.top
, yAlign
);
1667 if ((HEIGHT(updateRect
) % hAlign
) != 0)
1668 updateRect
.bottom
= updateRect
.top
+ ALIGN_DOWN(HEIGHT(updateRect
), hAlign
) + hAlign
;
1670 for (size_t i
= 0; i
< contents
->numHwLayers
; i
++) {
1671 if (contents
->hwLayers
[i
].compositionType
== HWC_FRAMEBUFFER
)
1673 if (!mFbNeeded
&& contents
->hwLayers
[i
].compositionType
== HWC_FRAMEBUFFER_TARGET
)
1675 int32_t windowIndex
= mLayerInfos
[i
]->mWindowIndex
;
1676 if (config
[windowIndex
].state
!= config
[windowIndex
].DECON_WIN_STATE_DISABLED
) {
1677 enum decon_pixel_format fmt
= config
[windowIndex
].format
;
1678 if (fmt
== DECON_PIXEL_FORMAT_RGBA_5551
|| fmt
== DECON_PIXEL_FORMAT_RGB_565
)
1680 else if (fmt
== DECON_PIXEL_FORMAT_NV12
|| fmt
== DECON_PIXEL_FORMAT_NV21
||
1681 fmt
== DECON_PIXEL_FORMAT_NV12M
|| fmt
== DECON_PIXEL_FORMAT_NV21M
)
1686 currentRect
.left
= config
[windowIndex
].dst
.x
;
1687 currentRect
.right
= config
[windowIndex
].dst
.x
+ config
[windowIndex
].dst
.w
;
1688 currentRect
.top
= config
[windowIndex
].dst
.y
;
1689 currentRect
.bottom
= config
[windowIndex
].dst
.y
+ config
[windowIndex
].dst
.h
;
1691 intersectionWidth
= WIDTH(intersection(currentRect
, updateRect
));
1693 DISPLAY_LOGD(eDebugWindowUpdate
, "[WIN_UPDATE] win[%d] left(%d) right(%d) intersection(%d)", windowIndex
, currentRect
.left
, currentRect
.right
, intersectionWidth
);
1695 if (intersectionWidth
!= 0 && (size_t)((intersectionWidth
* bitsPerPixel
) / 8) < BURSTLEN_BYTES
) {
1696 #ifdef USE_DRM_BURST_LEN
1697 if (mHasDrmSurface
) {
1698 if ((size_t)((intersectionWidth
* bitsPerPixel
) / 8) < DRM_BURSTLEN_BYTES
) {
1699 DISPLAY_LOGD(eDebugWindowUpdate
, "[WIN_UPDATE] win[%d] insufficient burst length (%d)*(%d) < %d", windowIndex
, intersectionWidth
, bitsPerPixel
, BURSTLEN_BYTES
);
1700 burstLengthCheckDone
= false;
1706 DISPLAY_LOGD(eDebugWindowUpdate
, "[WIN_UPDATE] win[%d] insufficient burst length (%d)*(%d) < %d", windowIndex
, intersectionWidth
, bitsPerPixel
, BURSTLEN_BYTES
);
1707 burstLengthCheckDone
= false;
1709 #ifdef USE_DRM_BURST_LEN
1716 if (burstLengthCheckDone
)
1718 DISPLAY_LOGD(eDebugWindowUpdate
, "[WIN_UPDATE] Adjusting update width. current left(%d) right(%d)", updateRect
.left
, updateRect
.right
);
1719 if (updateRect
.left
>= alignAdjustment
) {
1720 updateRect
.left
-= alignAdjustment
;
1721 } else if (updateRect
.right
+ alignAdjustment
<= this->mXres
) {
1722 updateRect
.right
+= alignAdjustment
;
1724 DISPLAY_LOGD(eDebugWindowUpdate
, "[WIN_UPDATE] Error during update width adjustment");
1725 return -eWindowUpdateAdjustmentFail
;
1729 config
[winUpdateInfoIdx
].state
= config
[winUpdateInfoIdx
].DECON_WIN_STATE_UPDATE
;
1730 config
[winUpdateInfoIdx
].dst
.x
= ALIGN_DOWN(updateRect
.left
, xAlign
);
1731 if ((WIDTH(updateRect
) % wAlign
) != 0)
1732 updateRect
.right
= updateRect
.left
+ ALIGN_DOWN(WIDTH(updateRect
), wAlign
) + wAlign
;
1733 config
[winUpdateInfoIdx
].dst
.w
= WIDTH(updateRect
);
1735 config
[winUpdateInfoIdx
].dst
.y
= ALIGN_DOWN(updateRect
.top
, yAlign
);
1736 if ((HEIGHT(updateRect
) % hAlign
) != 0)
1737 updateRect
.bottom
= updateRect
.top
+ ALIGN_DOWN(HEIGHT(updateRect
), hAlign
) + hAlign
;
1738 config
[winUpdateInfoIdx
].dst
.h
= HEIGHT(updateRect
);
1741 for (size_t i
= 0; i
< contents
->numHwLayers
; i
++) {
1742 if (contents
->hwLayers
[i
].compositionType
== HWC_FRAMEBUFFER
)
1745 if (!mFbNeeded
&& contents
->hwLayers
[i
].compositionType
== HWC_FRAMEBUFFER_TARGET
)
1748 int32_t windowIndex
= mLayerInfos
[i
]->mWindowIndex
;
1749 currentRect
.left
= config
[windowIndex
].dst
.x
;
1750 currentRect
.right
= config
[windowIndex
].dst
.x
+ config
[windowIndex
].dst
.w
;
1751 currentRect
.top
= config
[windowIndex
].dst
.y
;
1752 currentRect
.bottom
= config
[windowIndex
].dst
.y
+ config
[windowIndex
].dst
.h
;
1754 if ((config
[windowIndex
].state
!= config
[windowIndex
].DECON_WIN_STATE_DISABLED
) &&
1755 intersect(currentRect
, updateRect
)) {
1756 private_handle_t
*handle
= NULL
;
1757 hwc_rect intersect_rect
= intersection(currentRect
, updateRect
);
1758 hwc_layer_1_t
&layer
= contents
->hwLayers
[i
];
1760 handle
= private_handle_t::dynamicCast(layer
.handle
);
1762 return -eWindowUpdateInvalidConfig
;
1764 int originalFormat
= handle
->format
;
1765 int originalTransform
= layer
.transform
;
1766 if (mLayerInfos
[i
]->mInternalMPP
!= NULL
) {
1767 handle
->format
= S3CFormatToHalFormat(config
[windowIndex
].format
);
1768 /* rotation was handled by externalMPP */
1769 if (mLayerInfos
[i
]->mExternalMPP
!= NULL
)
1770 layer
.transform
= 0;
1771 if (((mLayerInfos
[i
]->mInternalMPP
->getSrcXOffsetAlign(layer
) % intersect_rect
.left
) != 0) ||
1772 ((mLayerInfos
[i
]->mInternalMPP
->getSrcYOffsetAlign(layer
) % intersect_rect
.top
) != 0) ||
1773 ((mLayerInfos
[i
]->mInternalMPP
->getCropWidthAlign(layer
) % WIDTH(intersect_rect
)) != 0) ||
1774 ((mLayerInfos
[i
]->mInternalMPP
->getCropHeightAlign(layer
) % HEIGHT(intersect_rect
)) != 0)) {
1775 handle
->format
= originalFormat
;
1776 layer
.transform
= originalTransform
;
1777 config
[winUpdateInfoIdx
].state
= config
[winUpdateInfoIdx
].DECON_WIN_STATE_DISABLED
;
1778 return -eWindowUpdateAdjustmentFail
;
1781 handle
->format
= originalFormat
;
1782 layer
.transform
= originalTransform
;
1786 DISPLAY_LOGD(eDebugWindowUpdate
, "[WIN_UPDATE] UpdateRegion cfg (%4d, %4d) w(%4d) h(%4d) updatedWindowCnt(%d)",
1787 config
[winUpdateInfoIdx
].dst
.x
, config
[winUpdateInfoIdx
].dst
.y
, config
[winUpdateInfoIdx
].dst
.w
, config
[winUpdateInfoIdx
].dst
.h
, updatedWinCnt
);
1789 /* Disable block mode if window update region is not full screen */
1790 if ((config
[winUpdateInfoIdx
].dst
.x
!= 0) || (config
[winUpdateInfoIdx
].dst
.y
!= 0) ||
1791 (config
[winUpdateInfoIdx
].dst
.w
!= (uint32_t)mXres
) || (config
[winUpdateInfoIdx
].dst
.h
!= (uint32_t)mXres
)) {
1792 for (size_t i
= 0; i
< NUM_HW_WINDOWS
; i
++) {
1793 memset(&config
[i
].transparent_area
, 0, sizeof(config
[i
].transparent_area
));
1794 #ifdef HWC_SET_OPAQUE
1795 memset(&config
[i
].covered_opaque_area
, 0, sizeof(config
[i
].covered_opaque_area
));
1803 void ExynosDisplay::getLayerRegion(hwc_layer_1_t
&layer
, decon_win_rect
&rect_area
, uint32_t regionType
)
1805 hwc_rect_t
const *hwcRects
= NULL
;
1806 unsigned int numRects
= 0;
1807 switch (regionType
) {
1809 case eTransparentRegion
:
1810 hwcRects
= layer
.transparentRegion
.rects
;
1811 numRects
= layer
.transparentRegion
.numRects
;
1813 case eCoveredOpaqueRegion
:
1814 hwcRects
= layer
.coveredOpaqueRegion
.rects
;
1815 numRects
= layer
.coveredOpaqueRegion
.numRects
;
1819 ALOGE("%s:: Invalid regionType (%d)", __func__
, regionType
);
1823 rect_area
.x
= rect_area
.y
= rect_area
.w
= rect_area
.h
= 0;
1824 if (hwcRects
!= NULL
) {
1825 for (size_t j
= 0; j
< numRects
; j
++) {
1827 rect
.left
= hwcRects
[j
].left
;
1828 rect
.top
= hwcRects
[j
].top
;
1829 rect
.right
= hwcRects
[j
].right
;
1830 rect
.bottom
= hwcRects
[j
].bottom
;
1831 adjustRect(rect
, mXres
, mYres
);
1832 /* Find the largest rect */
1833 if ((rect_area
.w
* rect_area
.h
) <
1834 (uint32_t)(WIDTH(rect
) * HEIGHT(rect
))) {
1835 rect_area
.x
= rect
.left
;
1836 rect_area
.y
= rect
.top
;
1837 rect_area
.w
= WIDTH(rect
);
1838 rect_area
.h
= HEIGHT(rect
);
1844 unsigned int ExynosDisplay::getLayerRegion(hwc_layer_1_t
&layer
, hwc_rect
&rect_area
, uint32_t regionType
) {
1845 hwc_rect_t
const *hwcRects
= NULL
;
1846 unsigned int numRects
= 0;
1848 switch (regionType
) {
1850 hwcRects
= layer
.surfaceDamage
.rects
;
1851 numRects
= layer
.surfaceDamage
.numRects
;
1854 ALOGE("%s:: Invalid regionType (%d)", __func__
, regionType
);
1855 return eDamageRegionError
;
1858 if ((numRects
== 0) || (hwcRects
== NULL
))
1859 return eDamageRegionFull
;
1861 if ((numRects
== 1) && (hwcRects
[0].left
== 0) && (hwcRects
[0].top
== 0) &&
1862 (hwcRects
[0].right
== 0) && (hwcRects
[0].bottom
== 0))
1863 return eDamageRegionSkip
;
1865 rect_area
.left
= INT_MAX
;
1866 rect_area
.top
= INT_MAX
;
1867 rect_area
.right
= rect_area
.bottom
= 0;
1868 if (hwcRects
!= NULL
) {
1869 for (size_t j
= 0; j
< numRects
; j
++) {
1871 rect
.left
= hwcRects
[j
].left
;
1872 rect
.top
= hwcRects
[j
].top
;
1873 rect
.right
= hwcRects
[j
].right
;
1874 rect
.bottom
= hwcRects
[j
].bottom
;
1875 adjustRect(rect
, INT_MAX
, INT_MAX
);
1876 /* Get sums of rects */
1877 rect_area
= expand(rect_area
, rect
);
1881 return eDamageRegionPartial
;
1884 bool ExynosDisplay::getPreviousDRMDMA(int *dma
)
1888 for (size_t i
= 0; i
< NUM_HW_WINDOWS
; i
++) {
1889 if (mLastConfigData
.config
[i
].protection
== 1) {
1890 *dma
= (int)mLastConfigData
.config
[i
].idma_type
;
1897 int ExynosDisplay::winconfigIoctl(decon_win_config_data
*win_data
)
1900 return ioctl(this->mDisplayFd
, S3CFB_WIN_CONFIG
, win_data
);
1903 int ExynosDisplay::postFrame(hwc_display_contents_1_t
* contents
)
1907 if (mWinData
== NULL
) {
1908 DISPLAY_LOGE("mWinData is not valid");
1911 struct decon_win_config
*config
= mWinData
->config
;
1913 int tot_ovly_wins
= 0;
1914 uint32_t rectCount
= 0;
1917 memset(mLastHandles
, 0, sizeof(mLastHandles
));
1918 memset(mLastMPPMap
, 0, sizeof(mLastMPPMap
));
1919 memset(config
, 0, sizeof(mWinData
->config
));
1921 for (size_t i
= 0; i
< NUM_HW_WINDOWS
; i
++) {
1922 config
[i
].fence_fd
= -1;
1923 mLastMPPMap
[i
].internal_mpp
.type
= -1;
1924 mLastMPPMap
[i
].external_mpp
.type
= -1;
1926 for (size_t i
= 0; i
< contents
->numHwLayers
; i
++) {
1927 hwc_layer_1_t
&layer
= contents
->hwLayers
[i
];
1929 private_handle_t
*handle
= private_handle_t::dynamicCast(layer
.handle
);
1930 if (handle
->format
== HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_PRIV
1931 && rectCount
< mBackUpFrect
.size())
1932 layer
.sourceCropf
= mBackUpFrect
[rectCount
++];
1936 for (size_t i
= 0; i
< contents
->numHwLayers
; i
++) {
1937 hwc_layer_1_t
&layer
= contents
->hwLayers
[i
];
1938 int32_t window_index
= mLayerInfos
[i
]->mWindowIndex
;
1939 private_handle_t
*handle
= NULL
;
1941 handle
= private_handle_t::dynamicCast(layer
.handle
);
1943 if ((layer
.flags
& HWC_SKIP_RENDERING
) ||
1944 ((layer
.compositionType
== HWC_OVERLAY
) &&
1945 ((window_index
< 0) || (window_index
>= NUM_HW_WINDOWS
)))) {
1946 if (layer
.acquireFenceFd
>= 0)
1947 close(layer
.acquireFenceFd
);
1948 layer
.acquireFenceFd
= -1;
1949 layer
.releaseFenceFd
= -1;
1951 if ((window_index
< 0) || (window_index
>= NUM_HW_WINDOWS
)) {
1952 android::String8 result
;
1953 DISPLAY_LOGE("window of layer %d was not assigned (window_index: %d)", i
, window_index
);
1954 dumpContents(result
, contents
);
1955 ALOGE(result
.string());
1957 dumpLayerInfo(result
);
1958 ALOGE(result
.string());
1963 if ((mVirtualOverlayFlag
== true) && (layer
.compositionType
== HWC_OVERLAY
) &&
1964 handle
&& (getDrmMode(handle
->flags
) == NO_DRM
) &&
1965 (mFirstFb
<= i
) && (i
<= mLastFb
))
1968 if (((layer
.compositionType
== HWC_OVERLAY
) ||
1969 (mFbNeeded
== true && layer
.compositionType
== HWC_FRAMEBUFFER_TARGET
))) {
1970 mLastHandles
[window_index
] = layer
.handle
;
1972 if (handle
&& (getDrmMode(handle
->flags
) == SECURE_DRM
))
1973 config
[window_index
].protection
= 1;
1975 config
[window_index
].protection
= 0;
1977 if (mLayerInfos
[i
]->mInternalMPP
!= NULL
) {
1978 mLastMPPMap
[window_index
].internal_mpp
.type
= mLayerInfos
[i
]->mInternalMPP
->mType
;
1979 mLastMPPMap
[window_index
].internal_mpp
.index
= mLayerInfos
[i
]->mInternalMPP
->mIndex
;
1981 if (mLayerInfos
[i
]->mExternalMPP
!= NULL
) {
1982 mLastMPPMap
[window_index
].external_mpp
.type
= mLayerInfos
[i
]->mExternalMPP
->mType
;
1983 mLastMPPMap
[window_index
].external_mpp
.index
= mLayerInfos
[i
]->mExternalMPP
->mIndex
;
1984 if (postMPPM2M(layer
, config
, window_index
, i
) < 0)
1987 configureOverlay(&layer
, i
, config
[window_index
]);
1990 if (window_index
== 0 && config
[window_index
].blending
!= DECON_BLENDING_NONE
) {
1991 DISPLAY_LOGD(eDebugWinConfig
, "blending not supported on window 0; forcing BLENDING_NONE");
1992 config
[window_index
].blending
= DECON_BLENDING_NONE
;
1994 if ((window_index
< DECON_WIN_UPDATE_IDX
) &&
1995 (config
[window_index
].state
!= config
[window_index
].DECON_WIN_STATE_DISABLED
) &&
1996 (config
[window_index
].src
.w
== 0 || config
[window_index
].src
.h
== 0 ||
1997 config
[window_index
].dst
.w
== 0 || config
[window_index
].dst
.h
== 0)) {
1998 config
[window_index
].state
= config
[window_index
].DECON_WIN_STATE_DISABLED
;
2002 if (this->mVirtualOverlayFlag
) {
2003 handleStaticLayers(contents
, *mWinData
, tot_ovly_wins
);
2006 if ((ret
= handleWindowUpdate(contents
, config
)) < 0)
2007 DISPLAY_LOGD(eDebugWindowUpdate
, "[WIN_UPDATE] UpdateRegion is FullScreen, ret(%d)", ret
);
2009 #if defined(USES_DUAL_DISPLAY)
2010 if (mType
== EXYNOS_PRIMARY_DISPLAY
) {
2011 int8_t indexLastConfig
= 0;
2012 for (size_t i
= 0; i
< NUM_HW_WINDOWS
; i
++) {
2013 if (config
[i
].state
== config
[i
].DECON_WIN_STATE_DISABLED
) {
2014 indexLastConfig
= i
;
2018 if (mHwc
->secondaryDisplay
->mEnabled
) {
2019 for (size_t i
= 0; i
< NUM_HW_WINDOWS
; i
++) {
2020 struct decon_win_config
&secondary_config
= mHwc
->secondaryDisplay
->mLastConfigData
.config
[i
];
2022 if (indexLastConfig
== NUM_HW_WINDOWS
) {
2023 DISPLAY_LOGE("primaryDisplay last config index is not valid(primaryLastIndex: %d)",
2027 if (i
== (NUM_HW_WINDOWS
- 1))
2030 index
= indexLastConfig
+ i
;
2031 DISPLAY_LOGD(eDebugWinConfig
, "secondary_config window %u configuration:", i
);
2032 dumpConfig(secondary_config
);
2033 if (secondary_config
.state
!= secondary_config
.DECON_WIN_STATE_DISABLED
) {
2034 if (index
>= NUM_HW_WINDOWS
) {
2035 DISPLAY_LOGE("secondaryDisplay config index is not valid(primaryLastIndex: %d, index:%d",
2036 indexLastConfig
, index
);
2038 memcpy(&config
[index
],&secondary_config
, sizeof(struct decon_win_config
));
2039 mLastHandles
[index
] = mHwc
->secondaryDisplay
->mLastHandles
[i
];
2046 if (mType
!= EXYNOS_SECONDARY_DISPLAY
)
2049 for (size_t i
= 0; i
<= NUM_HW_WINDOWS
; i
++) {
2050 DISPLAY_LOGD(eDebugWinConfig
, "window %u configuration:", i
);
2051 dumpConfig(config
[i
]);
2054 if (checkConfigValidation(config
) < 0) {
2055 android::String8 result
;
2056 DISPLAY_LOGE("WIN_CONFIG is not valid");
2057 for (size_t i
= 0; i
<= MAX_DECON_WIN
; i
++) {
2058 result
.appendFormat("window %zu configuration:\n", i
);
2059 dumpConfig(config
[i
], result
);
2061 ALOGE(result
.string());
2063 dumpContents(result
, contents
);
2064 ALOGE(result
.string());
2066 dumpLayerInfo(result
);
2067 ALOGE(result
.string());
2070 if (checkConfigChanged(*mWinData
, mLastConfigData
) == false) {
2073 ret
= winconfigIoctl(mWinData
);
2075 DISPLAY_LOGE("ioctl S3CFB_WIN_CONFIG failed: %s", strerror(errno
));
2077 ret
= mWinData
->fence
;
2078 memcpy(&(this->mLastConfigData
), mWinData
, sizeof(*mWinData
));
2083 * Acquire fence of all of OVERLAY layers(including layers for secondary LCD)
2084 * should be closed even if WIN_CONFIG is skipped
2086 for (size_t i
= 0; i
< NUM_HW_WINDOWS
; i
++) {
2087 if (config
[i
].fence_fd
!= -1)
2088 close(config
[i
].fence_fd
);
2090 #if defined(USES_DUAL_DISPLAY)
2092 memcpy(&(this->mLastConfigData
), mWinData
, sizeof(*mWinData
));
2095 if (contents
->numHwLayers
== 1) {
2096 hwc_layer_1_t
&layer
= contents
->hwLayers
[0];
2097 if (layer
.acquireFenceFd
>= 0)
2098 close(layer
.acquireFenceFd
);
2099 layer
.acquireFenceFd
= -1;
2100 layer
.releaseFenceFd
= -1;
2103 for (size_t i
= 0; i
< contents
->numHwLayers
; i
++) {
2104 hwc_layer_1_t
&layer
= contents
->hwLayers
[i
];
2106 private_handle_t
*handle
= private_handle_t::dynamicCast(layer
.handle
);
2107 if (handle
->format
== HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_PRIV
2108 && rectCount
< mOriginFrect
.size())
2109 layer
.sourceCropf
= mOriginFrect
[rectCount
++];
2112 mOriginFrect
.clear();
2113 mBackUpFrect
.clear();
2115 if (!this->mVirtualOverlayFlag
&& (ret
>= 0))
2116 this->mLastFbWindow
= mFbWindow
;
2121 void ExynosDisplay::skipStaticLayers(hwc_display_contents_1_t
* contents
)
2123 mVirtualOverlayFlag
= 0;
2125 int fbIndex
= contents
->numHwLayers
- 1;
2127 if (!mHwc
->hwc_ctrl
.skip_static_layer_mode
)
2130 if (mBypassSkipStaticLayer
)
2133 if (contents
->flags
& HWC_GEOMETRY_CHANGED
) {
2134 mSkipStaticInitFlag
= false;
2138 if (!mFbNeeded
|| ((mLastFb
- mFirstFb
+ 1) > NUM_VIRT_OVER
)) {
2139 mSkipStaticInitFlag
= false;
2143 if (mSkipStaticInitFlag
) {
2144 if (mNumStaticLayers
!= (mLastFb
- mFirstFb
+ 1)) {
2145 mSkipStaticInitFlag
= false;
2149 for (size_t i
= mFirstFb
; i
<= mLastFb
; i
++) {
2150 hwc_layer_1_t
&layer
= contents
->hwLayers
[i
];
2151 if (!layer
.handle
|| (layer
.flags
& HWC_SKIP_LAYER
) || (mLastLayerHandles
[i
- mFirstFb
] != layer
.handle
)) {
2152 mSkipStaticInitFlag
= false;
2157 if ((mLastFbWindow
>= NUM_HW_WINDOWS
) || (fbIndex
< 0)) {
2158 mSkipStaticInitFlag
= false;
2159 DISPLAY_LOGE("skipStaticLayers:: invalid mLastFbWindow(%d), fbIndex(%d)", mLastFbWindow
, fbIndex
);
2162 /* DMA mapping is changed */
2163 if (mLastConfigData
.config
[mLastFbWindow
].idma_type
!= mLayerInfos
[fbIndex
]->mDmaType
) {
2164 mSkipStaticInitFlag
= false;
2168 mVirtualOverlayFlag
= 1;
2169 for (size_t i
= 0; i
< contents
->numHwLayers
-1; i
++) {
2170 hwc_layer_1_t
&layer
= contents
->hwLayers
[i
];
2171 if (layer
.compositionType
== HWC_FRAMEBUFFER
) {
2172 layer
.compositionType
= HWC_OVERLAY
;
2173 mLayerInfos
[i
]->compositionType
= layer
.compositionType
;
2174 mLayerInfos
[i
]->mCheckOverlayFlag
|= eSkipStaticLayer
;
2177 mLastFbWindow
= mFbWindow
;
2181 mSkipStaticInitFlag
= true;
2182 for (size_t i
= 0; i
< NUM_VIRT_OVER
; i
++)
2183 mLastLayerHandles
[i
] = 0;
2185 for (size_t i
= mFirstFb
; i
<= mLastFb
; i
++) {
2186 hwc_layer_1_t
&layer
= contents
->hwLayers
[i
];
2187 mLastLayerHandles
[i
- mFirstFb
] = layer
.handle
;
2189 mNumStaticLayers
= (mLastFb
- mFirstFb
+ 1);
2194 void ExynosDisplay::dumpMPPs(android::String8
& result
)
2196 result
.appendFormat("displayType(%d)\n", mType
);
2197 result
.appendFormat("Internal MPPs number: %zu\n", mInternalMPPs
.size());
2199 " mType | mIndex | mState \n"
2200 "-------+--------+-----------\n");
2201 // 5____ | 6_____ | 9________ \n
2203 for (size_t i
= 0; i
< mInternalMPPs
.size(); i
++) {
2204 ExynosMPPModule
* internalMPP
= mInternalMPPs
[i
];
2205 result
.appendFormat(" %5d | %6d | %9d \n",
2206 internalMPP
->mType
, internalMPP
->mIndex
, internalMPP
->mState
);
2209 result
.append("\n");
2210 result
.appendFormat("External MPPs number: %zu\n", mExternalMPPs
.size());
2212 " mType | mIndex | mState \n"
2213 "-------+--------+-----------\n");
2214 // 5____ | 6_____ | 9________ \n
2216 for (size_t i
= 0; i
< mExternalMPPs
.size(); i
++) {
2217 ExynosMPPModule
* internalMPP
= mExternalMPPs
[i
];
2218 result
.appendFormat(" %5d | %6d | %9d \n",
2219 internalMPP
->mType
, internalMPP
->mIndex
, internalMPP
->mState
);
2223 void ExynosDisplay::preAssignFbTarget(hwc_display_contents_1_t
*contents
, bool assign
)
2225 ExynosMPPModule
* supportedInternalMPP
= NULL
;
2226 ExynosMPPModule
* supportedExternalMPP
= NULL
;
2228 int fbIndex
= contents
->numHwLayers
- 1;
2229 hwc_layer_1_t
&layer
= contents
->hwLayers
[fbIndex
];
2230 mFbPreAssigned
= false;
2235 if (layer
.compositionType
!= HWC_FRAMEBUFFER_TARGET
) {
2236 ALOGE("preAssignFbTarget: FRAMEBUFFER_TARGET is not set properly");
2240 bool ret
= isOverlaySupported(layer
, fbIndex
, true, &supportedInternalMPP
, &supportedExternalMPP
);
2241 if (ret
&& (supportedInternalMPP
!= NULL
) && (supportedExternalMPP
== NULL
)) {
2242 DISPLAY_LOGD(eDebugResourceAssigning
, "Preassigning FramebufferTarget with internalMPP(%d, %d)", supportedInternalMPP
->mType
, supportedInternalMPP
->mIndex
);
2243 supportedInternalMPP
->mState
= MPP_STATE_ASSIGNED
;
2244 mLayerInfos
[fbIndex
]->mInternalMPP
= supportedInternalMPP
;
2245 mLayerInfos
[fbIndex
]->mDmaType
= getDeconDMAType(mLayerInfos
[fbIndex
]->mInternalMPP
);
2246 for (size_t i
= 0; i
< mInternalMPPs
.size(); i
++) {
2247 if ((ExynosMPPModule
*)mInternalMPPs
[i
] == supportedInternalMPP
) {
2248 mInternalMPPs
.removeItemsAt(i
);
2251 mFbPreAssigned
= true;
2253 ALOGE("preAssignFbTarget: preassigning FB failed");
2258 void ExynosDisplay::determineYuvOverlay(hwc_display_contents_1_t
*contents
)
2261 bool useVPPOverlayFlag
= false, hasDrmLayer
= mHasDrmSurface
;
2262 uint32_t rectCount
= 0;
2263 int drmLayerIndex
= mForceOverlayLayerIndex
;
2265 mForceOverlayLayerIndex
= -1;
2266 mHasDrmSurface
= false;
2268 for (size_t j
= 0; j
< contents
->numHwLayers
; j
++) {
2269 i
= hasDrmLayer
? ((j
+ drmLayerIndex
) % contents
->numHwLayers
) : j
;
2271 ExynosMPPModule
* supportedInternalMPP
= NULL
;
2272 ExynosMPPModule
* supportedExternalMPP
= NULL
;
2273 hwc_layer_1_t
&layer
= contents
->hwLayers
[i
];
2274 useVPPOverlayFlag
= false;
2277 private_handle_t
*handle
= private_handle_t::dynamicCast(layer
.handle
);
2279 if (getDrmMode(handle
->flags
) != NO_DRM
) {
2280 useVPPOverlayFlag
= true;
2281 if (mHwc
->hdmi_hpd
&& (!mHwc
->video_playback_status
)) {
2282 layer
.flags
|= HWC_SKIP_RENDERING
;
2285 layer
.flags
&= ~HWC_SKIP_RENDERING
;
2288 /* check yuv surface */
2289 if (!isFormatRgb(handle
->format
)) {
2290 if (mForceFb
&& (getDrmMode(handle
->flags
) == NO_DRM
)) {
2291 layer
.compositionType
= HWC_FRAMEBUFFER
;
2292 mLayerInfos
[i
]->compositionType
= layer
.compositionType
;
2293 mLayerInfos
[i
]->mCheckOverlayFlag
|= eForceFbEnabled
;
2296 /* HACK: force integer source crop */
2297 layer
.sourceCropf
.top
= (int)layer
.sourceCropf
.top
;
2298 layer
.sourceCropf
.left
= (int)layer
.sourceCropf
.left
;
2299 layer
.sourceCropf
.bottom
= (int)(layer
.sourceCropf
.bottom
+ 0.9);
2300 layer
.sourceCropf
.right
= (int)(layer
.sourceCropf
.right
+ 0.9);
2302 /* support to process interlaced color format data */
2303 if (handle
->format
== HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_PRIV
) {
2304 void *metaData
= NULL
;
2305 int interlacedType
= -1;
2306 mOriginFrect
.push(layer
.sourceCropf
);
2308 if (handle
->fd2
>= 0) {
2309 metaData
= mmap(0, 64, PROT_READ
|PROT_WRITE
, MAP_SHARED
, handle
->fd2
, 0);
2311 interlacedType
= *(int *)metaData
;
2313 interlacedType
= -1;
2316 if (interlacedType
== V4L2_FIELD_INTERLACED_BT
) {
2317 if ((int)layer
.sourceCropf
.left
< (int)(handle
->stride
)) {
2318 layer
.sourceCropf
.left
= (int)layer
.sourceCropf
.left
+ handle
->stride
;
2319 layer
.sourceCropf
.right
= (int)layer
.sourceCropf
.right
+ handle
->stride
;
2322 if (interlacedType
== V4L2_FIELD_INTERLACED_TB
|| interlacedType
== V4L2_FIELD_INTERLACED_BT
) {
2323 layer
.sourceCropf
.top
= (int)(layer
.sourceCropf
.top
)/2;
2324 layer
.sourceCropf
.bottom
= (int)(layer
.sourceCropf
.bottom
)/2;
2326 mBackUpFrect
.push(layer
.sourceCropf
);
2329 munmap(metaData
, 64);
2332 if (isOverlaySupported(contents
->hwLayers
[i
], i
, useVPPOverlayFlag
, &supportedInternalMPP
, &supportedExternalMPP
)) {
2334 if (this->mHasDrmSurface
== false) {
2336 if (supportedExternalMPP
!= NULL
)
2337 supportedExternalMPP
->mState
= MPP_STATE_ASSIGNED
;
2338 if (supportedInternalMPP
!= NULL
)
2339 supportedInternalMPP
->mState
= MPP_STATE_ASSIGNED
;
2341 mForceOverlayLayerIndex
= i
;
2342 layer
.compositionType
= HWC_OVERLAY
;
2343 mLayerInfos
[i
]->mExternalMPP
= supportedExternalMPP
;
2344 mLayerInfos
[i
]->mInternalMPP
= supportedInternalMPP
;
2345 mLayerInfos
[i
]->compositionType
= layer
.compositionType
;
2347 if ((getDrmMode(handle
->flags
) != NO_DRM
) &&
2348 isBothMPPProcessingRequired(layer
) &&
2349 (supportedInternalMPP
!= NULL
)) {
2350 layer
.displayFrame
.right
= layer
.displayFrame
.left
+
2351 ALIGN_DOWN(WIDTH(layer
.displayFrame
), supportedInternalMPP
->getCropWidthAlign(layer
));
2352 layer
.displayFrame
.bottom
= layer
.displayFrame
.top
+
2353 ALIGN_DOWN(HEIGHT(layer
.displayFrame
), supportedInternalMPP
->getCropHeightAlign(layer
));
2356 if ((getDrmMode(handle
->flags
) != NO_DRM
) &&
2357 (supportedInternalMPP
!= NULL
)) {
2358 if (WIDTH(layer
.displayFrame
) < supportedInternalMPP
->getMinWidth(layer
)) {
2359 ALOGE("determineYuvOverlay layer %d displayFrame width %d is smaller than vpp minWidth %d",
2360 i
, WIDTH(layer
.displayFrame
), supportedInternalMPP
->getMinWidth(layer
));
2361 layer
.displayFrame
.right
= layer
.displayFrame
.left
+
2362 ALIGN_DOWN(WIDTH(layer
.displayFrame
), supportedInternalMPP
->getMinWidth(layer
));
2364 if (HEIGHT(layer
.displayFrame
) < supportedInternalMPP
->getMinHeight(layer
)) {
2365 ALOGE("determineYuvOverlay layer %d displayFrame height %d is smaller than vpp minHeight %d",
2366 i
, HEIGHT(layer
.displayFrame
), supportedInternalMPP
->getMinHeight(layer
));
2367 layer
.displayFrame
.bottom
= layer
.displayFrame
.top
+
2368 ALIGN_DOWN(HEIGHT(layer
.displayFrame
), supportedInternalMPP
->getMinHeight(layer
));
2373 if (getDrmMode(handle
->flags
) != NO_DRM
) {
2374 /* This layer should be overlay but HWC can't handle it */
2375 layer
.compositionType
= HWC_OVERLAY
;
2376 mLayerInfos
[i
]->compositionType
= layer
.compositionType
;
2377 layer
.flags
|= HWC_SKIP_RENDERING
;
2382 if (getDrmMode(handle
->flags
) != NO_DRM
) {
2383 this->mHasDrmSurface
= true;
2384 mForceOverlayLayerIndex
= i
;
2388 private_handle_t
*handle
= private_handle_t::dynamicCast(layer
.handle
);
2389 if (handle
->format
== HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_PRIV
2390 && rectCount
< mOriginFrect
.size())
2391 layer
.sourceCropf
= mOriginFrect
[rectCount
++];
2396 void ExynosDisplay::determineSupportedOverlays(hwc_display_contents_1_t
*contents
)
2398 bool videoLayer
= false;
2403 uint32_t rectCount
= 0;
2405 // find unsupported overlays
2406 for (size_t i
= 0; i
< contents
->numHwLayers
; i
++) {
2407 hwc_layer_1_t
&layer
= contents
->hwLayers
[i
];
2409 mLayerInfos
[i
]->mCompressed
= isCompressed(layer
);
2410 if (layer
.compositionType
== HWC_FRAMEBUFFER_TARGET
) {
2411 DISPLAY_LOGD(eDebugOverlaySupported
, "\tlayer %u: framebuffer target", i
);
2412 mLayerInfos
[i
]->compositionType
= layer
.compositionType
;
2416 if (layer
.compositionType
== HWC_BACKGROUND
&& !mForceFb
) {
2417 DISPLAY_LOGD(eDebugOverlaySupported
, "\tlayer %u: background supported", i
);
2418 dumpLayer(eDebugOverlaySupported
, &contents
->hwLayers
[i
]);
2419 mLayerInfos
[i
]->compositionType
= layer
.compositionType
;
2423 if (layer
.flags
& HWC_SKIP_RENDERING
) {
2424 layer
.compositionType
= HWC_OVERLAY
;
2425 mLayerInfos
[i
]->compositionType
= layer
.compositionType
;
2430 private_handle_t
*handle
= private_handle_t::dynamicCast(layer
.handle
);
2431 if (handle
->format
== HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_PRIV
2432 && rectCount
< mBackUpFrect
.size())
2433 layer
.sourceCropf
= mBackUpFrect
[rectCount
++];
2435 ExynosMPPModule
* supportedInternalMPP
= NULL
;
2436 ExynosMPPModule
* supportedExternalMPP
= NULL
;
2438 if ((int)get_yuv_planes(halFormatToV4L2Format(handle
->format
)) > 0) {
2440 if (!mHwc
->hdmi_hpd
&& mHwc
->mS3DMode
== S3D_MODE_READY
)
2441 mHwc
->mS3DMode
= S3D_MODE_RUNNING
;
2443 mHwc
->incomingPixels
+= WIDTH(layer
.displayFrame
) * HEIGHT(layer
.displayFrame
);
2444 DISPLAY_LOGD(eDebugOverlaySupported
, "\tlayer(%d), type=%d, flags=%08x, handle=%p, tr=%02x, blend=%04x, "
2445 "{%7.1f,%7.1f,%7.1f,%7.1f}, {%d,%d,%d,%d}", i
,
2446 layer
.compositionType
, layer
.flags
, layer
.handle
, layer
.transform
,
2448 layer
.sourceCropf
.left
,
2449 layer
.sourceCropf
.top
,
2450 layer
.sourceCropf
.right
,
2451 layer
.sourceCropf
.bottom
,
2452 layer
.displayFrame
.left
,
2453 layer
.displayFrame
.top
,
2454 layer
.displayFrame
.right
,
2455 layer
.displayFrame
.bottom
);
2456 /* Video layer's compositionType was set in determineYuvOverlay */
2457 if (!isFormatRgb(handle
->format
) && layer
.compositionType
== HWC_OVERLAY
)
2460 if(((getDrmMode(handle
->flags
) != NO_DRM
) ||
2461 (!mForceFb
&& (!mHwc
->hwc_ctrl
.dynamic_recomp_mode
|| mHwc
->CompModeSwitch
!= HWC_2_GLES
))) &&
2462 isOverlaySupported(contents
->hwLayers
[i
], i
, false, &supportedInternalMPP
, &supportedExternalMPP
)) {
2463 DISPLAY_LOGD(eDebugOverlaySupported
, "\tlayer %u: overlay supported", i
);
2464 if (supportedExternalMPP
!= NULL
) {
2465 supportedExternalMPP
->mState
= MPP_STATE_ASSIGNED
;
2466 mLayerInfos
[i
]->mExternalMPP
= supportedExternalMPP
;
2468 if (supportedInternalMPP
!= NULL
) {
2469 supportedInternalMPP
->mState
= MPP_STATE_ASSIGNED
;
2470 mLayerInfos
[i
]->mInternalMPP
= supportedInternalMPP
;
2473 layer
.compositionType
= HWC_OVERLAY
;
2474 mLayerInfos
[i
]->compositionType
= layer
.compositionType
;
2476 dumpLayer(eDebugOverlaySupported
, &contents
->hwLayers
[i
]);
2479 ExynosMPPModule
*dummyInternal
= NULL
;
2480 ExynosMPPModule
*dummyExternal
= NULL
;
2481 DISPLAY_LOGD(eDebugOverlaySupported
, "\tlayer %u: overlay is not supported, dynamic_recomp_mode(%d), CompModeSwitch(%d)", i
, mHwc
->hwc_ctrl
.dynamic_recomp_mode
, mHwc
->CompModeSwitch
);
2483 mLayerInfos
[i
]->mCheckOverlayFlag
|= eForceFbEnabled
;
2484 else if (mHwc
->hwc_ctrl
.dynamic_recomp_mode
&& mHwc
->CompModeSwitch
== HWC_2_GLES
)
2485 mLayerInfos
[i
]->mCheckOverlayFlag
|= eDynamicRecomposition
;
2486 else if (isOverlaySupported(contents
->hwLayers
[i
], i
, false, &dummyInternal
, &dummyExternal
))
2487 mLayerInfos
[i
]->mCheckOverlayFlag
|= eUnknown
;
2490 mLayerInfos
[i
]->mCheckOverlayFlag
|= eInvalidHandle
;
2498 layer
.compositionType
= HWC_FRAMEBUFFER
;
2499 mLayerInfos
[i
]->compositionType
= layer
.compositionType
;
2501 dumpLayer(eDebugOverlaySupported
, &contents
->hwLayers
[i
]);
2504 if (!mHwc
->hdmi_hpd
&& mHwc
->mS3DMode
== S3D_MODE_RUNNING
&& !videoLayer
)
2505 mHwc
->mS3DMode
= S3D_MODE_DISABLED
;
2506 hwc_rect_t base_rect
= {0, 0, 0, 0};
2507 hwc_rect_t intersect_rect
;
2508 for (size_t i
= 0; i
< contents
->numHwLayers
; i
++) {
2509 hwc_layer_1_t
&layer
= contents
->hwLayers
[i
];
2510 if (layer
.compositionType
== HWC_OVERLAY
) {
2512 base_rect
= layer
.displayFrame
;
2513 } else if (hasPlaneAlpha(layer
)) {
2514 //if alpha layer is not completely overlapped with base layer, bypass the alpha layer to GLES.
2515 intersect_rect
= intersection(base_rect
, layer
.displayFrame
);
2516 if (!rectEqual(intersect_rect
, layer
.displayFrame
)) {
2517 layer
.compositionType
= HWC_FRAMEBUFFER
;
2518 mLayerInfos
[i
]->compositionType
= layer
.compositionType
;
2519 mLayerInfos
[i
]->mCheckOverlayFlag
|= eUnsupportedBlending
;
2520 mFirstFb
= min(mFirstFb
, i
);
2521 mLastFb
= max(mLastFb
, i
);
2527 // if one of the bottom layer is HWC_FRAMEBUFFER type, no need to force the alpha layer to FRAMEBUFFER type.
2531 mFirstFb
= min(mFirstFb
, (size_t)NUM_HW_WINDOWS
-1);
2532 // can't composite overlays sandwiched between framebuffers
2534 private_handle_t
*handle
= NULL
;
2535 for (size_t i
= mFirstFb
; i
< mLastFb
; i
++) {
2536 if (contents
->hwLayers
[i
].flags
& HWC_SKIP_RENDERING
)
2539 hwc_layer_1_t
&layer
= contents
->hwLayers
[i
];
2542 handle
= private_handle_t::dynamicCast(layer
.handle
);
2543 if (handle
&& getDrmMode(handle
->flags
) != NO_DRM
) {
2544 layer
.hints
= HWC_HINT_CLEAR_FB
;
2546 contents
->hwLayers
[i
].compositionType
= HWC_FRAMEBUFFER
;
2547 mLayerInfos
[i
]->compositionType
= contents
->hwLayers
[i
].compositionType
;
2548 mLayerInfos
[i
]->mCheckOverlayFlag
|= eSandwitchedBetweenGLES
;
2549 if (mLayerInfos
[i
]->mExternalMPP
!= NULL
) {
2550 mLayerInfos
[i
]->mExternalMPP
->mState
= MPP_STATE_FREE
;
2551 mLayerInfos
[i
]->mExternalMPP
= NULL
;
2553 if (mLayerInfos
[i
]->mInternalMPP
!= NULL
) {
2554 mLayerInfos
[i
]->mInternalMPP
->mState
= MPP_STATE_FREE
;
2555 mLayerInfos
[i
]->mInternalMPP
= NULL
;
2562 void ExynosDisplay::determineBandwidthSupport(hwc_display_contents_1_t
*contents
)
2564 // Incrementally try to add our supported layers to hardware windows.
2565 // If adding a layer would violate a hardware constraint, force it
2566 // into the framebuffer and try again. (Revisiting the entire list is
2567 // necessary because adding a layer to the framebuffer can cause other
2568 // windows to retroactively violate constraints.)
2570 this->mBypassSkipStaticLayer
= false;
2571 unsigned int cannotComposeFlag
= 0;
2572 int internalDMAsUsed
= 0;
2574 int fbIndex
= contents
->numHwLayers
- 1;
2576 // Initialize to inverse values so that
2577 // min(left, l) = l, min(top, t) = t
2578 // max(right, r) = r, max(bottom, b) = b
2579 // for all l, t, r, b
2580 mFbUpdateRegion
.left
= mXres
;
2581 mFbUpdateRegion
.top
= mYres
;
2582 mFbUpdateRegion
.right
= 0;
2583 mFbUpdateRegion
.bottom
= 0;
2586 uint32_t win_idx
= 0;
2587 size_t windows_left
;
2588 unsigned int directFbNum
= 0;
2589 int videoOverlays
= 0;
2590 mHwc
->totPixels
= 0;
2591 ExynosMPPModule
* supportedInternalMPP
= NULL
;
2592 ExynosMPPModule
* supportedExternalMPP
= NULL
;
2595 for (size_t i
= 0; i
< mInternalMPPs
.size(); i
++) {
2596 if (mInternalMPPs
[i
]->mState
!= MPP_STATE_TRANSITION
&&
2598 (mLayerInfos
[mForceOverlayLayerIndex
]->mInternalMPP
!= mInternalMPPs
[i
]))) {
2599 mInternalMPPs
[i
]->mState
= MPP_STATE_FREE
;
2603 for (size_t i
= 0; i
< mExternalMPPs
.size(); i
++) {
2604 if (mExternalMPPs
[i
]->mState
!= MPP_STATE_TRANSITION
&&
2606 (mLayerInfos
[mForceOverlayLayerIndex
]->mExternalMPP
!= mExternalMPPs
[i
]))) {
2607 mExternalMPPs
[i
]->mState
= MPP_STATE_FREE
;
2611 for (size_t i
= 0; i
< contents
->numHwLayers
; i
++) {
2612 if (!mHasDrmSurface
|| (int)i
!= mForceOverlayLayerIndex
) {
2613 mLayerInfos
[i
]->mInternalMPP
= NULL
;
2614 mLayerInfos
[i
]->mExternalMPP
= NULL
;
2621 if (mFbPreAssigned
) {
2622 DISPLAY_LOGD(eDebugResourceAssigning
, "fb has been pre-assigned already");
2623 windows_left
= min(mAllowedOverlays
, mHwc
->hwc_ctrl
.max_num_ovly
) - 1;
2624 } else if (mFbNeeded
&& (contents
->numHwLayers
- 1 > 0)) {
2625 hwc_layer_1_t
&layer
= contents
->hwLayers
[fbIndex
];
2626 if (mUseSecureDMA
&& (mLastFb
== (contents
->numHwLayers
- 2)) && isOverlaySupportedByIDMA(layer
, fbIndex
)) {
2627 /* FramebufferTarget is the top layer, Secure DMA is used */
2628 windows_left
= min(mAllowedOverlays
, mHwc
->hwc_ctrl
.max_num_ovly
);
2629 mLayerInfos
[contents
->numHwLayers
- 1]->mDmaType
= IDMA_SECURE
;
2630 } else if ((mInternalDMAs
.size() > 0) && isOverlaySupportedByIDMA(layer
, fbIndex
)) {
2631 /* Internal DMA is used */
2632 windows_left
= min(mAllowedOverlays
, mHwc
->hwc_ctrl
.max_num_ovly
) - 1;
2633 mLayerInfos
[contents
->numHwLayers
- 1]->mDmaType
= mInternalDMAs
[directFbNum
];
2634 win_idx
= (win_idx
== mFirstFb
) ? (win_idx
+ 1) : win_idx
;
2637 /* VPP should be used for DMA */
2638 windows_left
= min(mAllowedOverlays
, mHwc
->hwc_ctrl
.max_num_ovly
) - 1;
2639 ret
= isOverlaySupported(layer
, fbIndex
, true, &supportedInternalMPP
, &supportedExternalMPP
);
2640 if (ret
&& (supportedInternalMPP
!= NULL
)) {
2641 DISPLAY_LOGD(eDebugResourceAssigning
, "FramebufferTarget internalMPP(%d, %d)", supportedInternalMPP
->mType
, supportedInternalMPP
->mIndex
);
2642 supportedInternalMPP
->mState
= MPP_STATE_ASSIGNED
;
2643 mLayerInfos
[fbIndex
]->mInternalMPP
= supportedInternalMPP
;
2644 mLayerInfos
[fbIndex
]->mDmaType
= getDeconDMAType(mLayerInfos
[fbIndex
]->mInternalMPP
);
2645 #if defined(MAX_DECON_DMA_TYPE)
2646 if (mLayerInfos
[fbIndex
]->mDmaType
>= MAX_DECON_DMA_TYPE
) {
2648 if (mLayerInfos
[fbIndex
]->mDmaType
>= IDMA_MAX
) {
2650 ALOGE("getDeconDMAType with InternalMPP for FramebufferTarget failed (MPP type: %d, MPP index: %d)",
2651 mLayerInfos
[fbIndex
]->mInternalMPP
->mType
, mLayerInfos
[fbIndex
]->mInternalMPP
->mIndex
);
2652 mLayerInfos
[fbIndex
]->mDmaType
= 0;
2654 win_idx
= (win_idx
== mFirstFb
) ? (win_idx
+ 1) : win_idx
;
2656 ALOGE("VPP should be assigned to FramebufferTarget but it was failed ret(%d)", ret
);
2659 mHwc
->totPixels
+= mXres
* mYres
;
2661 windows_left
= min(mAllowedOverlays
, mHwc
->hwc_ctrl
.max_num_ovly
);
2664 DISPLAY_LOGD(eDebugResourceAssigning
, "determineBandwidthSupport:: retry(%d), mAllowedOverlays(%d), windows_left(%d), win_idx(%d)",
2665 retry
, mAllowedOverlays
, windows_left
, win_idx
);
2667 for (size_t i
= 0; i
< contents
->numHwLayers
; i
++) {
2668 hwc_layer_1_t
&layer
= contents
->hwLayers
[i
];
2669 bool isTopLayer
= (i
== contents
->numHwLayers
- 2) ? true:false;
2670 private_handle_t
*handle
= NULL
;
2672 if (layer
.flags
& HWC_SKIP_RENDERING
)
2675 if ((layer
.flags
& HWC_SKIP_LAYER
) ||
2676 (layer
.compositionType
== HWC_FRAMEBUFFER_TARGET
))
2679 if (!layer
.planeAlpha
)
2683 handle
= private_handle_t::dynamicCast(layer
.handle
);
2687 // we've already accounted for the framebuffer above
2688 if (layer
.compositionType
== HWC_FRAMEBUFFER
)
2691 // only layer 0 can be HWC_BACKGROUND, so we can
2692 // unconditionally allow it without extra checks
2693 if (layer
.compositionType
== HWC_BACKGROUND
) {
2698 cannotComposeFlag
= 0;
2699 bool can_compose
= windows_left
&& (win_idx
< NUM_HW_WINDOWS
);
2700 if (mUseSecureDMA
&& !isCompressed(layer
) && isTopLayer
)
2702 else if (windows_left
<= 0 || (win_idx
>= NUM_HW_WINDOWS
))
2703 cannotComposeFlag
|= eInsufficientWindow
;
2704 if (!isFormatRgb(handle
->format
) && videoOverlays
>= mHwc
->hwc_ctrl
.num_of_video_ovly
) {
2705 can_compose
= false;
2706 cannotComposeFlag
|= eInsufficientMPP
;
2709 /* mInternalMPP, mExternalMPP could be set by determineYuvOverlay */
2710 supportedInternalMPP
= mLayerInfos
[i
]->mInternalMPP
;
2711 supportedExternalMPP
= mLayerInfos
[i
]->mExternalMPP
;
2713 if (can_compose
&& !isProcessingRequired(layer
) && isOverlaySupportedByIDMA(layer
, i
) &&
2714 (directFbNum
< mInternalDMAs
.size() || (mUseSecureDMA
&& isTopLayer
))) {
2715 if (directFbNum
< mInternalDMAs
.size())
2717 DISPLAY_LOGD(eDebugResourceAssigning
, "layer(%d) is directFB", i
);
2718 } else if (can_compose
&& isOverlaySupported(layer
, i
,
2719 !isProcessingRequired(layer
) |
2720 (directFbNum
>= mInternalDMAs
.size() && !(mUseSecureDMA
&& isTopLayer
)),
2721 &supportedInternalMPP
, &supportedExternalMPP
)) {
2722 DISPLAY_LOGD(eDebugResourceAssigning
, "layer(%d) is OVERLAY ",i
);
2723 if (supportedInternalMPP
!= NULL
) {
2724 DISPLAY_LOGD(eDebugResourceAssigning
, "layer(%d) is OVERLAY internalMPP(%d, %d)", i
, supportedInternalMPP
->mType
, supportedInternalMPP
->mIndex
);
2725 supportedInternalMPP
->mState
= MPP_STATE_ASSIGNED
;
2726 mLayerInfos
[i
]->mInternalMPP
= supportedInternalMPP
;
2727 mLayerInfos
[i
]->mDmaType
= getDeconDMAType(mLayerInfos
[i
]->mInternalMPP
);
2729 if (supportedExternalMPP
!= NULL
) {
2730 DISPLAY_LOGD(eDebugResourceAssigning
, "layer(%d) is OVERLAY externalMPP(%d, %d)", i
, supportedExternalMPP
->mType
, supportedExternalMPP
->mIndex
);
2731 supportedExternalMPP
->mState
= MPP_STATE_ASSIGNED
;
2732 mLayerInfos
[i
]->mExternalMPP
= supportedExternalMPP
;
2733 if ((supportedInternalMPP
== NULL
) && isOverlaySupportedByIDMA(layer
, i
) &&
2734 ((directFbNum
< mInternalDMAs
.size()) || (mUseSecureDMA
&& isTopLayer
))) {
2735 if (directFbNum
< mInternalDMAs
.size()) {
2736 mLayerInfos
[i
]->mDmaType
= mInternalDMAs
[directFbNum
];
2739 mLayerInfos
[i
]->mDmaType
= IDMA_SECURE
;
2744 if (!isFormatRgb(handle
->format
))
2747 DISPLAY_LOGD(eDebugResourceAssigning
, "layer(%d) is changed to FRAMEBUFFER", i
);
2748 can_compose
= false;
2752 size_t changed_index
= i
;
2753 hwc_layer_1_t
*layer_for_gles
= &contents
->hwLayers
[i
];
2754 if (getDrmMode(handle
->flags
) != NO_DRM
) {
2756 for (j
= i
- 1; j
>= 0 ; j
--) {
2757 layer_for_gles
= &contents
->hwLayers
[j
];
2758 if (layer_for_gles
->compositionType
== HWC_OVERLAY
) {
2766 layer_for_gles
= &contents
->hwLayers
[changed_index
];
2769 layer_for_gles
->compositionType
= HWC_FRAMEBUFFER
;
2770 mLayerInfos
[changed_index
]->compositionType
= layer_for_gles
->compositionType
;
2771 mLayerInfos
[changed_index
]->mCheckOverlayFlag
|= cannotComposeFlag
;
2772 if (mLayerInfos
[changed_index
]->mInternalMPP
!= NULL
)
2773 mLayerInfos
[changed_index
]->mInternalMPP
->mState
= MPP_STATE_FREE
;
2774 if (mLayerInfos
[changed_index
]->mExternalMPP
!= NULL
)
2775 mLayerInfos
[changed_index
]->mExternalMPP
->mState
= MPP_STATE_FREE
;
2776 mLayerInfos
[changed_index
]->mInternalMPP
= NULL
;
2777 mLayerInfos
[changed_index
]->mExternalMPP
= NULL
;
2779 mFirstFb
= mLastFb
= changed_index
;
2781 mHwc
->totPixels
+= mXres
* mYres
;
2784 mFirstFb
= min(changed_index
, mFirstFb
);
2785 mLastFb
= max(changed_index
, mLastFb
);
2788 mFirstFb
= min(mFirstFb
, (size_t)NUM_HW_WINDOWS
-1);
2791 mHwc
->totPixels
+= WIDTH(layer
.displayFrame
) * HEIGHT(layer
.displayFrame
);
2794 if ((mUseSecureDMA
== false) || (isTopLayer
== false)) {
2796 /* FB Target is not top layer */
2797 if (mFbNeeded
&& ((mUseSecureDMA
&& !isCompressed(layer
))|| (mLastFb
!= (contents
->numHwLayers
- 2))))
2798 win_idx
= (win_idx
== mFirstFb
) ? (win_idx
+ 1) : win_idx
;
2799 win_idx
= min((size_t)win_idx
, (size_t)(NUM_HW_WINDOWS
- 1));
2805 for (size_t i
= mFirstFb
; i
< mLastFb
; i
++) {
2806 hwc_layer_1_t
&layer
= contents
->hwLayers
[i
];
2807 private_handle_t
*handle
= NULL
;
2809 handle
= private_handle_t::dynamicCast(layer
.handle
);
2810 if (handle
&& getDrmMode(handle
->flags
) != NO_DRM
) {
2811 layer
.hints
= HWC_HINT_CLEAR_FB
;
2813 contents
->hwLayers
[i
].compositionType
= HWC_FRAMEBUFFER
;
2814 mLayerInfos
[i
]->compositionType
= contents
->hwLayers
[i
].compositionType
;
2815 mLayerInfos
[i
]->mCheckOverlayFlag
|= eSandwitchedBetweenGLES
;
2816 if (mLayerInfos
[i
]->mInternalMPP
!= NULL
)
2817 mLayerInfos
[i
]->mInternalMPP
->mState
= MPP_STATE_FREE
;
2818 if (mLayerInfos
[i
]->mExternalMPP
!= NULL
)
2819 mLayerInfos
[i
]->mExternalMPP
->mState
= MPP_STATE_FREE
;
2820 mLayerInfos
[i
]->mInternalMPP
= NULL
;
2821 mLayerInfos
[i
]->mExternalMPP
= NULL
;
2822 if (handle
&& !isFormatRgb(handle
->format
))
2826 if (handleTotalBandwidthOverload(contents
))
2831 DISPLAY_LOGE("%s", "retry 100, can't allocate vpp, dump error state");
2832 android::String8 result
;
2834 dumpLayerInfo(result
);
2835 DISPLAY_LOGE("%s", result
.string());
2840 uint32_t rectCount
= 0;
2841 for (size_t i
= 0; i
< contents
->numHwLayers
; i
++) {
2842 hwc_layer_1_t
&layer
= contents
->hwLayers
[i
];
2844 private_handle_t
*handle
= private_handle_t::dynamicCast(layer
.handle
);
2845 if (handle
->format
== HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_PRIV
2846 && rectCount
< mOriginFrect
.size())
2847 layer
.sourceCropf
= mOriginFrect
[rectCount
++];
2851 for (size_t i
= 0; i
< contents
->numHwLayers
; i
++) {
2852 hwc_layer_1_t
&layer
= contents
->hwLayers
[i
];
2853 if (layer
.compositionType
== HWC_FRAMEBUFFER
)
2854 mFbUpdateRegion
= expand(mFbUpdateRegion
, layer
.displayFrame
);
2857 for (size_t i
= mLastFb
+ 1; i
< contents
->numHwLayers
; i
++) {
2858 hwc_layer_1_t
&layer
= contents
->hwLayers
[i
];
2859 if (layer
.compositionType
== HWC_OVERLAY
&& layer
.planeAlpha
> 0 && layer
.planeAlpha
< 255)
2860 mFbUpdateRegion
= expand(mFbUpdateRegion
, contents
->hwLayers
[i
].displayFrame
);
2864 #ifdef USE_DRM_BURST_LEN
2866 minWidth
= DRM_BURSTLEN_BYTES
* 8 / formatToBpp(HAL_PIXEL_FORMAT_RGBA_8888
);
2869 minWidth
= BURSTLEN_BYTES
* 8 / formatToBpp(HAL_PIXEL_FORMAT_RGBA_8888
);
2871 int w
= WIDTH(mFbUpdateRegion
);
2873 #if defined(USES_DUAL_DISPLAY)
2874 uint32_t maxRightPosition
= (mType
== EXYNOS_PRIMARY_DISPLAY
)?(mXres
/2):mXres
;
2875 if (mFbUpdateRegion
.left
+ minWidth
<= maxRightPosition
)
2876 mFbUpdateRegion
.right
= mFbUpdateRegion
.left
+ minWidth
;
2878 mFbUpdateRegion
.left
= mFbUpdateRegion
.right
- minWidth
;
2880 if (mFbUpdateRegion
.left
+ minWidth
<= mXres
)
2881 mFbUpdateRegion
.right
= mFbUpdateRegion
.left
+ minWidth
;
2883 mFbUpdateRegion
.left
= mFbUpdateRegion
.right
- minWidth
;
2888 void ExynosDisplay::assignWindows(hwc_display_contents_1_t
*contents
)
2890 unsigned int nextWindow
= 0;
2891 unsigned int directFbNum
= 0;
2892 bool isTopLayer
= false;
2894 hwc_layer_1_t
&fbLayer
= contents
->hwLayers
[contents
->numHwLayers
- 1];
2895 if (mFbNeeded
&& (contents
->numHwLayers
- 1 > 0)) {
2896 /* FramebufferTarget is the top layer */
2897 if (mUseSecureDMA
&& !isCompressed(fbLayer
) && mLastFb
== (contents
->numHwLayers
- 2))
2898 mLayerInfos
[contents
->numHwLayers
- 1]->mDmaType
= IDMA_SECURE
;
2899 else if (mInternalDMAs
.size() > 0 && !isCompressed(fbLayer
)) {
2900 mLayerInfos
[contents
->numHwLayers
- 1]->mDmaType
= mInternalDMAs
[directFbNum
];
2903 /* mDmaType was set by determineBandwidthSupport() */
2906 DISPLAY_LOGD(eDebugResourceAssigning
, "assigning layer %u to DMA %u", contents
->numHwLayers
- 1, mLayerInfos
[contents
->numHwLayers
- 1]->mDmaType
);
2909 if (mFbNeeded
&& mUseSecureDMA
&& !isCompressed(fbLayer
) && (mLastFb
== (contents
->numHwLayers
- 2)))
2910 mFbWindow
= NUM_HW_WINDOWS
- 1;
2912 mFbWindow
= NO_FB_NEEDED
;
2914 for (size_t i
= 0; i
< contents
->numHwLayers
; i
++) {
2915 hwc_layer_1_t
&layer
= contents
->hwLayers
[i
];
2916 mLayerInfos
[i
]->mWindowIndex
= -1;
2917 isTopLayer
= (i
== contents
->numHwLayers
- 2) ? true:false;
2919 if (mFbNeeded
&& (mFbWindow
!= NUM_HW_WINDOWS
- 1)) {
2921 mFbWindow
= nextWindow
;
2927 if (layer
.flags
& HWC_SKIP_RENDERING
)
2930 if (!layer
.planeAlpha
) {
2931 if (layer
.acquireFenceFd
>= 0)
2932 close(layer
.acquireFenceFd
);
2933 layer
.acquireFenceFd
= -1;
2934 layer
.releaseFenceFd
= -1;
2938 if (layer
.compositionType
!= HWC_FRAMEBUFFER
) {
2939 if (mFbNeeded
&& (layer
.compositionType
== HWC_FRAMEBUFFER_TARGET
)) {
2940 DISPLAY_LOGD(eDebugResourceAssigning
, "assigning framebuffer target %u to window %u", i
, nextWindow
);
2941 mLayerInfos
[i
]->mWindowIndex
= mFbWindow
;
2942 if (mLayerInfos
[i
]->mInternalMPP
!= NULL
)
2943 mLayerInfos
[i
]->mInternalMPP
->setDisplay(this);
2946 if (layer
.compositionType
== HWC_OVERLAY
) {
2947 if ((!isProcessingRequired(layer
) ||
2948 ((mLayerInfos
[i
]->mInternalMPP
== NULL
) && (mLayerInfos
[i
]->mExternalMPP
!= NULL
))) &&
2949 isOverlaySupportedByIDMA(layer
, i
) && (directFbNum
< mInternalDMAs
.size() || (mUseSecureDMA
&& isTopLayer
)))
2951 if (directFbNum
< mInternalDMAs
.size()) {
2952 DISPLAY_LOGD(eDebugResourceAssigning
, "assigning layer %u to DMA %u", i
, mInternalDMAs
[directFbNum
]);
2953 mLayerInfos
[i
]->mDmaType
= mInternalDMAs
[directFbNum
];
2954 mLayerInfos
[i
]->mWindowIndex
= nextWindow
;
2957 DISPLAY_LOGD(eDebugResourceAssigning
, "assigning layer %u to DMA %u", i
, IDMA_SECURE
);
2958 mLayerInfos
[i
]->mDmaType
= IDMA_SECURE
;
2959 mLayerInfos
[i
]->mWindowIndex
= NUM_HW_WINDOWS
- 1;
2962 DISPLAY_LOGD(eDebugResourceAssigning
, "%u layer can't use internalDMA, isProcessingRequired(%d)", i
, isProcessingRequired(layer
));
2963 unsigned int dmaType
= 0;
2964 mLayerInfos
[i
]->mWindowIndex
= nextWindow
;
2965 if (mLayerInfos
[i
]->mInternalMPP
!= NULL
) {
2966 mLayerInfos
[i
]->mInternalMPP
->setDisplay(this);
2967 mLayerInfos
[i
]->mDmaType
= getDeconDMAType(mLayerInfos
[i
]->mInternalMPP
);
2968 DISPLAY_LOGD(eDebugResourceAssigning
, "assigning layer %u to DMA %u", i
, mLayerInfos
[i
]->mDmaType
);
2970 /* Find unused DMA connected with VPP */
2971 for (size_t j
= 0; j
< mInternalMPPs
.size(); j
++ )
2973 if ((mInternalMPPs
[j
]->mState
== MPP_STATE_FREE
) &&
2974 ((mInternalMPPs
[j
]->mDisplay
== NULL
) || (mInternalMPPs
[j
]->mDisplay
== this))) {
2975 mLayerInfos
[i
]->mInternalMPP
= mInternalMPPs
[j
];
2976 mLayerInfos
[i
]->mDmaType
= getDeconDMAType(mLayerInfos
[i
]->mInternalMPP
);
2977 mLayerInfos
[i
]->mInternalMPP
->setDisplay(this);
2978 mLayerInfos
[i
]->mInternalMPP
->mState
= MPP_STATE_ASSIGNED
;
2979 DISPLAY_LOGD(eDebugResourceAssigning
, "assigning layer %u to DMA %u", i
, mLayerInfos
[i
]->mDmaType
);
2985 if (mLayerInfos
[i
]->mExternalMPP
!= NULL
)
2986 mLayerInfos
[i
]->mExternalMPP
->setDisplay(this);
2988 if (mLayerInfos
[i
]->mWindowIndex
!= NUM_HW_WINDOWS
- 1)
2993 for (size_t i
= 0; i
< contents
->numHwLayers
; i
++) {
2994 hwc_layer_1_t
&layer
= contents
->hwLayers
[i
];
2995 if (layer
.compositionType
== HWC_FRAMEBUFFER
||
2996 layer
.compositionType
== HWC_FRAMEBUFFER_TARGET
) {
2997 mLayerInfos
[i
]->mWindowIndex
= mFbWindow
;
2998 if (contents
->numHwLayers
- 1 > 0) {
2999 mLayerInfos
[i
]->mDmaType
= mLayerInfos
[contents
->numHwLayers
- 1]->mDmaType
;
3005 int ExynosDisplay::postMPPM2M(hwc_layer_1_t
&layer
, struct decon_win_config
*config
, int win_map
, int index
)
3007 //exynos5_hwc_post_data_t *pdata = &mPostData;
3008 //int gsc_idx = pdata->gsc_map[index].idx;
3009 int dst_format
= mExternalMPPDstFormat
;
3010 private_handle_t
*handle
= private_handle_t::dynamicCast(layer
.handle
);
3011 ExynosMPPModule
*exynosMPP
= mLayerInfos
[index
]->mExternalMPP
;
3012 ExynosMPPModule
*exynosInternalMPP
= mLayerInfos
[index
]->mInternalMPP
;
3013 hwc_layer_1_t extMPPOutLayer
;
3015 if (exynosMPP
== NULL
) {
3016 DISPLAY_LOGE("postMPPM2M is called but externMPP is NULL");
3017 if (layer
.acquireFenceFd
>= 0)
3018 close(layer
.acquireFenceFd
);
3019 layer
.acquireFenceFd
= -1;
3020 layer
.releaseFenceFd
= -1;
3024 hwc_frect_t sourceCrop
= { 0, 0,
3025 (float)WIDTH(layer
.displayFrame
), (float)HEIGHT(layer
.displayFrame
) };
3026 int originalTransform
= layer
.transform
;
3027 hwc_rect_t originalDisplayFrame
= layer
.displayFrame
;
3029 bool bothMPPUsed
= isBothMPPProcessingRequired(layer
, &extMPPOutLayer
);
3031 sourceCrop
.right
= extMPPOutLayer
.displayFrame
.right
;
3032 sourceCrop
.bottom
= extMPPOutLayer
.displayFrame
.bottom
;
3033 layer
.displayFrame
= extMPPOutLayer
.displayFrame
;
3036 if (mType
== EXYNOS_PRIMARY_DISPLAY
) {
3037 handle
->flags
&= ~GRALLOC_USAGE_VIDEO_EXT
;
3038 if (mHwc
->mS3DMode
== S3D_MODE_READY
|| mHwc
->mS3DMode
== S3D_MODE_RUNNING
) {
3039 int S3DFormat
= getS3DFormat(mHwc
->mHdmiPreset
);
3040 if (S3DFormat
== S3D_SBS
)
3041 exynosMPP
->mS3DMode
= S3D_SBS
;
3042 else if (S3DFormat
== S3D_TB
)
3043 exynosMPP
->mS3DMode
= S3D_TB
;
3045 exynosMPP
->mS3DMode
= S3D_NONE
;
3049 /* OFF_Screen to ON_Screen changes */
3050 if (getDrmMode(handle
->flags
) != NO_DRM
)
3051 recalculateDisplayFrame(layer
, mXres
, mYres
);
3053 if (mType
!= EXYNOS_VIRTUAL_DISPLAY
&&
3054 (isFormatRgb(handle
->format
) ||
3055 (bothMPPUsed
&& !isFormatRgb(handle
->format
) &&
3056 exynosInternalMPP
!= NULL
&&
3057 exynosInternalMPP
->isCSCSupportedByMPP(handle
->format
, HAL_PIXEL_FORMAT_RGBX_8888
, layer
.dataSpace
) &&
3058 exynosInternalMPP
->isFormatSupportedByMPP(handle
->format
) &&
3059 WIDTH(extMPPOutLayer
.displayFrame
) % exynosInternalMPP
->getCropWidthAlign(layer
) == 0 &&
3060 HEIGHT(extMPPOutLayer
.displayFrame
) % exynosInternalMPP
->getCropHeightAlign(layer
) == 0)))
3061 dst_format
= handle
->format
;
3062 int err
= exynosMPP
->processM2M(layer
, dst_format
, &sourceCrop
);
3064 /* Restore displayFrame*/
3065 layer
.displayFrame
= originalDisplayFrame
;
3068 DISPLAY_LOGE("failed to configure MPP (type:%u, index:%u) for layer %u",
3069 exynosMPP
->mType
, exynosMPP
->mIndex
, index
);
3073 buffer_handle_t dst_buf
= exynosMPP
->mDstBuffers
[exynosMPP
->mCurrentBuf
];
3074 private_handle_t
*dst_handle
=
3075 private_handle_t::dynamicCast(dst_buf
);
3076 int fence
= exynosMPP
->mDstConfig
.releaseFenceFd
;
3077 hwc_frect originalCrop
= layer
.sourceCropf
;
3078 int originalFormat
= handle
->format
;
3080 /* ExtMPP out is the input of Decon
3081 * and Trsform was processed by ExtMPP
3083 layer
.sourceCropf
= sourceCrop
;
3084 layer
.transform
= 0;
3085 handle
->format
= dst_format
;
3086 configureHandle(dst_handle
, index
, layer
, fence
, config
[win_map
]);
3088 /* Restore sourceCropf and transform */
3089 layer
.sourceCropf
= originalCrop
;
3090 layer
.transform
= originalTransform
;
3091 handle
->format
= originalFormat
;
3095 void ExynosDisplay::handleStaticLayers(hwc_display_contents_1_t
*contents
, struct decon_win_config_data
&win_data
, int __unused tot_ovly_wins
)
3098 if (mLastFbWindow
>= NUM_HW_WINDOWS
) {
3099 DISPLAY_LOGE("handleStaticLayers:: invalid mLastFbWindow(%d)", mLastFbWindow
);
3102 win_map
= mLastFbWindow
;
3103 DISPLAY_LOGD(eDebugSkipStaicLayer
, "[USE] SKIP_STATIC_LAYER_COMP, mLastFbWindow(%d), win_map(%d)\n", mLastFbWindow
, win_map
);
3105 memcpy(&win_data
.config
[win_map
],
3106 &mLastConfigData
.config
[win_map
], sizeof(struct decon_win_config
));
3107 win_data
.config
[win_map
].fence_fd
= -1;
3109 for (size_t i
= mFirstFb
; i
<= mLastFb
; i
++) {
3110 hwc_layer_1_t
&layer
= contents
->hwLayers
[i
];
3111 private_handle_t
*handle
= NULL
;
3112 if (layer
.handle
== NULL
)
3115 handle
= private_handle_t::dynamicCast(layer
.handle
);
3117 if ((getDrmMode(handle
->flags
) == NO_DRM
) &&
3118 (layer
.compositionType
== HWC_OVERLAY
)) {
3119 DISPLAY_LOGD(eDebugSkipStaicLayer
, "[SKIP_STATIC_LAYER_COMP] layer.handle: 0x%p, layer.acquireFenceFd: %d\n", layer
.handle
, layer
.acquireFenceFd
);
3120 if (layer
.acquireFenceFd
>= 0)
3121 close(layer
.acquireFenceFd
);
3122 layer
.acquireFenceFd
= -1;
3123 layer
.releaseFenceFd
= -1;
3128 bool ExynosDisplay::multipleRGBScaling(int format
)
3130 return isFormatRgb(format
) &&
3134 bool ExynosDisplay::isProcessingRequired(hwc_layer_1_t
&layer
)
3138 private_handle_t
*handle
= private_handle_t::dynamicCast(layer
.handle
);
3139 return !(isFormatRgb(handle
->format
)) || isScaled(layer
) || isTransformed(layer
) || isCompressed(layer
) ||
3140 isFloat(layer
.sourceCropf
.left
) || isFloat(layer
.sourceCropf
.top
) ||
3141 isFloat(layer
.sourceCropf
.right
- layer
.sourceCropf
.left
) ||
3142 isFloat(layer
.sourceCropf
.bottom
- layer
.sourceCropf
.top
);
3145 bool ExynosDisplay::isBothMPPProcessingRequired(hwc_layer_1_t
&layer
)
3147 bool needDoubleOperation
= false;
3148 private_handle_t
*srcHandle
= NULL
;
3150 if (layer
.handle
== NULL
)
3153 srcHandle
= private_handle_t::dynamicCast(layer
.handle
);
3154 if ((mExternalMPPs
.size() == 0) || (mInternalMPPs
.size() == 0))
3157 /* Check scale ratio */
3158 int maxUpscaleExt
= mExternalMPPs
[0]->getMaxUpscale();
3159 int maxUpscaleInt
= mCheckIntMPP
->getMaxUpscale();
3160 bool rot90or270
= !!(layer
.transform
& HAL_TRANSFORM_ROT_90
);
3161 int srcW
= WIDTH(layer
.sourceCropf
), srcH
= HEIGHT(layer
.sourceCropf
);
3164 dstW
= HEIGHT(layer
.displayFrame
);
3165 dstH
= WIDTH(layer
.displayFrame
);
3167 dstW
= WIDTH(layer
.displayFrame
);
3168 dstH
= HEIGHT(layer
.displayFrame
);
3170 needDoubleOperation
= ((dstW
> srcW
* maxUpscaleExt
) && (dstW
<= srcW
* maxUpscaleExt
* maxUpscaleInt
)) ||
3171 ((dstH
> srcH
* maxUpscaleExt
) && (dstH
<= srcH
* maxUpscaleExt
* maxUpscaleInt
));
3173 int maxDownscaleExt
= mExternalMPPs
[0]->getMaxDownscale(layer
);
3174 int maxDownscaleInt
= mCheckIntMPP
->getMaxDownscale(layer
);
3176 needDoubleOperation
|= ((dstW
< srcW
/ maxDownscaleExt
) && (dstW
>= srcW
/ (maxDownscaleExt
* maxDownscaleExt
))) ||
3177 ((dstH
< srcH
/ maxDownscaleExt
) && (dstH
>= srcH
/ (maxDownscaleExt
* maxDownscaleExt
)));
3180 * Both VPP and MSC should be used if
3181 * MSC should be used for DRM contents
3183 if (getDrmMode(srcHandle
->flags
) != NO_DRM
) {
3184 bool supportVPP
= false;
3185 for (size_t i
= 0; i
< mInternalMPPs
.size(); i
++ )
3187 if (mInternalMPPs
[i
]->isProcessingSupported(layer
, srcHandle
->format
) > 0) {
3192 if (supportVPP
== false)
3193 needDoubleOperation
|= true;
3198 * Destination format should be RGB if dstW or dstH is not aligned.
3199 * VPP is not required at this time.
3201 if (!isFormatRgb(srcHandle
->format
) &&
3202 (srcW
>= UHD_WIDTH
|| srcH
>= UHD_HEIGHT
) &&
3203 (mInternalMPPs
.size() > 0) &&
3204 (dstW
% mCheckIntMPP
->getCropWidthAlign(layer
) == 0) &&
3205 (dstH
% mCheckIntMPP
->getCropHeightAlign(layer
) == 0)) {
3206 needDoubleOperation
|= true;
3209 return needDoubleOperation
;
3212 bool ExynosDisplay::isBothMPPProcessingRequired(hwc_layer_1_t
&layer
, hwc_layer_1_t
*extMPPOutLayer
)
3214 bool needDoubleOperation
= false;
3215 if (layer
.handle
== NULL
)
3218 private_handle_t
*srcHandle
= private_handle_t::dynamicCast(layer
.handle
);
3219 if ((mExternalMPPs
.size() == 0) || (mInternalMPPs
.size() == 0))
3222 int maxUpscaleExt
= mExternalMPPs
[0]->getMaxUpscale();
3223 int maxUpscaleInt
= mCheckIntMPP
->getMaxUpscale();
3224 bool rot90or270
= !!(layer
.transform
& HAL_TRANSFORM_ROT_90
);
3225 int srcW
= WIDTH(layer
.sourceCropf
), srcH
= HEIGHT(layer
.sourceCropf
);
3228 dstW
= HEIGHT(layer
.displayFrame
);
3229 dstH
= WIDTH(layer
.displayFrame
);
3231 dstW
= WIDTH(layer
.displayFrame
);
3232 dstH
= HEIGHT(layer
.displayFrame
);
3235 int maxDownscaleExt
= mExternalMPPs
[0]->getMaxDownscale(layer
);
3236 int maxDownscaleInt
= mCheckIntMPP
->getMaxDownscale(layer
);
3238 needDoubleOperation
= isBothMPPProcessingRequired(layer
);
3240 /* set extMPPOutLayer */
3241 if (needDoubleOperation
&& extMPPOutLayer
!= NULL
) {
3242 memcpy(extMPPOutLayer
, &layer
, sizeof(hwc_layer_1_t
));
3243 extMPPOutLayer
->displayFrame
.left
= 0;
3244 extMPPOutLayer
->displayFrame
.top
= 0;
3246 if (dstW
> srcW
* maxUpscaleExt
) {
3247 extMPPOutLayer
->displayFrame
.right
= ALIGN_UP((int)ceilf((float)dstW
/ maxUpscaleInt
),
3248 mExternalMPPs
[0]->getDstWidthAlign(srcHandle
->format
));
3249 } else if (dstW
< srcW
/ maxDownscaleExt
) {
3250 extMPPOutLayer
->displayFrame
.right
= ALIGN(dstW
* maxDownscaleInt
,
3251 mExternalMPPs
[0]->getDstWidthAlign(srcHandle
->format
));
3253 extMPPOutLayer
->displayFrame
.right
= dstW
;
3256 if (dstH
> srcH
* maxUpscaleExt
) {
3257 extMPPOutLayer
->displayFrame
.bottom
= ALIGN_UP((int)ceilf((float)dstH
/ maxUpscaleInt
),
3258 mExternalMPPs
[0]->getDstHeightAlign(srcHandle
->format
));
3259 } else if (dstH
< srcH
/ maxDownscaleExt
) {
3260 extMPPOutLayer
->displayFrame
.bottom
= ALIGN(dstH
* maxDownscaleInt
,
3261 mExternalMPPs
[0]->getDstHeightAlign(srcHandle
->format
));
3263 extMPPOutLayer
->displayFrame
.bottom
= dstH
;
3267 dstW
= extMPPOutLayer
->displayFrame
.bottom
;
3268 dstH
= extMPPOutLayer
->displayFrame
.right
;
3269 extMPPOutLayer
->displayFrame
.right
= dstW
;
3270 extMPPOutLayer
->displayFrame
.bottom
= dstH
;
3274 return needDoubleOperation
;
3277 bool ExynosDisplay::isSourceCropfSupported(hwc_layer_1_t layer
)
3279 private_handle_t
*handle
= private_handle_t::dynamicCast(layer
.handle
);
3280 unsigned int bpp
= formatToBpp(handle
->format
);
3282 /* HACK: Disable overlay if the layer have float position or size */
3284 if ((isFormatRgb(handle
->format
) && (bpp
== 32)) ||
3285 isFormatYUV420(handle
->format
))
3292 bool ExynosDisplay::checkConfigChanged(struct decon_win_config_data
&lastConfigData
, struct decon_win_config_data
&newConfigData
)
3294 for (size_t i
= 0; i
<= MAX_DECON_WIN
; i
++) {
3295 if ((lastConfigData
.config
[i
].state
!= newConfigData
.config
[i
].state
) ||
3296 (lastConfigData
.config
[i
].fd_idma
[0] != newConfigData
.config
[i
].fd_idma
[0]) ||
3297 (lastConfigData
.config
[i
].fd_idma
[1] != newConfigData
.config
[i
].fd_idma
[1]) ||
3298 (lastConfigData
.config
[i
].fd_idma
[2] != newConfigData
.config
[i
].fd_idma
[2]) ||
3299 (lastConfigData
.config
[i
].dst
.x
!= newConfigData
.config
[i
].dst
.x
) ||
3300 (lastConfigData
.config
[i
].dst
.y
!= newConfigData
.config
[i
].dst
.y
) ||
3301 (lastConfigData
.config
[i
].dst
.w
!= newConfigData
.config
[i
].dst
.w
) ||
3302 (lastConfigData
.config
[i
].dst
.h
!= newConfigData
.config
[i
].dst
.h
) ||
3303 (lastConfigData
.config
[i
].src
.x
!= newConfigData
.config
[i
].src
.x
) ||
3304 (lastConfigData
.config
[i
].src
.y
!= newConfigData
.config
[i
].src
.y
) ||
3305 (lastConfigData
.config
[i
].src
.w
!= newConfigData
.config
[i
].src
.w
) ||
3306 (lastConfigData
.config
[i
].src
.h
!= newConfigData
.config
[i
].src
.h
) ||
3307 (lastConfigData
.config
[i
].format
!= newConfigData
.config
[i
].format
) ||
3308 (lastConfigData
.config
[i
].blending
!= newConfigData
.config
[i
].blending
) ||
3309 (lastConfigData
.config
[i
].plane_alpha
!= newConfigData
.config
[i
].plane_alpha
))
3315 void ExynosDisplay::removeIDMA(decon_idma_type idma
)
3317 for (size_t i
= mInternalDMAs
.size(); i
-- > 0;) {
3318 if (mInternalDMAs
[i
] == (unsigned int)idma
) {
3319 mInternalDMAs
.removeItemsAt(i
);
3324 int ExynosDisplay::getDisplayConfigs(uint32_t *configs
, size_t *numConfigs
)
3331 int ExynosDisplay::getDeconDMAType(ExynosMPPModule
* internalMPP
)
3333 if (internalMPP
->mType
== MPP_VG
)
3334 return IDMA_VG0
+ internalMPP
->mIndex
;
3335 else if (internalMPP
->mType
== MPP_VGR
)
3336 return IDMA_VGR0
+ internalMPP
->mIndex
;
3337 else if (internalMPP
->mType
== MPP_VPP_G
) {
3338 switch (internalMPP
->mIndex
) {
3354 void ExynosDisplay::dumpContents(android::String8
& result
, hwc_display_contents_1_t
*contents
)
3356 for (size_t i
= 0; i
< contents
->numHwLayers
; i
++) {
3357 hwc_layer_1_t
&layer
= contents
->hwLayers
[i
];
3358 result
.appendFormat("[%zu] type=%d, flags=%08x, handle=%p, tr=%02x, blend=%04x, "
3359 "{%7.1f,%7.1f,%7.1f,%7.1f}, {%d,%d,%d,%d}\n",
3361 layer
.compositionType
, layer
.flags
, layer
.handle
, layer
.transform
,
3363 layer
.sourceCropf
.left
,
3364 layer
.sourceCropf
.top
,
3365 layer
.sourceCropf
.right
,
3366 layer
.sourceCropf
.bottom
,
3367 layer
.displayFrame
.left
,
3368 layer
.displayFrame
.top
,
3369 layer
.displayFrame
.right
,
3370 layer
.displayFrame
.bottom
);
3375 int ExynosDisplay::checkConfigValidation(decon_win_config
*config
)
3377 bool flagValidConfig
= true;
3378 for (size_t i
= 0; i
< MAX_DECON_WIN
; i
++) {
3379 if (config
[i
].state
!= config
[i
].DECON_WIN_STATE_DISABLED
) {
3380 /* multiple dma mapping */
3381 for (size_t j
= (i
+1); j
< MAX_DECON_WIN
; j
++) {
3382 if ((config
[i
].state
== config
[i
].DECON_WIN_STATE_BUFFER
) &&
3383 (config
[j
].state
== config
[j
].DECON_WIN_STATE_BUFFER
)) {
3384 if (config
[i
].idma_type
== config
[j
].idma_type
) {
3385 ALOGE("WIN_CONFIG error: duplicated dma(%d) between win%d, win%d",
3386 config
[i
].idma_type
, i
, j
);
3387 config
[j
].state
= config
[j
].DECON_WIN_STATE_DISABLED
;
3388 flagValidConfig
= false;
3392 if ((config
[i
].src
.x
< 0) || (config
[i
].src
.y
< 0)||
3393 (config
[i
].dst
.x
< 0) || (config
[i
].dst
.y
< 0)||
3394 (config
[i
].dst
.x
+ config
[i
].dst
.w
> (uint32_t)mXres
) ||
3395 (config
[i
].dst
.y
+ config
[i
].dst
.h
> (uint32_t)mYres
)) {
3396 ALOGE("WIN_CONFIG error: invalid pos or size win%d", i
);
3397 config
[i
].state
= config
[i
].DECON_WIN_STATE_DISABLED
;
3398 flagValidConfig
= false;
3401 if (i
>= NUM_HW_WINDOWS
) {
3402 ALOGE("WIN_CONFIG error: invalid window number win%d", i
);
3403 config
[i
].state
= config
[i
].DECON_WIN_STATE_DISABLED
;
3404 flagValidConfig
= false;
3409 if (flagValidConfig
)
3415 int ExynosDisplay::setPowerMode(int mode
)
3417 #if defined(S3CFB_POWER_MODE)
3418 return ioctl(this->mDisplayFd
, S3CFB_POWER_MODE
, &mode
);
3420 return ioctl(this->mDisplayFd
, FBIOBLANK
, (mode
== HWC_POWER_MODE_OFF
? FB_BLANK_POWERDOWN
: FB_BLANK_UNBLANK
));