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)
459 uint32_t rectCount
= 0;
460 for (size_t i
= 0; i
< contents
->numHwLayers
; i
++) {
461 hwc_layer_1_t
&layer
= contents
->hwLayers
[i
];
463 private_handle_t
*handle
= private_handle_t::dynamicCast(layer
.handle
);
464 if (handle
->format
== HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_PRIV
465 && rectCount
< mOriginFrect
.size())
466 layer
.sourceCropf
= mOriginFrect
[rectCount
++];
469 mOriginFrect
.clear();
470 mBackUpFrect
.clear();
475 void ExynosDisplay::dupFence(int fence
, hwc_display_contents_1_t
*contents
)
477 if (contents
== NULL
)
480 for (size_t i
= 0; i
< contents
->numHwLayers
; i
++) {
481 hwc_layer_1_t
&layer
= contents
->hwLayers
[i
];
482 private_handle_t
*handle
= NULL
;
483 if (layer
.handle
!= NULL
)
484 handle
= private_handle_t::dynamicCast(layer
.handle
);
486 /* If Fb is not needed and this is a HWC buffer (function reverse engineered from S7 libexynosdisplay.so) */
487 if(!mFbNeeded
&& layer
.compositionType
== HWC_FRAMEBUFFER_TARGET
) {
488 /* Close the acquire fence Fd if it is valid */
489 if(layer
.acquireFenceFd
>= 0) {
490 close(layer
.acquireFenceFd
);
491 layer
.acquireFenceFd
= -1;
495 if ((mVirtualOverlayFlag
== true) && (layer
.compositionType
== HWC_OVERLAY
) &&
496 ((handle
!= NULL
) && (getDrmMode(handle
->flags
) == NO_DRM
)) &&
497 (mFirstFb
<= i
) && (i
<= mLastFb
))
500 if (!(layer
.flags
& HWC_SKIP_RENDERING
) && ((layer
.compositionType
== HWC_OVERLAY
) ||
501 ((mFbNeeded
== true || this->mVirtualOverlayFlag
) && layer
.compositionType
== HWC_FRAMEBUFFER_TARGET
))) {
502 int dup_fd
= dup(fence
);
503 DISPLAY_LOGD(eDebugFence
, "%d layer[type: %d, dst: %d, %d, %d, %d] fence is duplicated(%d)",
504 i
, layer
.compositionType
,
505 layer
.displayFrame
.left
, layer
.displayFrame
.top
,
506 layer
.displayFrame
.right
, layer
.displayFrame
.bottom
,
509 DISPLAY_LOGW("release fence dup failed: %s", strerror(errno
));
510 if (mLayerInfos
[i
]->mInternalMPP
!= NULL
) {
511 ExynosMPPModule
*exynosMPP
= mLayerInfos
[i
]->mInternalMPP
;
512 if (mLayerInfos
[i
]->mInternalMPP
->mDstBufFence
[0] >= 0)
513 close(mLayerInfos
[i
]->mInternalMPP
->mDstBufFence
[0]);
514 exynosMPP
->mDstBufFence
[0] = dup(fence
);
516 if (mLayerInfos
[i
]->mExternalMPP
!= NULL
) {
517 ExynosMPPModule
*exysnosMPP
= mLayerInfos
[i
]->mExternalMPP
;
518 if (exysnosMPP
->mDstBufFence
[exysnosMPP
->mCurrentBuf
] >= 0) {
519 close (exysnosMPP
->mDstBufFence
[exysnosMPP
->mCurrentBuf
]);
520 exysnosMPP
->mDstBufFence
[exysnosMPP
->mCurrentBuf
] = -1;
522 exysnosMPP
->mDstBufFence
[exysnosMPP
->mCurrentBuf
] = dup_fd
;
523 exysnosMPP
->mCurrentBuf
= (exysnosMPP
->mCurrentBuf
+ 1) % exysnosMPP
->mNumAvailableDstBuffers
;
525 if (this->mVirtualOverlayFlag
&& (layer
.compositionType
== HWC_FRAMEBUFFER_TARGET
)) {
526 if (layer
.releaseFenceFd
>= 0)
527 close(layer
.releaseFenceFd
);
529 layer
.releaseFenceFd
= dup_fd
;
534 #if defined(USES_DUAL_DISPLAY)
535 if (mType
== EXYNOS_SECONDARY_DISPLAY
)
536 contents
->retireFenceFd
= dup(fence
);
538 contents
->retireFenceFd
= fence
;
540 contents
->retireFenceFd
= fence
;
544 void ExynosDisplay::dump(android::String8
& result
)
547 " type | handle | color | blend | pa | format | position | size | intMPP | extMPP \n"
548 "----------+--------------|----------+-------+----+---------------+---------------+----------------------------------\n");
549 // 8_______ | 12__________ | 8_______ | 5____ | 2_ | 13___________ | [5____,5____] | [5____,5____] | [2_,2_] | [2_,2_]\n"
551 for (size_t i
= 0; i
< NUM_HW_WINDOWS
; i
++) {
552 struct decon_win_config
&config
= mLastConfigData
.config
[i
];
553 if ((config
.state
== config
.DECON_WIN_STATE_DISABLED
) &&
554 (mLastMPPMap
[i
].internal_mpp
.type
== -1) &&
555 (mLastMPPMap
[i
].external_mpp
.type
== -1)){
556 result
.appendFormat(" %8s | %12s | %8s | %5s | %2s | %13s | %13s | %13s",
557 "OVERLAY", "-", "-", "-", "-", "-", "-", "-");
560 if (config
.state
== config
.DECON_WIN_STATE_COLOR
)
561 result
.appendFormat(" %8s | %12s | %8x | %5s | %2s | %13s", "COLOR",
562 "-", config
.color
, "-", "-", "-");
564 result
.appendFormat(" %8s | %12" PRIxPTR
" | %8s | %5x | %2x | %13s",
565 mLastFbWindow
== i
? "FB" : "OVERLAY",
566 intptr_t(mLastHandles
[i
]),
567 "-", config
.blending
, config
.plane_alpha
, deconFormat2str(config
.format
));
569 result
.appendFormat(" | [%5d,%5d] | [%5u,%5u]", config
.dst
.x
, config
.dst
.y
,
570 config
.dst
.w
, config
.dst
.h
);
572 if (mLastMPPMap
[i
].internal_mpp
.type
== -1) {
573 result
.appendFormat(" | [%2s,%2s]", "-", "-");
575 result
.appendFormat(" | [%2d,%2d]", mLastMPPMap
[i
].internal_mpp
.type
, mLastMPPMap
[i
].internal_mpp
.index
);
578 if (mLastMPPMap
[i
].external_mpp
.type
== -1) {
579 result
.appendFormat(" | [%2s,%2s]", "-", "-");
581 result
.appendFormat(" | [%2d,%2d]", mLastMPPMap
[i
].external_mpp
.type
, mLastMPPMap
[i
].external_mpp
.index
);
587 void ExynosDisplay::freeMPP()
591 void ExynosDisplay::doPreProcessing(hwc_display_contents_1_t
* contents
)
593 mPreProcessedInfo
.mHasDrmSurface
= false;
594 mForceOverlayLayerIndex
= -1;
595 this->mHasDrmSurface
= false;
597 mLayersNeedScaling
= false;
599 for (size_t i
= 0; i
< contents
->numHwLayers
; i
++) {
600 hwc_layer_1_t
&layer
= contents
->hwLayers
[i
];
602 private_handle_t
*h
= private_handle_t::dynamicCast(layer
.handle
);
603 if (h
->flags
& GRALLOC_USAGE_PROTECTED
) {
604 mPreProcessedInfo
.mHasDrmSurface
= true;
605 this->mHasDrmSurface
= true;
606 mForceOverlayLayerIndex
= i
;
608 if (!isFormatRgb(h
->format
)) {
612 mLayersNeedScaling
= true;
617 void ExynosDisplay::allocateLayerInfos(hwc_display_contents_1_t
* contents
)
619 if (contents
== NULL
)
622 if (!mLayerInfos
.isEmpty()) {
623 for (size_t i
= 0; i
< mLayerInfos
.size(); i
++) {
624 delete mLayerInfos
[i
];
629 for (size_t i
= 0; i
< contents
->numHwLayers
; i
++) {
630 ExynosLayerInfo
*layerInfo
= new ExynosLayerInfo();
631 memset(layerInfo
, 0, sizeof(ExynosLayerInfo
));
632 layerInfo
->mDmaType
= -1;
633 mLayerInfos
.push(layerInfo
);
636 mForceFb
= mHwc
->force_gpu
;
638 doPreProcessing(contents
);
641 void ExynosDisplay::dumpLayerInfo(android::String8
& result
)
643 if (!mLayerInfos
.isEmpty()) {
645 " type | CheckOverlayFlag | CheckMPPFlag | Comp | mWinIndex | mDmaType | mIntMPP | mExtMPP \n"
646 "------------+------------------+--------------+------+-----------+----------+-----------+----------\n");
647 // 10________ | 8_______ | 8_______ | 3__ | 9________ | 8_______ | [3__, 2_] | [3__, 2_]\n"
648 for (size_t i
= 0; i
< mLayerInfos
.size(); i
++) {
649 unsigned int type
= mLayerInfos
[i
]->compositionType
;
650 static char const* compositionTypeName
[] = {
657 if (type
>= NELEM(compositionTypeName
))
658 type
= NELEM(compositionTypeName
) - 1;
660 " %10s | 0x%8x | 0x%8x | %1s | %9d | %8d",
661 compositionTypeName
[type
],
662 mLayerInfos
[i
]->mCheckOverlayFlag
, mLayerInfos
[i
]->mCheckMPPFlag
,
663 mLayerInfos
[i
]->mCompressed
? "Y" : "N",
664 mLayerInfos
[i
]->mWindowIndex
, mLayerInfos
[i
]->mDmaType
);
666 if (mLayerInfos
[i
]->mInternalMPP
== NULL
)
667 result
.appendFormat(" | [%3s, %2s]", "-", "-");
669 result
.appendFormat(" | [%3s, %2d]", mLayerInfos
[i
]->mInternalMPP
->getName().string(), mLayerInfos
[i
]->mInternalMPP
->mIndex
);
672 if (mLayerInfos
[i
]->mExternalMPP
== NULL
)
673 result
.appendFormat(" | [%3s, %2s]", "-", "-");
675 result
.appendFormat(" | [%3s, %2d]", mLayerInfos
[i
]->mExternalMPP
->getName().string(), mLayerInfos
[i
]->mExternalMPP
->mIndex
);
683 bool ExynosDisplay::handleTotalBandwidthOverload(hwc_display_contents_1_t
*contents
)
685 bool changed
= false;
687 if (mHwc
->totPixels
>= FIMD_TOTAL_BW_LIMIT
) {
690 for (int i
= mFirstFb
- 1; i
>= 0; i
--) {
691 if (mForceOverlayLayerIndex
== 0 && i
== 0)
693 hwc_layer_1_t
&layer
= contents
->hwLayers
[i
];
694 layer
.compositionType
= HWC_FRAMEBUFFER
;
695 mLayerInfos
[i
]->compositionType
= layer
.compositionType
;
696 mLayerInfos
[i
]->mCheckOverlayFlag
|= eInsufficientBandwidth
;
697 mLayerInfos
[i
]->mInternalMPP
= NULL
;
698 mLayerInfos
[i
]->mExternalMPP
= NULL
;
699 mFirstFb
= (size_t)i
;
700 mHwc
->totPixels
-= WIDTH(layer
.displayFrame
) * HEIGHT(layer
.displayFrame
);
701 if (mHwc
->totPixels
< FIMD_TOTAL_BW_LIMIT
)
704 if (mHwc
->totPixels
>= FIMD_TOTAL_BW_LIMIT
) {
705 for (size_t i
= mLastFb
+ 1; i
< contents
->numHwLayers
- 1; i
++) {
706 hwc_layer_1_t
&layer
= contents
->hwLayers
[i
];
707 layer
.compositionType
= HWC_FRAMEBUFFER
;
708 mLayerInfos
[i
]->compositionType
= layer
.compositionType
;
709 mLayerInfos
[i
]->mCheckOverlayFlag
|= eInsufficientBandwidth
;
710 mLayerInfos
[i
]->mInternalMPP
= NULL
;
711 mLayerInfos
[i
]->mExternalMPP
= NULL
;
713 mHwc
->totPixels
-= WIDTH(layer
.displayFrame
) * HEIGHT(layer
.displayFrame
);
714 if (mHwc
->totPixels
< FIMD_TOTAL_BW_LIMIT
)
719 for (size_t i
= 0; i
< contents
->numHwLayers
; i
++) {
720 hwc_layer_1_t
&layer
= contents
->hwLayers
[i
];
721 if (layer
.compositionType
== HWC_OVERLAY
&&
722 mForceOverlayLayerIndex
!= (int)i
) {
723 layer
.compositionType
= HWC_FRAMEBUFFER
;
724 mLastFb
= max(mLastFb
, i
);
725 mLayerInfos
[i
]->compositionType
= layer
.compositionType
;
726 mLayerInfos
[i
]->mCheckOverlayFlag
|= eInsufficientBandwidth
;
727 mLayerInfos
[i
]->mInternalMPP
= NULL
;
728 mLayerInfos
[i
]->mExternalMPP
= NULL
;
731 mHwc
->totPixels
+= mXres
* mYres
;
733 mHwc
->totPixels
-= WIDTH(layer
.displayFrame
) * HEIGHT(layer
.displayFrame
);
734 if (mHwc
->totPixels
< FIMD_TOTAL_BW_LIMIT
)
738 if (mForceOverlayLayerIndex
== 0)
749 int ExynosDisplay::clearDisplay()
751 struct decon_win_config_data win_data
;
752 memset(&win_data
, 0, sizeof(win_data
));
754 int ret
= ioctl(this->mDisplayFd
, S3CFB_WIN_CONFIG
, &win_data
);
755 LOG_ALWAYS_FATAL_IF(ret
< 0,
756 "%s ioctl S3CFB_WIN_CONFIG failed to clear screen: %s",
757 mDisplayName
.string(), strerror(errno
));
758 // the causes of an empty config failing are all unrecoverable
760 return win_data
.fence
;
763 int ExynosDisplay::getCompModeSwitch()
765 unsigned int updateFps
= 0;
766 unsigned int lcd_size
= this->mXres
* this->mYres
;
767 uint64_t TimeStampDiff
;
770 if (!mHwc
->hwc_ctrl
.dynamic_recomp_mode
) {
771 mHwc
->LastModeSwitchTimeStamp
= 0;
772 mHwc
->CompModeSwitch
= NO_MODE_SWITCH
;
776 /* initialize the Timestamps */
777 if (!mHwc
->LastModeSwitchTimeStamp
) {
778 mHwc
->LastModeSwitchTimeStamp
= mHwc
->LastUpdateTimeStamp
;
779 mHwc
->CompModeSwitch
= NO_MODE_SWITCH
;
783 /* If video layer is there, skip the mode switch */
784 if (mYuvLayers
|| mLayersNeedScaling
) {
785 if (mHwc
->CompModeSwitch
!= HWC_2_GLES
) {
788 mHwc
->CompModeSwitch
= GLES_2_HWC
;
789 mHwc
->updateCallCnt
= 0;
790 mHwc
->LastModeSwitchTimeStamp
= mHwc
->LastUpdateTimeStamp
;
791 DISPLAY_LOGI("[DYNAMIC_RECOMP] GLES_2_HWC by video layer");
796 /* Mode Switch is not required if total pixels are not more than the threshold */
797 if ((uint32_t)mHwc
->incomingPixels
<= lcd_size
* HWC_FIMD_BW_TH
) {
798 if (mHwc
->CompModeSwitch
!= HWC_2_GLES
) {
801 mHwc
->CompModeSwitch
= GLES_2_HWC
;
802 mHwc
->updateCallCnt
= 0;
803 mHwc
->LastModeSwitchTimeStamp
= mHwc
->LastUpdateTimeStamp
;
804 DISPLAY_LOGI("[DYNAMIC_RECOMP] GLES_2_HWC by BW check");
810 * There will be at least one composition call per one minute (because of time update)
811 * To minimize the analysis overhead, just analyze it once in a second
813 TimeStampDiff
= systemTime(SYSTEM_TIME_MONOTONIC
) - mHwc
->LastModeSwitchTimeStamp
;
816 * previous CompModeSwitch was GLES_2_HWC: check fps every 250ms from LastModeSwitchTimeStamp
817 * previous CompModeSwitch was HWC_2_GLES: check immediately
819 if ((mHwc
->CompModeSwitch
!= HWC_2_GLES
) && (TimeStampDiff
< (VSYNC_INTERVAL
* 15))) {
822 mHwc
->LastModeSwitchTimeStamp
= mHwc
->LastUpdateTimeStamp
;
823 if ((mHwc
->update_event_cnt
!= 1) && // This is not called by hwc_update_stat_thread
824 (mHwc
->CompModeSwitch
== HWC_2_GLES
) && (mHwc
->updateCallCnt
== 1)) {
825 DISPLAY_LOGI("[DYNAMIC_RECOMP] first frame after HWC_2_GLES");
826 updateFps
= HWC_FPS_TH
;
828 Temp
= (VSYNC_INTERVAL
* 60) / TimeStampDiff
;
829 updateFps
= (int)(mHwc
->updateCallCnt
* Temp
+ 0.5);
831 mHwc
->updateCallCnt
= 0;
834 * If FPS is lower than HWC_FPS_TH, try to switch the mode to GLES
836 if (updateFps
< HWC_FPS_TH
) {
837 if (mHwc
->CompModeSwitch
!= HWC_2_GLES
) {
838 mHwc
->CompModeSwitch
= HWC_2_GLES
;
839 DISPLAY_LOGI("[DYNAMIC_RECOMP] HWC_2_GLES by low FPS(%d)", updateFps
);
845 if (mHwc
->CompModeSwitch
== HWC_2_GLES
) {
846 mHwc
->CompModeSwitch
= GLES_2_HWC
;
847 DISPLAY_LOGI("[DYNAMIC_RECOMP] GLES_2_HWC by high FPS(%d)", updateFps
);
857 int32_t ExynosDisplay::getDisplayAttributes(const uint32_t attribute
, uint32_t __unused config
)
860 case HWC_DISPLAY_VSYNC_PERIOD
:
861 return this->mVsyncPeriod
;
863 case HWC_DISPLAY_WIDTH
:
864 #if defined(USES_DUAL_DISPLAY)
865 if ((mType
== EXYNOS_PRIMARY_DISPLAY
) || (mType
== EXYNOS_SECONDARY_DISPLAY
))
866 return this->mXres
/2;
873 case HWC_DISPLAY_HEIGHT
:
876 case HWC_DISPLAY_DPI_X
:
879 case HWC_DISPLAY_DPI_Y
:
883 DISPLAY_LOGE("unknown display attribute %u", attribute
);
888 bool ExynosDisplay::isOverlaySupportedByIDMA(hwc_layer_1_t __unused
&layer
, size_t __unused index
)
890 if (isCompressed(layer
))
896 void ExynosDisplay::getIDMAMinSize(hwc_layer_1_t __unused
&layer
, int *w
, int *h
)
902 bool ExynosDisplay::isOverlaySupported(hwc_layer_1_t
&layer
, size_t index
, bool useVPPOverlay
,
903 ExynosMPPModule
** supportedInternalMPP
, ExynosMPPModule
** supportedExternalMPP
)
906 ExynosMPPModule
* transitionInternalMPP
= NULL
;
907 private_handle_t
*handle
= NULL
;
908 int handleFormat
= 0;
909 bool firstFrameFramebufferTarget
= false;
911 DISPLAY_LOGD(eDebugOverlaySupported
, "isOverlaySupported:: index(%d), useVPPOverlay(%d)", index
, useVPPOverlay
);
913 if (layer
.flags
& HWC_SKIP_LAYER
) {
914 mLayerInfos
[index
]->mCheckOverlayFlag
|= eSkipLayer
;
915 DISPLAY_LOGD(eDebugOverlaySupported
, "\tlayer %u: skipping", index
);
919 if (!layer
.planeAlpha
)
922 if (index
== 0 && layer
.planeAlpha
< 255) {
923 DISPLAY_LOGD(eDebugOverlaySupported
, "\tlayer %u: eUnsupportedPlaneAlpha", index
);
924 mLayerInfos
[index
]->mCheckOverlayFlag
|= eUnsupportedPlaneAlpha
;
929 handle
= private_handle_t::dynamicCast(layer
.handle
);
930 handleFormat
= handle
->format
;
933 if ((layer
.compositionType
!= HWC_FRAMEBUFFER_TARGET
) && !handle
) {
934 DISPLAY_LOGD(eDebugOverlaySupported
, "\tlayer %u: handle is NULL, type is %d", index
, layer
.compositionType
);
935 mLayerInfos
[index
]->mCheckOverlayFlag
|= eInvalidHandle
;
939 if (!handle
&& (layer
.compositionType
== HWC_FRAMEBUFFER_TARGET
)) {
940 firstFrameFramebufferTarget
= true;
941 handleFormat
= HAL_PIXEL_FORMAT_RGBA_8888
;
944 if (handle
&& (getDrmMode(handle
->flags
) == NO_DRM
) &&
945 (isFloat(layer
.sourceCropf
.left
) || isFloat(layer
.sourceCropf
.top
) ||
946 isFloat(layer
.sourceCropf
.right
- layer
.sourceCropf
.left
) ||
947 isFloat(layer
.sourceCropf
.bottom
- layer
.sourceCropf
.top
))) {
948 if (isSourceCropfSupported(layer
) == false)
952 if (!isBlendingSupported(layer
.blending
)) {
953 DISPLAY_LOGD(eDebugOverlaySupported
, "\tlayer %u: blending %d not supported", index
, layer
.blending
);
954 mLayerInfos
[index
]->mCheckOverlayFlag
|= eUnsupportedBlending
;
958 int32_t bpp
= formatToBpp(handleFormat
);
959 int32_t left
= max(layer
.displayFrame
.left
, 0);
960 int32_t right
= min(layer
.displayFrame
.right
, mXres
);
961 uint32_t visible_width
= 0;
964 ((layer
.displayFrame
.left
% 2 != 0) || (layer
.displayFrame
.right
% 2 != 0))) {
965 DISPLAY_LOGD(eDebugOverlaySupported
, "\tlayer %u: eNotAlignedDstPosition", index
);
966 mLayerInfos
[index
]->mCheckOverlayFlag
|= eNotAlignedDstPosition
;
970 visible_width
= (right
- left
) * bpp
/ 8;
971 if (visible_width
< BURSTLEN_BYTES
) {
972 #ifdef USE_DRM_BURST_LEN
973 if (handle
&& (getDrmMode(handle
->flags
) != NO_DRM
)) {
974 if (visible_width
< DRM_BURSTLEN_BYTES
) {
975 DISPLAY_LOGD(eDebugOverlaySupported
, "\tlayer %u: visible area is too narrow", index
);
976 mLayerInfos
[index
]->mCheckOverlayFlag
|= eUnsupportedDstWidth
;
981 DISPLAY_LOGD(eDebugOverlaySupported
, "\tlayer %u: visible area is too narrow", index
);
982 mLayerInfos
[index
]->mCheckOverlayFlag
|= eUnsupportedDstWidth
;
984 #ifdef USE_DRM_BURST_LEN
989 if (!isProcessingRequired(layer
) && !useVPPOverlay
)
992 hwc_layer_1_t extMPPOutLayer
= layer
;
993 int originalHandleFormt
= handleFormat
;
994 int dst_format
= handleFormat
;
995 bool isBothMPPUsed
= isBothMPPProcessingRequired(layer
, &extMPPOutLayer
);
996 DISPLAY_LOGD(eDebugOverlaySupported
, "isOverlaySupported:: index(%d), isBothMPPUsed(%d)", index
, isBothMPPUsed
);
999 if ((*supportedInternalMPP
!= NULL
) && (*supportedExternalMPP
!= NULL
))
1002 if ((*supportedInternalMPP
!= NULL
) || (*supportedExternalMPP
!= NULL
&& !useVPPOverlay
))
1006 if (*supportedExternalMPP
== NULL
&& isBothMPPUsed
)
1008 /* extMPPOutLayer is output of ExtMPP
1009 * The output of ExtMPP is the input of IntMPP
1011 if (!isFormatRgb(handleFormat
) &&
1012 (WIDTH(extMPPOutLayer
.displayFrame
) % mCheckIntMPP
->getCropWidthAlign(layer
) != 0 ||
1013 HEIGHT(extMPPOutLayer
.displayFrame
) % mCheckIntMPP
->getCropHeightAlign(layer
) != 0 ||
1014 !(mCheckIntMPP
->isFormatSupportedByMPP(handleFormat
)) ||
1015 !(mCheckIntMPP
->isCSCSupportedByMPP(handleFormat
, HAL_PIXEL_FORMAT_RGBX_8888
, 1))))
1016 dst_format
= mExternalMPPDstFormat
;
1018 /* extMPPOutLayer is output of ExtMPP */
1019 for (size_t i
= 0; i
< mExternalMPPs
.size(); i
++)
1021 ExynosMPPModule
* externalMPP
= mExternalMPPs
[i
];
1022 if (externalMPP
->mState
== MPP_STATE_FREE
) {
1023 ret
= externalMPP
->isProcessingSupported(extMPPOutLayer
, dst_format
);
1025 *supportedExternalMPP
= externalMPP
;
1028 mLayerInfos
[index
]->mCheckMPPFlag
|= -ret
;
1033 /* Can't find valid externalMPP */
1034 if (*supportedExternalMPP
== NULL
) {
1035 DISPLAY_LOGD(eDebugOverlaySupported
, "\tlayer %u: Can't find valid externalMPP", index
);
1036 mLayerInfos
[index
]->mCheckOverlayFlag
|= eInsufficientMPP
;
1040 if (*supportedInternalMPP
== NULL
) {
1041 for (size_t i
= 0; i
< mInternalMPPs
.size(); i
++)
1043 ExynosMPPModule
* internalMPP
= mInternalMPPs
[i
];
1044 hwc_layer_1_t extMPPTempOutLayer
= extMPPOutLayer
;
1045 if (isBothMPPUsed
) {
1046 if (internalMPP
->mType
== MPP_VPP_G
)
1048 /* extMPPOutLayer is output of ExtMPP
1049 * The output of ExtMPP is the input of IntMPP
1051 if (!isFormatRgb(handleFormat
) &&
1052 (WIDTH(extMPPTempOutLayer
.displayFrame
) % internalMPP
->getCropWidthAlign(layer
) != 0 ||
1053 HEIGHT(extMPPTempOutLayer
.displayFrame
) % internalMPP
->getCropHeightAlign(layer
) != 0 ||
1054 !(internalMPP
->isFormatSupportedByMPP(handleFormat
))))
1055 dst_format
= mExternalMPPDstFormat
;
1057 extMPPTempOutLayer
.sourceCropf
.left
= extMPPOutLayer
.displayFrame
.left
;
1058 extMPPTempOutLayer
.sourceCropf
.top
= extMPPOutLayer
.displayFrame
.top
;
1059 extMPPTempOutLayer
.sourceCropf
.right
= extMPPOutLayer
.displayFrame
.right
;
1060 extMPPTempOutLayer
.sourceCropf
.bottom
= extMPPOutLayer
.displayFrame
.bottom
;
1061 extMPPTempOutLayer
.displayFrame
.left
= layer
.displayFrame
.left
;
1062 extMPPTempOutLayer
.displayFrame
.top
= layer
.displayFrame
.top
;
1063 extMPPTempOutLayer
.displayFrame
.right
= layer
.displayFrame
.right
;
1064 extMPPTempOutLayer
.displayFrame
.bottom
= layer
.displayFrame
.bottom
;
1065 ((private_handle_t
*)extMPPTempOutLayer
.handle
)->format
= dst_format
;
1066 extMPPTempOutLayer
.transform
= 0;
1068 ExynosDisplay
*addedDisplay
= (mHwc
->hdmi_hpd
? (ExynosDisplay
*)mHwc
->externalDisplay
: (ExynosDisplay
*)mHwc
->virtualDisplay
);
1069 ExynosDisplay
*otherDisplay
= (mType
? (ExynosDisplay
*)mHwc
->primaryDisplay
: addedDisplay
);
1072 * If MPP was assigned to other Device in previous frame
1073 * then doesn't assign it untill it is cleared
1075 if ((internalMPP
->mState
== MPP_STATE_FREE
) &&
1076 (internalMPP
->mDisplay
== NULL
|| internalMPP
->mDisplay
== this)) {
1077 /* InternalMPP doesn't need to check dst_format. Set dst_format with source format */
1078 if (firstFrameFramebufferTarget
)
1081 ret
= internalMPP
->isProcessingSupported(extMPPTempOutLayer
, ((private_handle_t
*)extMPPTempOutLayer
.handle
)->format
);
1082 handle
->format
= originalHandleFormt
;
1085 *supportedInternalMPP
= internalMPP
;
1088 mLayerInfos
[index
]->mCheckMPPFlag
|= -ret
;
1090 } else if (internalMPP
->wasUsedByDisplay(otherDisplay
)) {
1091 DISPLAY_LOGD(eDebugOverlaySupported
, "\tlayer %u: internalMPP[%d, %d] was used by other device", index
, internalMPP
->mType
, internalMPP
->mIndex
);
1092 if (transitionInternalMPP
== NULL
)
1093 transitionInternalMPP
= internalMPP
;
1096 handle
->format
= originalHandleFormt
;
1100 if ((*supportedInternalMPP
== NULL
) && (useVPPOverlay
== true) && !isProcessingRequired(layer
)) {
1101 DISPLAY_LOGD(eDebugOverlaySupported
, "\tlayer %u: eInsufficientMPP", index
);
1102 mLayerInfos
[index
]->mCheckOverlayFlag
|= eInsufficientMPP
;
1103 if (transitionInternalMPP
!= NULL
) {
1104 DISPLAY_LOGD(eDebugOverlaySupported
, "\tlayer %u: internalMPP[%d, %d] transition is started", index
, transitionInternalMPP
->mType
, transitionInternalMPP
->mIndex
);
1105 transitionInternalMPP
->startTransition(this);
1110 /* Can't find valid internalMPP */
1111 if (isBothMPPProcessingRequired(layer
) && *supportedInternalMPP
== NULL
) {
1112 DISPLAY_LOGD(eDebugOverlaySupported
, "\tlayer %u: Can't find valid internalMPP", index
);
1113 if (transitionInternalMPP
!= NULL
) {
1114 DISPLAY_LOGD(eDebugOverlaySupported
, "\tlayer %u: internalMPP[%d, %d] transition is started", index
, transitionInternalMPP
->mType
, transitionInternalMPP
->mIndex
);
1115 transitionInternalMPP
->startTransition(this);
1117 mLayerInfos
[index
]->mCheckOverlayFlag
|= eInsufficientMPP
;
1121 if (*supportedExternalMPP
== NULL
) {
1122 for (size_t i
= 0; i
< mExternalMPPs
.size(); i
++)
1124 ExynosMPPModule
* externalMPP
= mExternalMPPs
[i
];
1125 int dst_format
= handleFormat
;
1126 if (!isFormatRgb(handleFormat
))
1127 dst_format
= mExternalMPPDstFormat
;
1129 if (externalMPP
->mState
== MPP_STATE_FREE
) {
1130 if (firstFrameFramebufferTarget
)
1133 ret
= externalMPP
->isProcessingSupported(layer
, dst_format
);
1135 *supportedExternalMPP
= externalMPP
;
1140 mLayerInfos
[index
]->mCheckMPPFlag
|= -ret
;
1146 if (*supportedExternalMPP
!= NULL
&& useVPPOverlay
== true && *supportedInternalMPP
== NULL
) {
1147 int originalHandleFormt
= handleFormat
;
1148 dst_format
= handleFormat
;
1149 if (!isFormatRgb(handleFormat
))
1150 dst_format
= mExternalMPPDstFormat
;
1151 for (size_t i
= 0; i
< mInternalMPPs
.size(); i
++)
1153 extMPPOutLayer
= layer
;
1154 /* extMPPOutLayer is output of ExtMPP
1155 * The output of ExtMPP is the input of IntMPP
1157 extMPPOutLayer
.sourceCropf
.left
= layer
.displayFrame
.left
;
1158 extMPPOutLayer
.sourceCropf
.top
= layer
.displayFrame
.top
;
1159 extMPPOutLayer
.sourceCropf
.right
= layer
.displayFrame
.right
;
1160 extMPPOutLayer
.sourceCropf
.bottom
= layer
.displayFrame
.bottom
;
1161 extMPPOutLayer
.transform
= 0;
1163 ((private_handle_t
*)extMPPOutLayer
.handle
)->format
= dst_format
;
1164 ExynosMPPModule
* internalMPP
= mInternalMPPs
[i
];
1167 * If MPP was assigned to other Device in previous frame
1168 * then doesn't assign it untill it is cleared
1170 if ((internalMPP
->mState
== MPP_STATE_FREE
) &&
1171 (internalMPP
->mDisplay
== NULL
|| internalMPP
->mDisplay
== this)) {
1172 if (firstFrameFramebufferTarget
)
1175 ret
= internalMPP
->isProcessingSupported(extMPPOutLayer
, ((private_handle_t
*)extMPPOutLayer
.handle
)->format
);
1176 handle
->format
= originalHandleFormt
;
1179 *supportedInternalMPP
= internalMPP
;
1182 mLayerInfos
[index
]->mCheckMPPFlag
|= -ret
;
1185 ExynosDisplay
*addedDisplay
= (mHwc
->hdmi_hpd
? (ExynosDisplay
*)mHwc
->externalDisplay
: (ExynosDisplay
*)mHwc
->virtualDisplay
);
1186 ExynosDisplay
*otherDisplay
= (mType
? (ExynosDisplay
*)mHwc
->primaryDisplay
: addedDisplay
);
1187 if (firstFrameFramebufferTarget
) {
1188 if ((internalMPP
->wasUsedByDisplay(otherDisplay
)) && (transitionInternalMPP
== NULL
))
1189 transitionInternalMPP
= internalMPP
;
1191 if ((internalMPP
->wasUsedByDisplay(otherDisplay
)) &&
1192 ((transitionInternalMPP
== NULL
) ||
1193 ((transitionInternalMPP
->isProcessingSupported(extMPPOutLayer
, ((private_handle_t
*)extMPPOutLayer
.handle
)->format
) < 0) &&
1194 (internalMPP
->isProcessingSupported(extMPPOutLayer
, ((private_handle_t
*)extMPPOutLayer
.handle
)->format
) > 0))))
1195 transitionInternalMPP
= internalMPP
;
1200 handle
->format
= originalHandleFormt
;
1204 /* Transit display for next frame */
1205 if ((*supportedInternalMPP
== NULL
) && (transitionInternalMPP
!= NULL
)) {
1206 DISPLAY_LOGD(eDebugOverlaySupported
, "\tlayer %u: internalMPP[%d, %d] transition is started", index
, transitionInternalMPP
->mType
, transitionInternalMPP
->mIndex
);
1207 transitionInternalMPP
->startTransition(this);
1210 /* Can't find valid MPP */
1211 DISPLAY_LOGD(eDebugOverlaySupported
, "\tlayer %u: can't find valid MPP", index
);
1212 mLayerInfos
[index
]->mCheckOverlayFlag
|= eInsufficientMPP
;
1217 void ExynosDisplay::configureHandle(private_handle_t
*handle
, size_t index
,
1218 hwc_layer_1_t
&layer
, int fence_fd
, decon_win_config
&cfg
)
1225 #ifdef HWC_SET_OPAQUE
1226 if ((layer
.flags
& HWC_SET_OPAQUE
) && handle
&& (handle
->format
== HAL_PIXEL_FORMAT_RGBA_8888
)
1227 && (layer
.compositionType
== HWC_OVERLAY
)) {
1228 handle
->format
= HAL_PIXEL_FORMAT_RGBX_8888
;
1232 hwc_frect_t
&sourceCrop
= layer
.sourceCropf
;
1233 hwc_rect_t
&displayFrame
= layer
.compositionType
== HWC_FRAMEBUFFER_TARGET
? mFbUpdateRegion
: layer
.displayFrame
;
1234 int32_t blending
= layer
.blending
;
1235 int32_t planeAlpha
= layer
.planeAlpha
;
1237 uint32_t w
= WIDTH(displayFrame
);
1238 uint32_t h
= HEIGHT(displayFrame
);
1239 uint8_t bpp
= formatToBpp(handle
->format
);
1240 uint32_t offset
= ((uint32_t)sourceCrop
.top
* handle
->stride
+ (uint32_t)sourceCrop
.left
) * bpp
/ 8;
1241 ExynosMPPModule
* internalMPP
= mLayerInfos
[index
]->mInternalMPP
;
1242 ExynosMPPModule
* externalMPP
= mLayerInfos
[index
]->mExternalMPP
;
1244 #ifdef USES_DECON_AFBC_DECODER
1245 cfg
.compression
= isCompressed(layer
);
1248 if (displayFrame
.left
< 0) {
1249 unsigned int crop
= -displayFrame
.left
;
1250 DISPLAY_LOGD(eDebugWinConfig
, "layer off left side of screen; cropping %u pixels from left edge",
1254 offset
+= crop
* bpp
/ 8;
1256 x
= displayFrame
.left
;
1259 if (displayFrame
.right
> this->mXres
) {
1260 unsigned int crop
= displayFrame
.right
- this->mXres
;
1261 DISPLAY_LOGD(eDebugWinConfig
, "layer off right side of screen; cropping %u pixels from right edge",
1266 if (displayFrame
.top
< 0) {
1267 unsigned int crop
= -displayFrame
.top
;
1268 DISPLAY_LOGD(eDebugWinConfig
, "layer off top side of screen; cropping %u pixels from top edge",
1272 offset
+= handle
->stride
* crop
* bpp
/ 8;
1274 y
= displayFrame
.top
;
1277 if (displayFrame
.bottom
> this->mYres
) {
1278 int crop
= displayFrame
.bottom
- this->mYres
;
1279 DISPLAY_LOGD(eDebugWinConfig
, "layer off bottom side of screen; cropping %u pixels from bottom edge",
1284 cfg
.fd_idma
[0] = handle
->fd
;
1285 cfg
.fd_idma
[1] = handle
->fd1
;
1286 cfg
.fd_idma
[2] = handle
->fd2
;
1287 if (mLayerInfos
[index
]->mDmaType
== -1) {
1288 cfg
.state
= cfg
.DECON_WIN_STATE_DISABLED
;
1290 cfg
.state
= cfg
.DECON_WIN_STATE_BUFFER
;
1291 cfg
.idma_type
= (decon_idma_type
)mLayerInfos
[index
]->mDmaType
;
1297 cfg
.dst
.f_w
= mXres
;
1298 cfg
.dst
.f_h
= mYres
;
1299 cfg
.format
= halFormatToS3CFormat(handle
->format
);
1301 cfg
.src
.f_w
= handle
->stride
;
1302 cfg
.src
.f_h
= handle
->vstride
;
1303 if (handle
->format
== HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_PRIV
) {
1304 if (handle
->fd2
>= 0) {
1305 void *metaData
= NULL
;
1306 int interlacedType
= -1;
1307 metaData
= mmap(0, 64, PROT_READ
|PROT_WRITE
, MAP_SHARED
, handle
->fd2
, 0);
1309 interlacedType
= *(int *)metaData
;
1311 interlacedType
= -1;
1313 if (interlacedType
== V4L2_FIELD_INTERLACED_TB
||
1314 interlacedType
== V4L2_FIELD_INTERLACED_BT
) {
1315 cfg
.src
.f_w
= handle
->stride
* 2;
1316 cfg
.src
.f_h
= handle
->vstride
/ 2;
1319 munmap(metaData
, 64);
1323 cfg
.src
.x
= (int)sourceCrop
.left
;
1324 cfg
.src
.y
= (int)sourceCrop
.top
;
1331 if (internalMPP
!= NULL
) {
1332 if (cfg
.src
.f_w
> (unsigned int)internalMPP
->getMaxWidth(layer
))
1333 cfg
.src
.f_w
= (unsigned int)internalMPP
->getMaxWidth(layer
);
1334 if (cfg
.src
.f_h
> (unsigned int)internalMPP
->getMaxHeight(layer
))
1335 cfg
.src
.f_h
= (unsigned int)internalMPP
->getMaxHeight(layer
);
1336 cfg
.src
.f_w
= ALIGN_DOWN((unsigned int)cfg
.src
.f_w
, internalMPP
->getSrcWidthAlign(layer
));
1337 cfg
.src
.f_h
= ALIGN_DOWN((unsigned int)cfg
.src
.f_h
, internalMPP
->getSrcHeightAlign(layer
));
1339 cfg
.src
.x
= ALIGN((unsigned int)sourceCrop
.left
, internalMPP
->getSrcXOffsetAlign(layer
));
1340 cfg
.src
.y
= ALIGN((unsigned int)sourceCrop
.top
, internalMPP
->getSrcYOffsetAlign(layer
));
1343 cfg
.src
.w
= WIDTH(sourceCrop
) - (cfg
.src
.x
- (uint32_t)sourceCrop
.left
);
1344 if (cfg
.src
.x
+ cfg
.src
.w
> cfg
.src
.f_w
)
1345 cfg
.src
.w
= cfg
.src
.f_w
- cfg
.src
.x
;
1346 cfg
.src
.h
= HEIGHT(sourceCrop
) - (cfg
.src
.y
- (uint32_t)sourceCrop
.top
);
1347 if (cfg
.src
.y
+ cfg
.src
.h
> cfg
.src
.f_h
)
1348 cfg
.src
.h
= cfg
.src
.f_h
- cfg
.src
.y
;
1350 if (internalMPP
!= NULL
) {
1351 if (cfg
.src
.w
> (unsigned int)internalMPP
->getMaxCropWidth(layer
))
1352 cfg
.src
.w
= (unsigned int)internalMPP
->getMaxCropWidth(layer
);
1353 if (cfg
.src
.h
> (unsigned int)internalMPP
->getMaxCropHeight(layer
))
1354 cfg
.src
.h
= (unsigned int)internalMPP
->getMaxCropHeight(layer
);
1355 cfg
.src
.w
= ALIGN_DOWN(cfg
.src
.w
, internalMPP
->getCropWidthAlign(layer
));
1356 cfg
.src
.h
= ALIGN_DOWN(cfg
.src
.h
, internalMPP
->getCropHeightAlign(layer
));
1359 if (isSrcCropFloat(layer
.sourceCropf
))
1361 if (internalMPP
!= NULL
) {
1362 exynos_mpp_img srcImg
;
1363 internalMPP
->adjustSourceImage(layer
, srcImg
);
1364 cfg
.src
.f_w
= srcImg
.fw
;
1365 cfg
.src
.f_h
= srcImg
.fh
;
1366 cfg
.src
.x
= srcImg
.x
;
1367 cfg
.src
.y
= srcImg
.y
;
1368 cfg
.src
.w
= srcImg
.w
;
1369 cfg
.src
.h
= srcImg
.h
;
1371 if (externalMPP
== NULL
)
1372 ALOGE("float sourceCrop should be handled by MPP");
1375 ALOGD("x = %7.1f, 0x%8x", sourceCrop
.left
, cfg
.src
.x
);
1376 ALOGD("y = %7.1f, 0x%8x", sourceCrop
.top
, cfg
.src
.y
);
1377 ALOGD("w = %7.1f, 0x%8x", sourceCrop
.right
- sourceCrop
.left
, cfg
.src
.w
);
1378 ALOGD("h = %7.1f, 0x%8x", sourceCrop
.bottom
- sourceCrop
.top
, cfg
.src
.h
);
1382 cfg
.blending
= halBlendingToS3CBlending(blending
);
1383 cfg
.fence_fd
= fence_fd
;
1384 cfg
.plane_alpha
= 255;
1385 if (planeAlpha
&& (planeAlpha
< 255)) {
1386 cfg
.plane_alpha
= planeAlpha
;
1388 if (mLayerInfos
[index
]->mInternalMPP
) {
1389 cfg
.vpp_parm
.rot
= (vpp_rotate
)halTransformToHWRot(layer
.transform
);
1390 cfg
.vpp_parm
.eq_mode
= isFullRangeColor(layer
) ? BT_601_WIDE
: BT_601_NARROW
;
1392 if ((!mLayerInfos
[index
]->mExternalMPP
&&
1393 (mHwc
->mS3DMode
== S3D_MODE_READY
|| mHwc
->mS3DMode
== S3D_MODE_RUNNING
) &&
1394 !isFormatRgb(handle
->format
)) &&
1395 mType
== EXYNOS_PRIMARY_DISPLAY
) {
1396 int S3DFormat
= getS3DFormat(mHwc
->mHdmiPreset
);
1397 if (S3DFormat
== S3D_SBS
)
1399 else if (S3DFormat
== S3D_TB
)
1403 /* transparent region coordinates is on source buffer */
1404 //getLayerRegion(layer, cfg.transparent_area, eTransparentRegion);
1405 cfg
.transparent_area
.x
+= cfg
.dst
.x
;
1406 cfg
.transparent_area
.y
+= cfg
.dst
.y
;
1408 /* opaque region coordinates is on screen */
1409 //getLayerRegion(layer, cfg.covered_opaque_area, eCoveredOpaqueRegion);
1411 if (isOpaque
&& (handle
->format
== HAL_PIXEL_FORMAT_RGBX_8888
)) {
1412 handle
->format
= HAL_PIXEL_FORMAT_RGBA_8888
;
1417 void ExynosDisplay::configureOverlay(hwc_layer_1_t
*layer
, size_t index
, decon_win_config
&cfg
)
1419 if (layer
->compositionType
== HWC_BACKGROUND
) {
1420 hwc_color_t color
= layer
->backgroundColor
;
1421 cfg
.state
= cfg
.DECON_WIN_STATE_COLOR
;
1422 cfg
.color
= (color
.r
<< 16) | (color
.g
<< 8) | color
.b
;
1425 cfg
.dst
.w
= this->mXres
;
1426 cfg
.dst
.h
= this->mYres
;
1429 private_handle_t
*handle
= private_handle_t::dynamicCast(layer
->handle
);
1430 hwc_frect_t originalCrop
= layer
->sourceCropf
;
1431 if (layer
->compositionType
== HWC_FRAMEBUFFER_TARGET
) {
1432 /* Adjust FbUpdateRegion */
1433 int minCropWidth
= 0;
1434 int minCropHeight
= 0;
1435 int cropWidthAlign
= 1;
1436 if (mLayerInfos
[index
]->mInternalMPP
!= NULL
) {
1437 minCropWidth
= mLayerInfos
[index
]->mInternalMPP
->getMinWidth(*layer
);
1438 minCropHeight
= mLayerInfos
[index
]->mInternalMPP
->getMinHeight(*layer
);
1439 cropWidthAlign
= mLayerInfos
[index
]->mInternalMPP
->getCropWidthAlign(*layer
);
1441 getIDMAMinSize(*layer
, &minCropWidth
, &minCropHeight
);
1443 #if defined(USES_DUAL_DISPLAY)
1444 int32_t minLeftPosition
= (mType
!= EXYNOS_SECONDARY_DISPLAY
)? 0:(mXres
/2);
1445 int32_t maxRightPosition
= (mType
== EXYNOS_PRIMARY_DISPLAY
)?(mXres
/2):mXres
;
1447 int32_t minLeftPosition
= 0;
1448 int32_t maxRightPosition
= mXres
;
1450 if (mFbUpdateRegion
.left
< minLeftPosition
) mFbUpdateRegion
.left
= minLeftPosition
;
1451 if (mFbUpdateRegion
.right
< minLeftPosition
) mFbUpdateRegion
.right
= minLeftPosition
;
1452 if (mFbUpdateRegion
.left
> maxRightPosition
) mFbUpdateRegion
.left
= maxRightPosition
;
1453 if (mFbUpdateRegion
.right
> maxRightPosition
) mFbUpdateRegion
.right
= maxRightPosition
;
1454 if (mFbUpdateRegion
.top
< 0) mFbUpdateRegion
.top
= 0;
1455 if (mFbUpdateRegion
.bottom
< 0) mFbUpdateRegion
.bottom
= 0;
1456 if (mFbUpdateRegion
.top
> mYres
) mFbUpdateRegion
.top
= mYres
;
1457 if (mFbUpdateRegion
.bottom
> mYres
) mFbUpdateRegion
.bottom
= mYres
;
1459 if ((WIDTH(mFbUpdateRegion
) % cropWidthAlign
) != 0) {
1460 mFbUpdateRegion
.left
= ALIGN_DOWN(mFbUpdateRegion
.left
, cropWidthAlign
);
1461 mFbUpdateRegion
.right
= ALIGN_UP(mFbUpdateRegion
.right
, cropWidthAlign
);
1463 if (WIDTH(mFbUpdateRegion
) < minCropWidth
) {
1464 #if defined(USES_DUAL_DISPLAY)
1465 if (mFbUpdateRegion
.left
+ minCropWidth
<= maxRightPosition
)
1466 mFbUpdateRegion
.right
= mFbUpdateRegion
.left
+ minCropWidth
;
1468 mFbUpdateRegion
.left
= mFbUpdateRegion
.right
- minCropWidth
;
1470 if (mFbUpdateRegion
.left
+ minCropWidth
<= mXres
)
1471 mFbUpdateRegion
.right
= mFbUpdateRegion
.left
+ minCropWidth
;
1473 mFbUpdateRegion
.left
= mFbUpdateRegion
.right
- minCropWidth
;
1476 if (HEIGHT(mFbUpdateRegion
) < minCropHeight
) {
1477 if (mFbUpdateRegion
.top
+ minCropHeight
<= mYres
)
1478 mFbUpdateRegion
.bottom
= mFbUpdateRegion
.top
+ minCropHeight
;
1480 mFbUpdateRegion
.top
= mFbUpdateRegion
.bottom
- minCropHeight
;
1483 if ((mFbUpdateRegion
.left
>= minLeftPosition
) && (mFbUpdateRegion
.top
>= 0) &&
1484 (mFbUpdateRegion
.right
<= maxRightPosition
) && (mFbUpdateRegion
.bottom
<= mYres
)) {
1485 #ifdef USES_DUAL_DISPLAY
1486 if (mType
== EXYNOS_SECONDARY_DISPLAY
) {
1487 layer
->sourceCropf
.left
= (double)mFbUpdateRegion
.left
- (mXres
/2);
1488 layer
->sourceCropf
.right
= (double)mFbUpdateRegion
.right
- (mXres
/2);
1490 layer
->sourceCropf
.left
= (double)mFbUpdateRegion
.left
;
1491 layer
->sourceCropf
.right
= (double)mFbUpdateRegion
.right
;
1494 layer
->sourceCropf
.left
= (double)mFbUpdateRegion
.left
;
1495 layer
->sourceCropf
.right
= (double)mFbUpdateRegion
.right
;
1497 layer
->sourceCropf
.top
= (double)mFbUpdateRegion
.top
;
1498 layer
->sourceCropf
.bottom
= (double)mFbUpdateRegion
.bottom
;
1500 mFbUpdateRegion
= layer
->displayFrame
;
1503 configureHandle(handle
, index
, *layer
, layer
->acquireFenceFd
, cfg
);
1504 layer
->sourceCropf
= originalCrop
;
1507 int ExynosDisplay::handleWindowUpdate(hwc_display_contents_1_t __unused
*contents
,
1508 struct decon_win_config __unused
*config
)
1511 int updatedWinCnt
= 0;
1512 int totalWinCnt
= 0;
1513 int bitsPerPixel
= 0;
1514 size_t winUpdateInfoIdx
;
1515 hwc_rect updateRect
= {this->mXres
, this->mYres
, 0, 0};
1516 hwc_rect currentRect
= {0, 0, 0, 0};
1517 bool burstLengthCheckDone
= false;
1518 int alignAdjustment
= 1;
1519 int intersectionWidth
= 0;
1525 #if defined(USES_DUAL_DISPLAY)
1526 return -eWindowUpdateDisabled
;
1530 char value
[PROPERTY_VALUE_MAX
];
1531 property_get("debug.hwc.winupdate", value
, "1");
1533 if (!(!strcmp(value
, "1") || !strcmp(value
, "true")))
1534 return -eWindowUpdateDisabled
;
1536 if (DECON_WIN_UPDATE_IDX
< 0)
1537 return -eWindowUpdateInvalidIndex
;
1538 winUpdateInfoIdx
= DECON_WIN_UPDATE_IDX
;
1540 if (contents
->flags
& HWC_GEOMETRY_CHANGED
)
1541 return -eWindowUpdateGeometryChanged
;
1543 if (mPanelType
== PANEL_DSC
) {
1544 xAlign
= this->mXres
/ mDSCHSliceNum
;
1545 wAlign
= this->mXres
/ mDSCHSliceNum
;
1546 yAlign
= mDSCYSliceSize
;
1547 hAlign
= mDSCYSliceSize
;
1549 xAlign
= WINUPDATE_X_ALIGNMENT
;
1550 wAlign
= WINUPDATE_W_ALIGNMENT
;
1555 for (size_t i
= 0; i
< contents
->numHwLayers
; i
++) {
1556 if (contents
->hwLayers
[i
].compositionType
== HWC_FRAMEBUFFER
)
1559 if (!mFbNeeded
&& contents
->hwLayers
[i
].compositionType
== HWC_FRAMEBUFFER_TARGET
)
1561 int32_t windowIndex
= mLayerInfos
[i
]->mWindowIndex
;
1562 if ((windowIndex
< 0) || (windowIndex
> MAX_DECON_WIN
))
1563 return -eWindowUpdateInvalidConfig
;
1565 if (config
[windowIndex
].state
!= config
[windowIndex
].DECON_WIN_STATE_DISABLED
) {
1568 if (winConfigChanged(&config
[windowIndex
], &this->mLastConfigData
.config
[windowIndex
])) {
1571 currentRect
.left
= config
[windowIndex
].dst
.x
;
1572 currentRect
.right
= config
[windowIndex
].dst
.x
+ config
[windowIndex
].dst
.w
;
1573 currentRect
.top
= config
[windowIndex
].dst
.y
;
1574 currentRect
.bottom
= config
[windowIndex
].dst
.y
+ config
[windowIndex
].dst
.h
;
1576 if (hwcHasApiVersion((hwc_composer_device_1_t
*)mHwc
, HWC_DEVICE_API_VERSION_1_5
))
1578 private_handle_t
*handle
= NULL
;
1579 hwc_rect damageRect
= {0, 0, 0, 0};
1580 hwc_layer_1_t
&layer
= contents
->hwLayers
[i
];
1582 handle
= private_handle_t::dynamicCast(layer
.handle
);
1583 unsigned int damageRegionMod
= getLayerRegion(layer
, damageRect
, eDamageRegion
);
1585 if (damageRegionMod
== eDamageRegionSkip
)
1588 if (handle
&& !isScaled(layer
) && !isRotated(layer
) && (damageRegionMod
== eDamageRegionPartial
)) {
1589 DISPLAY_LOGD(eDebugWindowUpdate
, "[WIN_UPDATE][surfaceDamage] layer w(%4d) h(%4d), dirty (%4d, %4d) - (%4d, %4d)",
1590 handle
->width
, handle
->height
, damageRect
.left
, damageRect
.top
, damageRect
.right
, damageRect
.bottom
);
1592 currentRect
.left
= config
[windowIndex
].dst
.x
- (int32_t)layer
.sourceCropf
.left
+ damageRect
.left
;
1593 currentRect
.right
= config
[windowIndex
].dst
.x
- (int32_t)layer
.sourceCropf
.left
+ damageRect
.right
;
1594 currentRect
.top
= config
[windowIndex
].dst
.y
- (int32_t)layer
.sourceCropf
.top
+ damageRect
.top
;
1595 currentRect
.bottom
= config
[windowIndex
].dst
.y
- (int32_t)layer
.sourceCropf
.top
+ damageRect
.bottom
;
1596 adjustRect(currentRect
, mXres
, mYres
);
1601 if ((currentRect
.left
> currentRect
.right
) || (currentRect
.top
> currentRect
.bottom
)) {
1602 DISPLAY_LOGD(eDebugWindowUpdate
, "[WIN_UPDATE] window(%d) layer(%d) invalid region (%4d, %4d) - (%4d, %4d)",
1603 i
, layerIdx
, currentRect
.left
, currentRect
.top
, currentRect
.right
, currentRect
.bottom
);
1604 return -eWindowUpdateInvalidRegion
;
1606 DISPLAY_LOGD(eDebugWindowUpdate
, "[WIN_UPDATE] Updated Window(%d) Layer(%d) (%4d, %4d) - (%4d, %4d)",
1607 windowIndex
, i
, currentRect
.left
, currentRect
.top
, currentRect
.right
, currentRect
.bottom
);
1608 updateRect
= expand(updateRect
, currentRect
);
1612 if (updatedWinCnt
== 0)
1613 return -eWindowUpdateNotUpdated
;
1615 /* Alignment check */
1616 for (size_t i
= 0; i
< contents
->numHwLayers
; i
++) {
1617 if (contents
->hwLayers
[i
].compositionType
== HWC_FRAMEBUFFER
)
1620 if (!mFbNeeded
&& contents
->hwLayers
[i
].compositionType
== HWC_FRAMEBUFFER_TARGET
)
1623 int32_t windowIndex
= mLayerInfos
[i
]->mWindowIndex
;
1624 currentRect
.left
= config
[windowIndex
].dst
.x
;
1625 currentRect
.right
= config
[windowIndex
].dst
.x
+ config
[windowIndex
].dst
.w
;
1626 currentRect
.top
= config
[windowIndex
].dst
.y
;
1627 currentRect
.bottom
= config
[windowIndex
].dst
.y
+ config
[windowIndex
].dst
.h
;
1629 if ((config
[windowIndex
].state
!= config
[windowIndex
].DECON_WIN_STATE_DISABLED
) &&
1630 intersect(currentRect
, updateRect
)) {
1631 private_handle_t
*handle
= NULL
;
1632 hwc_layer_1_t
&layer
= contents
->hwLayers
[i
];
1634 handle
= private_handle_t::dynamicCast(layer
.handle
);
1636 return -eWindowUpdateInvalidConfig
;
1638 int originalFormat
= handle
->format
;
1639 int originalTransform
= layer
.transform
;
1640 if (mLayerInfos
[i
]->mInternalMPP
!= NULL
) {
1641 /* VPP scaling case */
1642 if ((config
[windowIndex
].src
.w
!= config
[windowIndex
].dst
.w
) ||
1643 (config
[windowIndex
].src
.h
!= config
[windowIndex
].dst
.h
))
1644 return -eWindowUpdateUnsupportedUseCase
;
1646 handle
->format
= S3CFormatToHalFormat(config
[windowIndex
].format
);
1647 if (handle
->format
>= 0) {
1648 /* rotation was handled by externalMPP */
1649 if (mLayerInfos
[i
]->mExternalMPP
!= NULL
)
1650 layer
.transform
= 0;
1651 xAlign
= getLCM(xAlign
, mLayerInfos
[i
]->mInternalMPP
->getSrcXOffsetAlign(layer
));
1652 yAlign
= getLCM(yAlign
, mLayerInfos
[i
]->mInternalMPP
->getSrcYOffsetAlign(layer
));
1653 wAlign
= getLCM(wAlign
, mLayerInfos
[i
]->mInternalMPP
->getCropWidthAlign(layer
));
1654 hAlign
= getLCM(hAlign
, mLayerInfos
[i
]->mInternalMPP
->getCropHeightAlign(layer
));
1656 handle
->format
= originalFormat
;
1657 layer
.transform
= originalTransform
;
1658 return -eWindowUpdateInvalidConfig
;
1661 handle
->format
= originalFormat
;
1662 layer
.transform
= originalTransform
;
1666 updateRect
.left
= ALIGN_DOWN(updateRect
.left
, xAlign
);
1667 updateRect
.top
= ALIGN_DOWN(updateRect
.top
, yAlign
);
1669 if (HEIGHT(updateRect
) < WINUPDATE_MIN_HEIGHT
) {
1670 if (updateRect
.top
+ WINUPDATE_MIN_HEIGHT
<= mYres
)
1671 updateRect
.bottom
= updateRect
.top
+ WINUPDATE_MIN_HEIGHT
;
1673 updateRect
.top
= updateRect
.bottom
- WINUPDATE_MIN_HEIGHT
;
1676 if ((100 * (WIDTH(updateRect
) * HEIGHT(updateRect
)) / (this->mXres
* this->mYres
)) > WINUPDATE_THRESHOLD
)
1677 return -eWindowUpdateOverThreshold
;
1679 alignAdjustment
= getLCM(alignAdjustment
, xAlign
);
1680 alignAdjustment
= getLCM(alignAdjustment
, wAlign
);
1683 burstLengthCheckDone
= true;
1684 updateRect
.left
= ALIGN_DOWN(updateRect
.left
, xAlign
);
1685 if ((WIDTH(updateRect
) % wAlign
) != 0)
1686 updateRect
.right
= updateRect
.left
+ ALIGN_DOWN(WIDTH(updateRect
), wAlign
) + wAlign
;
1687 updateRect
.top
= ALIGN_DOWN(updateRect
.top
, yAlign
);
1688 if ((HEIGHT(updateRect
) % hAlign
) != 0)
1689 updateRect
.bottom
= updateRect
.top
+ ALIGN_DOWN(HEIGHT(updateRect
), hAlign
) + hAlign
;
1691 for (size_t i
= 0; i
< contents
->numHwLayers
; i
++) {
1692 if (contents
->hwLayers
[i
].compositionType
== HWC_FRAMEBUFFER
)
1694 if (!mFbNeeded
&& contents
->hwLayers
[i
].compositionType
== HWC_FRAMEBUFFER_TARGET
)
1696 int32_t windowIndex
= mLayerInfos
[i
]->mWindowIndex
;
1697 if (config
[windowIndex
].state
!= config
[windowIndex
].DECON_WIN_STATE_DISABLED
) {
1698 enum decon_pixel_format fmt
= config
[windowIndex
].format
;
1699 if (fmt
== DECON_PIXEL_FORMAT_RGBA_5551
|| fmt
== DECON_PIXEL_FORMAT_RGB_565
)
1701 else if (fmt
== DECON_PIXEL_FORMAT_NV12
|| fmt
== DECON_PIXEL_FORMAT_NV21
||
1702 fmt
== DECON_PIXEL_FORMAT_NV12M
|| fmt
== DECON_PIXEL_FORMAT_NV21M
)
1707 currentRect
.left
= config
[windowIndex
].dst
.x
;
1708 currentRect
.right
= config
[windowIndex
].dst
.x
+ config
[windowIndex
].dst
.w
;
1709 currentRect
.top
= config
[windowIndex
].dst
.y
;
1710 currentRect
.bottom
= config
[windowIndex
].dst
.y
+ config
[windowIndex
].dst
.h
;
1712 intersectionWidth
= WIDTH(intersection(currentRect
, updateRect
));
1714 DISPLAY_LOGD(eDebugWindowUpdate
, "[WIN_UPDATE] win[%d] left(%d) right(%d) intersection(%d)", windowIndex
, currentRect
.left
, currentRect
.right
, intersectionWidth
);
1716 if (intersectionWidth
!= 0 && (size_t)((intersectionWidth
* bitsPerPixel
) / 8) < BURSTLEN_BYTES
) {
1717 #ifdef USE_DRM_BURST_LEN
1718 if (mHasDrmSurface
) {
1719 if ((size_t)((intersectionWidth
* bitsPerPixel
) / 8) < DRM_BURSTLEN_BYTES
) {
1720 DISPLAY_LOGD(eDebugWindowUpdate
, "[WIN_UPDATE] win[%d] insufficient burst length (%d)*(%d) < %d", windowIndex
, intersectionWidth
, bitsPerPixel
, BURSTLEN_BYTES
);
1721 burstLengthCheckDone
= false;
1727 DISPLAY_LOGD(eDebugWindowUpdate
, "[WIN_UPDATE] win[%d] insufficient burst length (%d)*(%d) < %d", windowIndex
, intersectionWidth
, bitsPerPixel
, BURSTLEN_BYTES
);
1728 burstLengthCheckDone
= false;
1730 #ifdef USE_DRM_BURST_LEN
1737 if (burstLengthCheckDone
)
1739 DISPLAY_LOGD(eDebugWindowUpdate
, "[WIN_UPDATE] Adjusting update width. current left(%d) right(%d)", updateRect
.left
, updateRect
.right
);
1740 if (updateRect
.left
>= alignAdjustment
) {
1741 updateRect
.left
-= alignAdjustment
;
1742 } else if (updateRect
.right
+ alignAdjustment
<= this->mXres
) {
1743 updateRect
.right
+= alignAdjustment
;
1745 DISPLAY_LOGD(eDebugWindowUpdate
, "[WIN_UPDATE] Error during update width adjustment");
1746 return -eWindowUpdateAdjustmentFail
;
1750 config
[winUpdateInfoIdx
].state
= config
[winUpdateInfoIdx
].DECON_WIN_STATE_UPDATE
;
1751 config
[winUpdateInfoIdx
].dst
.x
= ALIGN_DOWN(updateRect
.left
, xAlign
);
1752 if ((WIDTH(updateRect
) % wAlign
) != 0)
1753 updateRect
.right
= updateRect
.left
+ ALIGN_DOWN(WIDTH(updateRect
), wAlign
) + wAlign
;
1754 config
[winUpdateInfoIdx
].dst
.w
= WIDTH(updateRect
);
1756 config
[winUpdateInfoIdx
].dst
.y
= ALIGN_DOWN(updateRect
.top
, yAlign
);
1757 if ((HEIGHT(updateRect
) % hAlign
) != 0)
1758 updateRect
.bottom
= updateRect
.top
+ ALIGN_DOWN(HEIGHT(updateRect
), hAlign
) + hAlign
;
1759 config
[winUpdateInfoIdx
].dst
.h
= HEIGHT(updateRect
);
1762 for (size_t i
= 0; i
< contents
->numHwLayers
; i
++) {
1763 if (contents
->hwLayers
[i
].compositionType
== HWC_FRAMEBUFFER
)
1766 if (!mFbNeeded
&& contents
->hwLayers
[i
].compositionType
== HWC_FRAMEBUFFER_TARGET
)
1769 int32_t windowIndex
= mLayerInfos
[i
]->mWindowIndex
;
1770 currentRect
.left
= config
[windowIndex
].dst
.x
;
1771 currentRect
.right
= config
[windowIndex
].dst
.x
+ config
[windowIndex
].dst
.w
;
1772 currentRect
.top
= config
[windowIndex
].dst
.y
;
1773 currentRect
.bottom
= config
[windowIndex
].dst
.y
+ config
[windowIndex
].dst
.h
;
1775 if ((config
[windowIndex
].state
!= config
[windowIndex
].DECON_WIN_STATE_DISABLED
) &&
1776 intersect(currentRect
, updateRect
)) {
1777 private_handle_t
*handle
= NULL
;
1778 hwc_rect intersect_rect
= intersection(currentRect
, updateRect
);
1779 hwc_layer_1_t
&layer
= contents
->hwLayers
[i
];
1781 handle
= private_handle_t::dynamicCast(layer
.handle
);
1783 return -eWindowUpdateInvalidConfig
;
1785 int originalFormat
= handle
->format
;
1786 int originalTransform
= layer
.transform
;
1787 if (mLayerInfos
[i
]->mInternalMPP
!= NULL
) {
1788 handle
->format
= S3CFormatToHalFormat(config
[windowIndex
].format
);
1789 /* rotation was handled by externalMPP */
1790 if (mLayerInfos
[i
]->mExternalMPP
!= NULL
)
1791 layer
.transform
= 0;
1792 if (((mLayerInfos
[i
]->mInternalMPP
->getSrcXOffsetAlign(layer
) % intersect_rect
.left
) != 0) ||
1793 ((mLayerInfos
[i
]->mInternalMPP
->getSrcYOffsetAlign(layer
) % intersect_rect
.top
) != 0) ||
1794 ((mLayerInfos
[i
]->mInternalMPP
->getCropWidthAlign(layer
) % WIDTH(intersect_rect
)) != 0) ||
1795 ((mLayerInfos
[i
]->mInternalMPP
->getCropHeightAlign(layer
) % HEIGHT(intersect_rect
)) != 0)) {
1796 handle
->format
= originalFormat
;
1797 layer
.transform
= originalTransform
;
1798 config
[winUpdateInfoIdx
].state
= config
[winUpdateInfoIdx
].DECON_WIN_STATE_DISABLED
;
1799 return -eWindowUpdateAdjustmentFail
;
1802 handle
->format
= originalFormat
;
1803 layer
.transform
= originalTransform
;
1807 DISPLAY_LOGD(eDebugWindowUpdate
, "[WIN_UPDATE] UpdateRegion cfg (%4d, %4d) w(%4d) h(%4d) updatedWindowCnt(%d)",
1808 config
[winUpdateInfoIdx
].dst
.x
, config
[winUpdateInfoIdx
].dst
.y
, config
[winUpdateInfoIdx
].dst
.w
, config
[winUpdateInfoIdx
].dst
.h
, updatedWinCnt
);
1810 /* Disable block mode if window update region is not full screen */
1811 if ((config
[winUpdateInfoIdx
].dst
.x
!= 0) || (config
[winUpdateInfoIdx
].dst
.y
!= 0) ||
1812 (config
[winUpdateInfoIdx
].dst
.w
!= (uint32_t)mXres
) || (config
[winUpdateInfoIdx
].dst
.h
!= (uint32_t)mXres
)) {
1813 for (size_t i
= 0; i
< NUM_HW_WINDOWS
; i
++) {
1814 memset(&config
[i
].transparent_area
, 0, sizeof(config
[i
].transparent_area
));
1815 #ifdef HWC_SET_OPAQUE
1816 memset(&config
[i
].covered_opaque_area
, 0, sizeof(config
[i
].covered_opaque_area
));
1824 void ExynosDisplay::getLayerRegion(hwc_layer_1_t
&layer __unused
, decon_win_rect
&rect_area
, uint32_t regionType
)
1826 hwc_rect_t
const *hwcRects
= NULL
;
1827 unsigned int numRects
= 0;
1828 switch (regionType
) {
1830 case eTransparentRegion
:
1831 hwcRects
= layer
.transparentRegion
.rects
;
1832 numRects
= layer
.transparentRegion
.numRects
;
1834 case eCoveredOpaqueRegion
:
1835 hwcRects
= layer
.coveredOpaqueRegion
.rects
;
1836 numRects
= layer
.coveredOpaqueRegion
.numRects
;
1840 ALOGE("%s:: Invalid regionType (%d)", __func__
, regionType
);
1844 rect_area
.x
= rect_area
.y
= rect_area
.w
= rect_area
.h
= 0;
1845 if (hwcRects
!= NULL
) {
1846 for (size_t j
= 0; j
< numRects
; j
++) {
1848 rect
.left
= hwcRects
[j
].left
;
1849 rect
.top
= hwcRects
[j
].top
;
1850 rect
.right
= hwcRects
[j
].right
;
1851 rect
.bottom
= hwcRects
[j
].bottom
;
1852 adjustRect(rect
, mXres
, mYres
);
1853 /* Find the largest rect */
1854 if ((rect_area
.w
* rect_area
.h
) <
1855 (uint32_t)(WIDTH(rect
) * HEIGHT(rect
))) {
1856 rect_area
.x
= rect
.left
;
1857 rect_area
.y
= rect
.top
;
1858 rect_area
.w
= WIDTH(rect
);
1859 rect_area
.h
= HEIGHT(rect
);
1865 unsigned int ExynosDisplay::getLayerRegion(hwc_layer_1_t
&layer
, hwc_rect
&rect_area
, uint32_t regionType
) {
1866 hwc_rect_t
const *hwcRects
= NULL
;
1867 unsigned int numRects
= 0;
1869 switch (regionType
) {
1871 hwcRects
= layer
.surfaceDamage
.rects
;
1872 numRects
= layer
.surfaceDamage
.numRects
;
1875 ALOGE("%s:: Invalid regionType (%d)", __func__
, regionType
);
1876 return eDamageRegionError
;
1879 if ((numRects
== 0) || (hwcRects
== NULL
))
1880 return eDamageRegionFull
;
1882 if ((numRects
== 1) && (hwcRects
[0].left
== 0) && (hwcRects
[0].top
== 0) &&
1883 (hwcRects
[0].right
== 0) && (hwcRects
[0].bottom
== 0))
1884 return eDamageRegionSkip
;
1886 rect_area
.left
= INT_MAX
;
1887 rect_area
.top
= INT_MAX
;
1888 rect_area
.right
= rect_area
.bottom
= 0;
1889 if (hwcRects
!= NULL
) {
1890 for (size_t j
= 0; j
< numRects
; j
++) {
1892 rect
.left
= hwcRects
[j
].left
;
1893 rect
.top
= hwcRects
[j
].top
;
1894 rect
.right
= hwcRects
[j
].right
;
1895 rect
.bottom
= hwcRects
[j
].bottom
;
1896 adjustRect(rect
, INT_MAX
, INT_MAX
);
1897 /* Get sums of rects */
1898 rect_area
= expand(rect_area
, rect
);
1902 return eDamageRegionPartial
;
1905 bool ExynosDisplay::getPreviousDRMDMA(int *dma
)
1909 for (size_t i
= 0; i
< NUM_HW_WINDOWS
; i
++) {
1910 if (mLastConfigData
.config
[i
].protection
== 1) {
1911 *dma
= (int)mLastConfigData
.config
[i
].idma_type
;
1918 int ExynosDisplay::winconfigIoctl(decon_win_config_data
*win_data
)
1921 return ioctl(this->mDisplayFd
, S3CFB_WIN_CONFIG
, win_data
);
1924 int ExynosDisplay::postFrame(hwc_display_contents_1_t
* contents
)
1928 if (mWinData
== NULL
) {
1929 DISPLAY_LOGE("mWinData is not valid");
1932 struct decon_win_config
*config
= mWinData
->config
;
1934 int tot_ovly_wins
= 0;
1935 uint32_t rectCount
= 0;
1938 memset(mLastHandles
, 0, sizeof(mLastHandles
));
1939 memset(mLastMPPMap
, 0, sizeof(mLastMPPMap
));
1940 memset(config
, 0, sizeof(mWinData
->config
));
1942 for (size_t i
= 0; i
< NUM_HW_WINDOWS
; i
++) {
1943 config
[i
].fence_fd
= -1;
1944 mLastMPPMap
[i
].internal_mpp
.type
= -1;
1945 mLastMPPMap
[i
].external_mpp
.type
= -1;
1947 for (size_t i
= 0; i
< contents
->numHwLayers
; i
++) {
1948 hwc_layer_1_t
&layer
= contents
->hwLayers
[i
];
1950 private_handle_t
*handle
= private_handle_t::dynamicCast(layer
.handle
);
1951 if (handle
->format
== HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_PRIV
1952 && rectCount
< mBackUpFrect
.size())
1953 layer
.sourceCropf
= mBackUpFrect
[rectCount
++];
1957 for (size_t i
= 0; i
< contents
->numHwLayers
; i
++) {
1958 hwc_layer_1_t
&layer
= contents
->hwLayers
[i
];
1959 int32_t window_index
= mLayerInfos
[i
]->mWindowIndex
;
1960 private_handle_t
*handle
= NULL
;
1962 handle
= private_handle_t::dynamicCast(layer
.handle
);
1964 if ((layer
.flags
& HWC_SKIP_RENDERING
) ||
1965 ((layer
.compositionType
== HWC_OVERLAY
) &&
1966 ((window_index
< 0) || (window_index
>= (int32_t)NUM_HW_WINDOWS
)))) {
1967 if (layer
.acquireFenceFd
>= 0)
1968 close(layer
.acquireFenceFd
);
1969 layer
.acquireFenceFd
= -1;
1970 layer
.releaseFenceFd
= -1;
1972 if ((window_index
< 0) || (window_index
>= (int32_t)NUM_HW_WINDOWS
)) {
1973 android::String8 result
;
1974 DISPLAY_LOGE("window of layer %d was not assigned (window_index: %d)", i
, window_index
);
1975 dumpContents(result
, contents
);
1977 dumpLayerInfo(result
);
1982 if ((mVirtualOverlayFlag
== true) && (layer
.compositionType
== HWC_OVERLAY
) &&
1983 handle
&& (getDrmMode(handle
->flags
) == NO_DRM
) &&
1984 (mFirstFb
<= i
) && (i
<= mLastFb
))
1987 if (((layer
.compositionType
== HWC_OVERLAY
) ||
1988 (mFbNeeded
== true && layer
.compositionType
== HWC_FRAMEBUFFER_TARGET
))) {
1989 mLastHandles
[window_index
] = layer
.handle
;
1991 if (handle
&& (getDrmMode(handle
->flags
) == SECURE_DRM
))
1992 config
[window_index
].protection
= 1;
1994 config
[window_index
].protection
= 0;
1996 if (mLayerInfos
[i
]->mInternalMPP
!= NULL
) {
1997 mLastMPPMap
[window_index
].internal_mpp
.type
= mLayerInfos
[i
]->mInternalMPP
->mType
;
1998 mLastMPPMap
[window_index
].internal_mpp
.index
= mLayerInfos
[i
]->mInternalMPP
->mIndex
;
2000 if (mLayerInfos
[i
]->mExternalMPP
!= NULL
) {
2001 mLastMPPMap
[window_index
].external_mpp
.type
= mLayerInfos
[i
]->mExternalMPP
->mType
;
2002 mLastMPPMap
[window_index
].external_mpp
.index
= mLayerInfos
[i
]->mExternalMPP
->mIndex
;
2003 if (postMPPM2M(layer
, config
, window_index
, i
) < 0)
2006 configureOverlay(&layer
, i
, config
[window_index
]);
2009 if (window_index
== 0 && config
[window_index
].blending
!= DECON_BLENDING_NONE
) {
2010 DISPLAY_LOGD(eDebugWinConfig
, "blending not supported on window 0; forcing BLENDING_NONE");
2011 config
[window_index
].blending
= DECON_BLENDING_NONE
;
2013 if ((window_index
< DECON_WIN_UPDATE_IDX
) &&
2014 (config
[window_index
].state
!= config
[window_index
].DECON_WIN_STATE_DISABLED
) &&
2015 (config
[window_index
].src
.w
== 0 || config
[window_index
].src
.h
== 0 ||
2016 config
[window_index
].dst
.w
== 0 || config
[window_index
].dst
.h
== 0)) {
2017 config
[window_index
].state
= config
[window_index
].DECON_WIN_STATE_DISABLED
;
2021 if (this->mVirtualOverlayFlag
) {
2022 handleStaticLayers(contents
, *mWinData
, tot_ovly_wins
);
2025 if ((ret
= handleWindowUpdate(contents
, config
)) < 0)
2026 DISPLAY_LOGD(eDebugWindowUpdate
, "[WIN_UPDATE] UpdateRegion is FullScreen, ret(%d)", ret
);
2028 #if defined(USES_DUAL_DISPLAY)
2029 if (mType
== EXYNOS_PRIMARY_DISPLAY
) {
2030 int8_t indexLastConfig
= 0;
2031 for (size_t i
= 0; i
< NUM_HW_WINDOWS
; i
++) {
2032 if (config
[i
].state
== config
[i
].DECON_WIN_STATE_DISABLED
) {
2033 indexLastConfig
= i
;
2037 if (mHwc
->secondaryDisplay
->mEnabled
) {
2038 for (size_t i
= 0; i
< NUM_HW_WINDOWS
; i
++) {
2039 struct decon_win_config
&secondary_config
= mHwc
->secondaryDisplay
->mLastConfigData
.config
[i
];
2041 if (indexLastConfig
== NUM_HW_WINDOWS
) {
2042 DISPLAY_LOGE("primaryDisplay last config index is not valid(primaryLastIndex: %d)",
2046 if (i
== (NUM_HW_WINDOWS
- 1))
2049 index
= indexLastConfig
+ i
;
2050 DISPLAY_LOGD(eDebugWinConfig
, "secondary_config window %u configuration:", i
);
2051 dumpConfig(secondary_config
);
2052 if (secondary_config
.state
!= secondary_config
.DECON_WIN_STATE_DISABLED
) {
2053 if (index
>= NUM_HW_WINDOWS
) {
2054 DISPLAY_LOGE("secondaryDisplay config index is not valid(primaryLastIndex: %d, index:%d",
2055 indexLastConfig
, index
);
2057 memcpy(&config
[index
],&secondary_config
, sizeof(struct decon_win_config
));
2058 mLastHandles
[index
] = mHwc
->secondaryDisplay
->mLastHandles
[i
];
2065 if (mType
!= EXYNOS_SECONDARY_DISPLAY
)
2068 for (size_t i
= 0; i
<= NUM_HW_WINDOWS
; i
++) {
2069 DISPLAY_LOGD(eDebugWinConfig
, "window %u configuration:", i
);
2070 dumpConfig(config
[i
]);
2073 if (checkConfigValidation(config
) < 0) {
2074 android::String8 result
;
2075 DISPLAY_LOGE("WIN_CONFIG is not valid");
2076 for (size_t i
= 0; i
<= MAX_DECON_WIN
; i
++) {
2077 result
.appendFormat("window %zu configuration:\n", i
);
2078 dumpConfig(config
[i
], result
);
2081 dumpContents(result
, contents
);
2083 dumpLayerInfo(result
);
2086 if (checkConfigChanged(*mWinData
, mLastConfigData
) == false) {
2089 ret
= winconfigIoctl(mWinData
);
2091 DISPLAY_LOGE("ioctl S3CFB_WIN_CONFIG failed: %s", strerror(errno
));
2093 ret
= mWinData
->fence
;
2094 memcpy(&(this->mLastConfigData
), mWinData
, sizeof(*mWinData
));
2099 * Acquire fence of all of OVERLAY layers(including layers for secondary LCD)
2100 * should be closed even if WIN_CONFIG is skipped
2102 for (size_t i
= 0; i
< NUM_HW_WINDOWS
; i
++) {
2103 if (config
[i
].fence_fd
!= -1)
2104 close(config
[i
].fence_fd
);
2106 #if defined(USES_DUAL_DISPLAY)
2108 memcpy(&(this->mLastConfigData
), mWinData
, sizeof(*mWinData
));
2111 if (contents
->numHwLayers
== 1) {
2112 hwc_layer_1_t
&layer
= contents
->hwLayers
[0];
2113 if (layer
.acquireFenceFd
>= 0)
2114 close(layer
.acquireFenceFd
);
2115 layer
.acquireFenceFd
= -1;
2116 layer
.releaseFenceFd
= -1;
2119 if (!this->mVirtualOverlayFlag
&& (ret
>= 0))
2120 this->mLastFbWindow
= mFbWindow
;
2125 void ExynosDisplay::skipStaticLayers(hwc_display_contents_1_t
* contents
)
2127 mVirtualOverlayFlag
= 0;
2128 int fbIndex
= contents
->numHwLayers
- 1;
2130 if (!mHwc
->hwc_ctrl
.skip_static_layer_mode
)
2133 if (mBypassSkipStaticLayer
)
2136 if (contents
->flags
& HWC_GEOMETRY_CHANGED
) {
2137 mSkipStaticInitFlag
= false;
2141 if (!mFbNeeded
|| ((mLastFb
- mFirstFb
+ 1) > NUM_VIRT_OVER
)) {
2142 mSkipStaticInitFlag
= false;
2146 if (mSkipStaticInitFlag
) {
2147 if (mNumStaticLayers
!= (mLastFb
- mFirstFb
+ 1)) {
2148 mSkipStaticInitFlag
= false;
2152 for (size_t i
= mFirstFb
; i
<= mLastFb
; i
++) {
2153 hwc_layer_1_t
&layer
= contents
->hwLayers
[i
];
2154 if (!layer
.handle
|| (layer
.flags
& HWC_SKIP_LAYER
) || (mLastLayerHandles
[i
- mFirstFb
] != layer
.handle
)) {
2155 mSkipStaticInitFlag
= false;
2160 if ((mLastFbWindow
>= NUM_HW_WINDOWS
) || (fbIndex
< 0)) {
2161 mSkipStaticInitFlag
= false;
2162 DISPLAY_LOGE("skipStaticLayers:: invalid mLastFbWindow(%d), fbIndex(%d)", mLastFbWindow
, fbIndex
);
2165 /* DMA mapping is changed */
2166 if (mLastConfigData
.config
[mLastFbWindow
].idma_type
!= mLayerInfos
[fbIndex
]->mDmaType
) {
2167 mSkipStaticInitFlag
= false;
2171 mVirtualOverlayFlag
= 1;
2172 for (size_t i
= 0; i
< contents
->numHwLayers
-1; i
++) {
2173 hwc_layer_1_t
&layer
= contents
->hwLayers
[i
];
2174 if (layer
.compositionType
== HWC_FRAMEBUFFER
) {
2175 layer
.compositionType
= HWC_OVERLAY
;
2176 mLayerInfos
[i
]->compositionType
= layer
.compositionType
;
2177 mLayerInfos
[i
]->mCheckOverlayFlag
|= eSkipStaticLayer
;
2180 mLastFbWindow
= mFbWindow
;
2184 mSkipStaticInitFlag
= true;
2185 for (size_t i
= 0; i
< NUM_VIRT_OVER
; i
++)
2186 mLastLayerHandles
[i
] = 0;
2188 for (size_t i
= mFirstFb
; i
<= mLastFb
; i
++) {
2189 hwc_layer_1_t
&layer
= contents
->hwLayers
[i
];
2190 mLastLayerHandles
[i
- mFirstFb
] = layer
.handle
;
2192 mNumStaticLayers
= (mLastFb
- mFirstFb
+ 1);
2197 void ExynosDisplay::dumpMPPs(android::String8
& result
)
2199 result
.appendFormat("displayType(%d)\n", mType
);
2200 result
.appendFormat("Internal MPPs number: %zu\n", mInternalMPPs
.size());
2202 " mType | mIndex | mState \n"
2203 "-------+--------+-----------\n");
2204 // 5____ | 6_____ | 9________ \n
2206 for (size_t i
= 0; i
< mInternalMPPs
.size(); i
++) {
2207 ExynosMPPModule
* internalMPP
= mInternalMPPs
[i
];
2208 result
.appendFormat(" %5d | %6d | %9d \n",
2209 internalMPP
->mType
, internalMPP
->mIndex
, internalMPP
->mState
);
2212 result
.append("\n");
2213 result
.appendFormat("External MPPs number: %zu\n", mExternalMPPs
.size());
2215 " mType | mIndex | mState \n"
2216 "-------+--------+-----------\n");
2217 // 5____ | 6_____ | 9________ \n
2219 for (size_t i
= 0; i
< mExternalMPPs
.size(); i
++) {
2220 ExynosMPPModule
* internalMPP
= mExternalMPPs
[i
];
2221 result
.appendFormat(" %5d | %6d | %9d \n",
2222 internalMPP
->mType
, internalMPP
->mIndex
, internalMPP
->mState
);
2226 void ExynosDisplay::preAssignFbTarget(hwc_display_contents_1_t
*contents
, bool assign
)
2228 ExynosMPPModule
* supportedInternalMPP
= NULL
;
2229 ExynosMPPModule
* supportedExternalMPP
= NULL
;
2231 int fbIndex
= contents
->numHwLayers
- 1;
2232 hwc_layer_1_t
&layer
= contents
->hwLayers
[fbIndex
];
2233 mFbPreAssigned
= false;
2238 if (layer
.compositionType
!= HWC_FRAMEBUFFER_TARGET
) {
2239 ALOGE("preAssignFbTarget: FRAMEBUFFER_TARGET is not set properly");
2243 bool ret
= isOverlaySupported(layer
, fbIndex
, true, &supportedInternalMPP
, &supportedExternalMPP
);
2244 if (ret
&& (supportedInternalMPP
!= NULL
) && (supportedExternalMPP
== NULL
)) {
2245 DISPLAY_LOGD(eDebugResourceAssigning
, "Preassigning FramebufferTarget with internalMPP(%d, %d)", supportedInternalMPP
->mType
, supportedInternalMPP
->mIndex
);
2246 supportedInternalMPP
->mState
= MPP_STATE_ASSIGNED
;
2247 mLayerInfos
[fbIndex
]->mInternalMPP
= supportedInternalMPP
;
2248 mLayerInfos
[fbIndex
]->mDmaType
= getDeconDMAType(mLayerInfos
[fbIndex
]->mInternalMPP
);
2249 for (size_t i
= 0; i
< mInternalMPPs
.size(); i
++) {
2250 if ((ExynosMPPModule
*)mInternalMPPs
[i
] == supportedInternalMPP
) {
2251 mInternalMPPs
.removeItemsAt(i
);
2254 mFbPreAssigned
= true;
2256 ALOGE("preAssignFbTarget: preassigning FB failed");
2261 void ExynosDisplay::determineYuvOverlay(hwc_display_contents_1_t
*contents
)
2264 bool useVPPOverlayFlag
= false, hasDrmLayer
= mHasDrmSurface
;
2265 uint32_t rectCount
= 0;
2266 int drmLayerIndex
= mForceOverlayLayerIndex
;
2268 mForceOverlayLayerIndex
= -1;
2269 mHasDrmSurface
= false;
2271 for (size_t j
= 0; j
< contents
->numHwLayers
; j
++) {
2272 i
= hasDrmLayer
? ((j
+ drmLayerIndex
) % contents
->numHwLayers
) : j
;
2274 ExynosMPPModule
* supportedInternalMPP
= NULL
;
2275 ExynosMPPModule
* supportedExternalMPP
= NULL
;
2276 hwc_layer_1_t
&layer
= contents
->hwLayers
[i
];
2277 useVPPOverlayFlag
= false;
2279 private_handle_t
*handle
= private_handle_t::dynamicCast(layer
.handle
);
2281 if (getDrmMode(handle
->flags
) != NO_DRM
) {
2282 useVPPOverlayFlag
= true;
2283 if (mHwc
->hdmi_hpd
&& (!mHwc
->video_playback_status
)) {
2284 layer
.flags
|= HWC_SKIP_RENDERING
;
2287 layer
.flags
&= ~HWC_SKIP_RENDERING
;
2290 /* check yuv surface */
2291 if (!isFormatRgb(handle
->format
)) {
2292 if (mForceFb
&& (getDrmMode(handle
->flags
) == NO_DRM
)) {
2293 layer
.compositionType
= HWC_FRAMEBUFFER
;
2294 mLayerInfos
[i
]->compositionType
= layer
.compositionType
;
2295 mLayerInfos
[i
]->mCheckOverlayFlag
|= eForceFbEnabled
;
2298 /* HACK: force integer source crop */
2299 layer
.sourceCropf
.top
= (int)layer
.sourceCropf
.top
;
2300 layer
.sourceCropf
.left
= (int)layer
.sourceCropf
.left
;
2301 layer
.sourceCropf
.bottom
= (int)(layer
.sourceCropf
.bottom
+ 0.9);
2302 layer
.sourceCropf
.right
= (int)(layer
.sourceCropf
.right
+ 0.9);
2304 /* support to process interlaced color format data */
2305 if (handle
->format
== HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_PRIV
) {
2306 void *metaData
= NULL
;
2307 int interlacedType
= -1;
2308 mOriginFrect
.push(layer
.sourceCropf
);
2310 if (handle
->fd2
>= 0) {
2311 metaData
= mmap(0, 64, PROT_READ
|PROT_WRITE
, MAP_SHARED
, handle
->fd2
, 0);
2313 interlacedType
= *(int *)metaData
;
2315 interlacedType
= -1;
2318 if (interlacedType
== V4L2_FIELD_INTERLACED_BT
) {
2319 if ((int)layer
.sourceCropf
.left
< (int)(handle
->stride
)) {
2320 layer
.sourceCropf
.left
= (int)layer
.sourceCropf
.left
+ handle
->stride
;
2321 layer
.sourceCropf
.right
= (int)layer
.sourceCropf
.right
+ handle
->stride
;
2324 if (interlacedType
== V4L2_FIELD_INTERLACED_TB
|| interlacedType
== V4L2_FIELD_INTERLACED_BT
) {
2325 layer
.sourceCropf
.top
= (int)(layer
.sourceCropf
.top
)/2;
2326 layer
.sourceCropf
.bottom
= (int)(layer
.sourceCropf
.bottom
)/2;
2328 mBackUpFrect
.push(layer
.sourceCropf
);
2331 munmap(metaData
, 64);
2334 if (isOverlaySupported(contents
->hwLayers
[i
], i
, useVPPOverlayFlag
, &supportedInternalMPP
, &supportedExternalMPP
)) {
2336 if (this->mHasDrmSurface
== false) {
2338 if (supportedExternalMPP
!= NULL
)
2339 supportedExternalMPP
->mState
= MPP_STATE_ASSIGNED
;
2340 if (supportedInternalMPP
!= NULL
)
2341 supportedInternalMPP
->mState
= MPP_STATE_ASSIGNED
;
2343 mForceOverlayLayerIndex
= i
;
2344 layer
.compositionType
= HWC_OVERLAY
;
2345 mLayerInfos
[i
]->mExternalMPP
= supportedExternalMPP
;
2346 mLayerInfos
[i
]->mInternalMPP
= supportedInternalMPP
;
2347 mLayerInfos
[i
]->compositionType
= layer
.compositionType
;
2349 if ((getDrmMode(handle
->flags
) != NO_DRM
) &&
2350 isBothMPPProcessingRequired(layer
) &&
2351 (supportedInternalMPP
!= NULL
)) {
2352 layer
.displayFrame
.right
= layer
.displayFrame
.left
+
2353 ALIGN_DOWN(WIDTH(layer
.displayFrame
), supportedInternalMPP
->getCropWidthAlign(layer
));
2354 layer
.displayFrame
.bottom
= layer
.displayFrame
.top
+
2355 ALIGN_DOWN(HEIGHT(layer
.displayFrame
), supportedInternalMPP
->getCropHeightAlign(layer
));
2358 if ((getDrmMode(handle
->flags
) != NO_DRM
) &&
2359 (supportedInternalMPP
!= NULL
)) {
2360 if (WIDTH(layer
.displayFrame
) < supportedInternalMPP
->getMinWidth(layer
)) {
2361 ALOGE("determineYuvOverlay layer %d displayFrame width %d is smaller than vpp minWidth %d",
2362 i
, WIDTH(layer
.displayFrame
), supportedInternalMPP
->getMinWidth(layer
));
2363 layer
.displayFrame
.right
= layer
.displayFrame
.left
+
2364 ALIGN_DOWN(WIDTH(layer
.displayFrame
), supportedInternalMPP
->getMinWidth(layer
));
2366 if (HEIGHT(layer
.displayFrame
) < supportedInternalMPP
->getMinHeight(layer
)) {
2367 ALOGE("determineYuvOverlay layer %d displayFrame height %d is smaller than vpp minHeight %d",
2368 i
, HEIGHT(layer
.displayFrame
), supportedInternalMPP
->getMinHeight(layer
));
2369 layer
.displayFrame
.bottom
= layer
.displayFrame
.top
+
2370 ALIGN_DOWN(HEIGHT(layer
.displayFrame
), supportedInternalMPP
->getMinHeight(layer
));
2375 if (getDrmMode(handle
->flags
) != NO_DRM
) {
2376 /* This layer should be overlay but HWC can't handle it */
2377 layer
.compositionType
= HWC_OVERLAY
;
2378 mLayerInfos
[i
]->compositionType
= layer
.compositionType
;
2379 layer
.flags
|= HWC_SKIP_RENDERING
;
2384 if (getDrmMode(handle
->flags
) != NO_DRM
) {
2385 this->mHasDrmSurface
= true;
2386 mForceOverlayLayerIndex
= i
;
2390 private_handle_t
*handle
= private_handle_t::dynamicCast(layer
.handle
);
2391 if (handle
->format
== HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_PRIV
2392 && rectCount
< mOriginFrect
.size())
2393 layer
.sourceCropf
= mOriginFrect
[rectCount
++];
2398 void ExynosDisplay::determineSupportedOverlays(hwc_display_contents_1_t
*contents
)
2400 bool videoLayer
= false;
2405 uint32_t rectCount
= 0;
2407 // find unsupported overlays
2408 for (size_t i
= 0; i
< contents
->numHwLayers
; i
++) {
2409 hwc_layer_1_t
&layer
= contents
->hwLayers
[i
];
2411 mLayerInfos
[i
]->mCompressed
= isCompressed(layer
);
2412 if (layer
.compositionType
== HWC_FRAMEBUFFER_TARGET
) {
2413 DISPLAY_LOGD(eDebugOverlaySupported
, "\tlayer %u: framebuffer target", i
);
2414 mLayerInfos
[i
]->compositionType
= layer
.compositionType
;
2418 if (layer
.compositionType
== HWC_BACKGROUND
&& !mForceFb
) {
2419 DISPLAY_LOGD(eDebugOverlaySupported
, "\tlayer %u: background supported", i
);
2420 dumpLayer(eDebugOverlaySupported
, &contents
->hwLayers
[i
]);
2421 mLayerInfos
[i
]->compositionType
= layer
.compositionType
;
2425 if (layer
.flags
& HWC_SKIP_RENDERING
) {
2426 layer
.compositionType
= HWC_OVERLAY
;
2427 mLayerInfos
[i
]->compositionType
= layer
.compositionType
;
2432 private_handle_t
*handle
= private_handle_t::dynamicCast(layer
.handle
);
2433 if (handle
->format
== HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_PRIV
2434 && rectCount
< mBackUpFrect
.size())
2435 layer
.sourceCropf
= mBackUpFrect
[rectCount
++];
2437 ExynosMPPModule
* supportedInternalMPP
= NULL
;
2438 ExynosMPPModule
* supportedExternalMPP
= NULL
;
2440 if ((int)get_yuv_planes(halFormatToV4L2Format(handle
->format
)) > 0) {
2442 if (!mHwc
->hdmi_hpd
&& mHwc
->mS3DMode
== S3D_MODE_READY
)
2443 mHwc
->mS3DMode
= S3D_MODE_RUNNING
;
2445 mHwc
->incomingPixels
+= WIDTH(layer
.displayFrame
) * HEIGHT(layer
.displayFrame
);
2446 DISPLAY_LOGD(eDebugOverlaySupported
, "\tlayer(%d), type=%d, flags=%08x, handle=%p, tr=%02x, blend=%04x, "
2447 "{%7.1f,%7.1f,%7.1f,%7.1f}, {%d,%d,%d,%d}", i
,
2448 layer
.compositionType
, layer
.flags
, layer
.handle
, layer
.transform
,
2450 layer
.sourceCropf
.left
,
2451 layer
.sourceCropf
.top
,
2452 layer
.sourceCropf
.right
,
2453 layer
.sourceCropf
.bottom
,
2454 layer
.displayFrame
.left
,
2455 layer
.displayFrame
.top
,
2456 layer
.displayFrame
.right
,
2457 layer
.displayFrame
.bottom
);
2458 /* Video layer's compositionType was set in determineYuvOverlay */
2459 if (!isFormatRgb(handle
->format
) && layer
.compositionType
== HWC_OVERLAY
)
2462 if(((getDrmMode(handle
->flags
) != NO_DRM
) ||
2463 (!mForceFb
&& (!mHwc
->hwc_ctrl
.dynamic_recomp_mode
|| mHwc
->CompModeSwitch
!= HWC_2_GLES
))) &&
2464 isOverlaySupported(contents
->hwLayers
[i
], i
, false, &supportedInternalMPP
, &supportedExternalMPP
)) {
2465 DISPLAY_LOGD(eDebugOverlaySupported
, "\tlayer %u: overlay supported", i
);
2466 if (supportedExternalMPP
!= NULL
) {
2467 supportedExternalMPP
->mState
= MPP_STATE_ASSIGNED
;
2468 mLayerInfos
[i
]->mExternalMPP
= supportedExternalMPP
;
2470 if (supportedInternalMPP
!= NULL
) {
2471 supportedInternalMPP
->mState
= MPP_STATE_ASSIGNED
;
2472 mLayerInfos
[i
]->mInternalMPP
= supportedInternalMPP
;
2475 layer
.compositionType
= HWC_OVERLAY
;
2476 mLayerInfos
[i
]->compositionType
= layer
.compositionType
;
2478 dumpLayer(eDebugOverlaySupported
, &contents
->hwLayers
[i
]);
2481 ExynosMPPModule
*dummyInternal
= NULL
;
2482 ExynosMPPModule
*dummyExternal
= NULL
;
2483 DISPLAY_LOGD(eDebugOverlaySupported
, "\tlayer %u: overlay is not supported, dynamic_recomp_mode(%d), CompModeSwitch(%d)", i
, mHwc
->hwc_ctrl
.dynamic_recomp_mode
, mHwc
->CompModeSwitch
);
2485 mLayerInfos
[i
]->mCheckOverlayFlag
|= eForceFbEnabled
;
2486 else if (mHwc
->hwc_ctrl
.dynamic_recomp_mode
&& mHwc
->CompModeSwitch
== HWC_2_GLES
)
2487 mLayerInfos
[i
]->mCheckOverlayFlag
|= eDynamicRecomposition
;
2488 else if (isOverlaySupported(contents
->hwLayers
[i
], i
, false, &dummyInternal
, &dummyExternal
))
2489 mLayerInfos
[i
]->mCheckOverlayFlag
|= eUnknown
;
2492 mLayerInfos
[i
]->mCheckOverlayFlag
|= eInvalidHandle
;
2500 layer
.compositionType
= HWC_FRAMEBUFFER
;
2501 mLayerInfos
[i
]->compositionType
= layer
.compositionType
;
2503 dumpLayer(eDebugOverlaySupported
, &contents
->hwLayers
[i
]);
2506 if (!mHwc
->hdmi_hpd
&& mHwc
->mS3DMode
== S3D_MODE_RUNNING
&& !videoLayer
)
2507 mHwc
->mS3DMode
= S3D_MODE_DISABLED
;
2508 hwc_rect_t base_rect
= {0, 0, 0, 0};
2509 hwc_rect_t intersect_rect
;
2510 for (size_t i
= 0; i
< contents
->numHwLayers
; i
++) {
2511 hwc_layer_1_t
&layer
= contents
->hwLayers
[i
];
2512 if (layer
.compositionType
== HWC_OVERLAY
) {
2514 base_rect
= layer
.displayFrame
;
2515 } else if (hasPlaneAlpha(layer
)) {
2516 //if alpha layer is not completely overlapped with base layer, bypass the alpha layer to GLES.
2517 intersect_rect
= intersection(base_rect
, layer
.displayFrame
);
2518 if (!rectEqual(intersect_rect
, layer
.displayFrame
)) {
2519 layer
.compositionType
= HWC_FRAMEBUFFER
;
2520 mLayerInfos
[i
]->compositionType
= layer
.compositionType
;
2521 mLayerInfos
[i
]->mCheckOverlayFlag
|= eUnsupportedBlending
;
2522 mFirstFb
= min(mFirstFb
, i
);
2523 mLastFb
= max(mLastFb
, i
);
2529 // if one of the bottom layer is HWC_FRAMEBUFFER type, no need to force the alpha layer to FRAMEBUFFER type.
2533 mFirstFb
= min(mFirstFb
, (size_t)NUM_HW_WINDOWS
-1);
2534 // can't composite overlays sandwiched between framebuffers
2536 private_handle_t
*handle
= NULL
;
2537 for (size_t i
= mFirstFb
; i
< mLastFb
; i
++) {
2538 if (contents
->hwLayers
[i
].flags
& HWC_SKIP_RENDERING
)
2541 hwc_layer_1_t
&layer
= contents
->hwLayers
[i
];
2544 handle
= private_handle_t::dynamicCast(layer
.handle
);
2545 if (handle
&& getDrmMode(handle
->flags
) != NO_DRM
) {
2546 layer
.hints
= HWC_HINT_CLEAR_FB
;
2548 contents
->hwLayers
[i
].compositionType
= HWC_FRAMEBUFFER
;
2549 mLayerInfos
[i
]->compositionType
= contents
->hwLayers
[i
].compositionType
;
2550 mLayerInfos
[i
]->mCheckOverlayFlag
|= eSandwitchedBetweenGLES
;
2551 if (mLayerInfos
[i
]->mExternalMPP
!= NULL
) {
2552 mLayerInfos
[i
]->mExternalMPP
->mState
= MPP_STATE_FREE
;
2553 mLayerInfos
[i
]->mExternalMPP
= NULL
;
2555 if (mLayerInfos
[i
]->mInternalMPP
!= NULL
) {
2556 mLayerInfos
[i
]->mInternalMPP
->mState
= MPP_STATE_FREE
;
2557 mLayerInfos
[i
]->mInternalMPP
= NULL
;
2564 void ExynosDisplay::determineBandwidthSupport(hwc_display_contents_1_t
*contents
)
2566 // Incrementally try to add our supported layers to hardware windows.
2567 // If adding a layer would violate a hardware constraint, force it
2568 // into the framebuffer and try again. (Revisiting the entire list is
2569 // necessary because adding a layer to the framebuffer can cause other
2570 // windows to retroactively violate constraints.)
2572 this->mBypassSkipStaticLayer
= false;
2573 unsigned int cannotComposeFlag
= 0;
2575 int fbIndex
= contents
->numHwLayers
- 1;
2577 // Initialize to inverse values so that
2578 // min(left, l) = l, min(top, t) = t
2579 // max(right, r) = r, max(bottom, b) = b
2580 // for all l, t, r, b
2581 mFbUpdateRegion
.left
= mXres
;
2582 mFbUpdateRegion
.top
= mYres
;
2583 mFbUpdateRegion
.right
= 0;
2584 mFbUpdateRegion
.bottom
= 0;
2587 uint32_t win_idx
= 0;
2588 size_t windows_left
;
2589 unsigned int directFbNum
= 0;
2590 int videoOverlays
= 0;
2591 mHwc
->totPixels
= 0;
2592 ExynosMPPModule
* supportedInternalMPP
= NULL
;
2593 ExynosMPPModule
* supportedExternalMPP
= NULL
;
2596 for (size_t i
= 0; i
< mInternalMPPs
.size(); i
++) {
2597 if (mInternalMPPs
[i
]->mState
!= MPP_STATE_TRANSITION
&&
2599 (mLayerInfos
[mForceOverlayLayerIndex
]->mInternalMPP
!= mInternalMPPs
[i
]))) {
2600 mInternalMPPs
[i
]->mState
= MPP_STATE_FREE
;
2604 for (size_t i
= 0; i
< mExternalMPPs
.size(); i
++) {
2605 if (mExternalMPPs
[i
]->mState
!= MPP_STATE_TRANSITION
&&
2607 (mLayerInfos
[mForceOverlayLayerIndex
]->mExternalMPP
!= mExternalMPPs
[i
]))) {
2608 mExternalMPPs
[i
]->mState
= MPP_STATE_FREE
;
2612 for (size_t i
= 0; i
< contents
->numHwLayers
; i
++) {
2613 if (!mHasDrmSurface
|| (int)i
!= mForceOverlayLayerIndex
) {
2614 mLayerInfos
[i
]->mInternalMPP
= NULL
;
2615 mLayerInfos
[i
]->mExternalMPP
= NULL
;
2622 if (mFbPreAssigned
) {
2623 DISPLAY_LOGD(eDebugResourceAssigning
, "fb has been pre-assigned already");
2624 windows_left
= min(mAllowedOverlays
, mHwc
->hwc_ctrl
.max_num_ovly
) - 1;
2625 } else if (mFbNeeded
&& (contents
->numHwLayers
- 1 > 0)) {
2626 hwc_layer_1_t
&layer
= contents
->hwLayers
[fbIndex
];
2627 if (mUseSecureDMA
&& (mLastFb
== (contents
->numHwLayers
- 2)) && isOverlaySupportedByIDMA(layer
, fbIndex
)) {
2628 /* FramebufferTarget is the top layer, Secure DMA is used */
2629 windows_left
= min(mAllowedOverlays
, mHwc
->hwc_ctrl
.max_num_ovly
);
2630 mLayerInfos
[contents
->numHwLayers
- 1]->mDmaType
= IDMA_SECURE
;
2631 } else if ((mInternalDMAs
.size() > 0) && isOverlaySupportedByIDMA(layer
, fbIndex
)) {
2632 /* Internal DMA is used */
2633 windows_left
= min(mAllowedOverlays
, mHwc
->hwc_ctrl
.max_num_ovly
) - 1;
2634 mLayerInfos
[contents
->numHwLayers
- 1]->mDmaType
= mInternalDMAs
[directFbNum
];
2635 win_idx
= (win_idx
== mFirstFb
) ? (win_idx
+ 1) : win_idx
;
2638 /* VPP should be used for DMA */
2639 windows_left
= min(mAllowedOverlays
, mHwc
->hwc_ctrl
.max_num_ovly
) - 1;
2640 ret
= isOverlaySupported(layer
, fbIndex
, true, &supportedInternalMPP
, &supportedExternalMPP
);
2641 if (ret
&& (supportedInternalMPP
!= NULL
)) {
2642 DISPLAY_LOGD(eDebugResourceAssigning
, "FramebufferTarget internalMPP(%d, %d)", supportedInternalMPP
->mType
, supportedInternalMPP
->mIndex
);
2643 supportedInternalMPP
->mState
= MPP_STATE_ASSIGNED
;
2644 mLayerInfos
[fbIndex
]->mInternalMPP
= supportedInternalMPP
;
2645 mLayerInfos
[fbIndex
]->mDmaType
= getDeconDMAType(mLayerInfos
[fbIndex
]->mInternalMPP
);
2646 #if defined(MAX_DECON_DMA_TYPE)
2647 if (mLayerInfos
[fbIndex
]->mDmaType
>= MAX_DECON_DMA_TYPE
) {
2649 if (mLayerInfos
[fbIndex
]->mDmaType
>= IDMA_MAX
) {
2651 ALOGE("getDeconDMAType with InternalMPP for FramebufferTarget failed (MPP type: %d, MPP index: %d)",
2652 mLayerInfos
[fbIndex
]->mInternalMPP
->mType
, mLayerInfos
[fbIndex
]->mInternalMPP
->mIndex
);
2653 mLayerInfos
[fbIndex
]->mDmaType
= 0;
2655 win_idx
= (win_idx
== mFirstFb
) ? (win_idx
+ 1) : win_idx
;
2657 ALOGE("VPP should be assigned to FramebufferTarget but it was failed ret(%d)", ret
);
2660 mHwc
->totPixels
+= mXres
* mYres
;
2662 windows_left
= min(mAllowedOverlays
, mHwc
->hwc_ctrl
.max_num_ovly
);
2665 DISPLAY_LOGD(eDebugResourceAssigning
, "determineBandwidthSupport:: retry(%d), mAllowedOverlays(%d), windows_left(%d), win_idx(%d)",
2666 retry
, mAllowedOverlays
, windows_left
, win_idx
);
2668 for (size_t i
= 0; i
< contents
->numHwLayers
; i
++) {
2669 hwc_layer_1_t
&layer
= contents
->hwLayers
[i
];
2670 bool isTopLayer
= (i
== contents
->numHwLayers
- 2) ? true:false;
2671 private_handle_t
*handle
= NULL
;
2673 if (layer
.flags
& HWC_SKIP_RENDERING
)
2676 if ((layer
.flags
& HWC_SKIP_LAYER
) ||
2677 (layer
.compositionType
== HWC_FRAMEBUFFER_TARGET
))
2680 if (!layer
.planeAlpha
)
2684 handle
= private_handle_t::dynamicCast(layer
.handle
);
2688 // we've already accounted for the framebuffer above
2689 if (layer
.compositionType
== HWC_FRAMEBUFFER
)
2692 // only layer 0 can be HWC_BACKGROUND, so we can
2693 // unconditionally allow it without extra checks
2694 if (layer
.compositionType
== HWC_BACKGROUND
) {
2699 cannotComposeFlag
= 0;
2700 bool can_compose
= windows_left
&& (win_idx
< NUM_HW_WINDOWS
);
2701 if (mUseSecureDMA
&& !isCompressed(layer
) && isTopLayer
)
2703 else if (windows_left
<= 0 || (win_idx
>= NUM_HW_WINDOWS
))
2704 cannotComposeFlag
|= eInsufficientWindow
;
2705 if (!isFormatRgb(handle
->format
) && videoOverlays
>= mHwc
->hwc_ctrl
.num_of_video_ovly
) {
2706 can_compose
= false;
2707 cannotComposeFlag
|= eInsufficientMPP
;
2710 /* mInternalMPP, mExternalMPP could be set by determineYuvOverlay */
2711 supportedInternalMPP
= mLayerInfos
[i
]->mInternalMPP
;
2712 supportedExternalMPP
= mLayerInfos
[i
]->mExternalMPP
;
2714 if (can_compose
&& !isProcessingRequired(layer
) && isOverlaySupportedByIDMA(layer
, i
) &&
2715 (directFbNum
< mInternalDMAs
.size() || (mUseSecureDMA
&& isTopLayer
))) {
2716 if (directFbNum
< mInternalDMAs
.size())
2718 DISPLAY_LOGD(eDebugResourceAssigning
, "layer(%d) is directFB", i
);
2719 } else if (can_compose
&& isOverlaySupported(layer
, i
,
2720 !isProcessingRequired(layer
) |
2721 (directFbNum
>= mInternalDMAs
.size() && !(mUseSecureDMA
&& isTopLayer
)),
2722 &supportedInternalMPP
, &supportedExternalMPP
)) {
2723 DISPLAY_LOGD(eDebugResourceAssigning
, "layer(%d) is OVERLAY ",i
);
2724 if (supportedInternalMPP
!= NULL
) {
2725 DISPLAY_LOGD(eDebugResourceAssigning
, "layer(%d) is OVERLAY internalMPP(%d, %d)", i
, supportedInternalMPP
->mType
, supportedInternalMPP
->mIndex
);
2726 supportedInternalMPP
->mState
= MPP_STATE_ASSIGNED
;
2727 mLayerInfos
[i
]->mInternalMPP
= supportedInternalMPP
;
2728 mLayerInfos
[i
]->mDmaType
= getDeconDMAType(mLayerInfos
[i
]->mInternalMPP
);
2730 if (supportedExternalMPP
!= NULL
) {
2731 DISPLAY_LOGD(eDebugResourceAssigning
, "layer(%d) is OVERLAY externalMPP(%d, %d)", i
, supportedExternalMPP
->mType
, supportedExternalMPP
->mIndex
);
2732 supportedExternalMPP
->mState
= MPP_STATE_ASSIGNED
;
2733 mLayerInfos
[i
]->mExternalMPP
= supportedExternalMPP
;
2734 if ((supportedInternalMPP
== NULL
) && isOverlaySupportedByIDMA(layer
, i
) &&
2735 ((directFbNum
< mInternalDMAs
.size()) || (mUseSecureDMA
&& isTopLayer
))) {
2736 if (directFbNum
< mInternalDMAs
.size()) {
2737 mLayerInfos
[i
]->mDmaType
= mInternalDMAs
[directFbNum
];
2740 mLayerInfos
[i
]->mDmaType
= IDMA_SECURE
;
2745 if (!isFormatRgb(handle
->format
))
2748 DISPLAY_LOGD(eDebugResourceAssigning
, "layer(%d) is changed to FRAMEBUFFER", i
);
2749 can_compose
= false;
2753 size_t changed_index
= i
;
2754 hwc_layer_1_t
*layer_for_gles
= &contents
->hwLayers
[i
];
2755 if (getDrmMode(handle
->flags
) != NO_DRM
) {
2757 for (j
= i
- 1; j
>= 0 ; j
--) {
2758 layer_for_gles
= &contents
->hwLayers
[j
];
2759 if (layer_for_gles
->compositionType
== HWC_OVERLAY
) {
2767 layer_for_gles
= &contents
->hwLayers
[changed_index
];
2770 layer_for_gles
->compositionType
= HWC_FRAMEBUFFER
;
2771 mLayerInfos
[changed_index
]->compositionType
= layer_for_gles
->compositionType
;
2772 mLayerInfos
[changed_index
]->mCheckOverlayFlag
|= cannotComposeFlag
;
2773 if (mLayerInfos
[changed_index
]->mInternalMPP
!= NULL
)
2774 mLayerInfos
[changed_index
]->mInternalMPP
->mState
= MPP_STATE_FREE
;
2775 if (mLayerInfos
[changed_index
]->mExternalMPP
!= NULL
)
2776 mLayerInfos
[changed_index
]->mExternalMPP
->mState
= MPP_STATE_FREE
;
2777 mLayerInfos
[changed_index
]->mInternalMPP
= NULL
;
2778 mLayerInfos
[changed_index
]->mExternalMPP
= NULL
;
2780 mFirstFb
= mLastFb
= changed_index
;
2782 mHwc
->totPixels
+= mXres
* mYres
;
2785 mFirstFb
= min(changed_index
, mFirstFb
);
2786 mLastFb
= max(changed_index
, mLastFb
);
2789 mFirstFb
= min(mFirstFb
, (size_t)NUM_HW_WINDOWS
-1);
2792 mHwc
->totPixels
+= WIDTH(layer
.displayFrame
) * HEIGHT(layer
.displayFrame
);
2795 if ((mUseSecureDMA
== false) || (isTopLayer
== false)) {
2797 /* FB Target is not top layer */
2798 if (mFbNeeded
&& ((mUseSecureDMA
&& !isCompressed(layer
))|| (mLastFb
!= (contents
->numHwLayers
- 2))))
2799 win_idx
= (win_idx
== mFirstFb
) ? (win_idx
+ 1) : win_idx
;
2800 win_idx
= min((size_t)win_idx
, (size_t)(NUM_HW_WINDOWS
- 1));
2806 for (size_t i
= mFirstFb
; i
< mLastFb
; i
++) {
2807 hwc_layer_1_t
&layer
= contents
->hwLayers
[i
];
2808 private_handle_t
*handle
= NULL
;
2810 handle
= private_handle_t::dynamicCast(layer
.handle
);
2811 if (handle
&& getDrmMode(handle
->flags
) != NO_DRM
) {
2812 layer
.hints
= HWC_HINT_CLEAR_FB
;
2814 contents
->hwLayers
[i
].compositionType
= HWC_FRAMEBUFFER
;
2815 mLayerInfos
[i
]->compositionType
= contents
->hwLayers
[i
].compositionType
;
2816 mLayerInfos
[i
]->mCheckOverlayFlag
|= eSandwitchedBetweenGLES
;
2817 if (mLayerInfos
[i
]->mInternalMPP
!= NULL
)
2818 mLayerInfos
[i
]->mInternalMPP
->mState
= MPP_STATE_FREE
;
2819 if (mLayerInfos
[i
]->mExternalMPP
!= NULL
)
2820 mLayerInfos
[i
]->mExternalMPP
->mState
= MPP_STATE_FREE
;
2821 mLayerInfos
[i
]->mInternalMPP
= NULL
;
2822 mLayerInfos
[i
]->mExternalMPP
= NULL
;
2823 if (handle
&& !isFormatRgb(handle
->format
))
2827 if (handleTotalBandwidthOverload(contents
))
2832 DISPLAY_LOGE("%s", "retry 100, can't allocate vpp, dump error state");
2833 android::String8 result
;
2835 dumpLayerInfo(result
);
2836 DISPLAY_LOGE("%s", result
.string());
2841 uint32_t rectCount
= 0;
2842 for (size_t i
= 0; i
< contents
->numHwLayers
; i
++) {
2843 hwc_layer_1_t
&layer
= contents
->hwLayers
[i
];
2845 private_handle_t
*handle
= private_handle_t::dynamicCast(layer
.handle
);
2846 if (handle
->format
== HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_PRIV
2847 && rectCount
< mOriginFrect
.size())
2848 layer
.sourceCropf
= mOriginFrect
[rectCount
++];
2852 for (size_t i
= 0; i
< contents
->numHwLayers
; i
++) {
2853 hwc_layer_1_t
&layer
= contents
->hwLayers
[i
];
2854 if (layer
.compositionType
== HWC_FRAMEBUFFER
)
2855 mFbUpdateRegion
= expand(mFbUpdateRegion
, layer
.displayFrame
);
2858 for (size_t i
= mLastFb
+ 1; i
< contents
->numHwLayers
; i
++) {
2859 hwc_layer_1_t
&layer
= contents
->hwLayers
[i
];
2860 if (layer
.compositionType
== HWC_OVERLAY
&& layer
.planeAlpha
> 0 && layer
.planeAlpha
< 255)
2861 mFbUpdateRegion
= expand(mFbUpdateRegion
, contents
->hwLayers
[i
].displayFrame
);
2865 #ifdef USE_DRM_BURST_LEN
2867 minWidth
= DRM_BURSTLEN_BYTES
* 8 / formatToBpp(HAL_PIXEL_FORMAT_RGBA_8888
);
2870 minWidth
= BURSTLEN_BYTES
* 8 / formatToBpp(HAL_PIXEL_FORMAT_RGBA_8888
);
2872 int w
= WIDTH(mFbUpdateRegion
);
2874 #if defined(USES_DUAL_DISPLAY)
2875 uint32_t maxRightPosition
= (mType
== EXYNOS_PRIMARY_DISPLAY
)?(mXres
/2):mXres
;
2876 if (mFbUpdateRegion
.left
+ minWidth
<= maxRightPosition
)
2877 mFbUpdateRegion
.right
= mFbUpdateRegion
.left
+ minWidth
;
2879 mFbUpdateRegion
.left
= mFbUpdateRegion
.right
- minWidth
;
2881 if (mFbUpdateRegion
.left
+ minWidth
<= mXres
)
2882 mFbUpdateRegion
.right
= mFbUpdateRegion
.left
+ minWidth
;
2884 mFbUpdateRegion
.left
= mFbUpdateRegion
.right
- minWidth
;
2889 void ExynosDisplay::assignWindows(hwc_display_contents_1_t
*contents
)
2891 unsigned int nextWindow
= 0;
2892 unsigned int directFbNum
= 0;
2893 bool isTopLayer
= false;
2895 hwc_layer_1_t
&fbLayer
= contents
->hwLayers
[contents
->numHwLayers
- 1];
2896 if (mFbNeeded
&& (contents
->numHwLayers
- 1 > 0)) {
2897 /* FramebufferTarget is the top layer */
2898 if (mUseSecureDMA
&& !isCompressed(fbLayer
) && mLastFb
== (contents
->numHwLayers
- 2))
2899 mLayerInfos
[contents
->numHwLayers
- 1]->mDmaType
= IDMA_SECURE
;
2900 else if (mInternalDMAs
.size() > 0 && !isCompressed(fbLayer
)) {
2901 mLayerInfos
[contents
->numHwLayers
- 1]->mDmaType
= mInternalDMAs
[directFbNum
];
2904 /* mDmaType was set by determineBandwidthSupport() */
2907 DISPLAY_LOGD(eDebugResourceAssigning
, "assigning layer %u to DMA %u", contents
->numHwLayers
- 1, mLayerInfos
[contents
->numHwLayers
- 1]->mDmaType
);
2910 if (mFbNeeded
&& mUseSecureDMA
&& !isCompressed(fbLayer
) && (mLastFb
== (contents
->numHwLayers
- 2)))
2911 mFbWindow
= NUM_HW_WINDOWS
- 1;
2913 mFbWindow
= NO_FB_NEEDED
;
2915 for (size_t i
= 0; i
< contents
->numHwLayers
; i
++) {
2916 hwc_layer_1_t
&layer
= contents
->hwLayers
[i
];
2917 mLayerInfos
[i
]->mWindowIndex
= -1;
2918 isTopLayer
= (i
== contents
->numHwLayers
- 2) ? true:false;
2920 if (mFbNeeded
&& (mFbWindow
!= NUM_HW_WINDOWS
- 1)) {
2922 mFbWindow
= nextWindow
;
2928 if (layer
.flags
& HWC_SKIP_RENDERING
)
2931 if (!layer
.planeAlpha
) {
2932 if (layer
.acquireFenceFd
>= 0)
2933 close(layer
.acquireFenceFd
);
2934 layer
.acquireFenceFd
= -1;
2935 layer
.releaseFenceFd
= -1;
2939 if (layer
.compositionType
!= HWC_FRAMEBUFFER
) {
2940 if (mFbNeeded
&& (layer
.compositionType
== HWC_FRAMEBUFFER_TARGET
)) {
2941 DISPLAY_LOGD(eDebugResourceAssigning
, "assigning framebuffer target %u to window %u", i
, nextWindow
);
2942 mLayerInfos
[i
]->mWindowIndex
= mFbWindow
;
2943 if (mLayerInfos
[i
]->mInternalMPP
!= NULL
)
2944 mLayerInfos
[i
]->mInternalMPP
->setDisplay(this);
2947 if (layer
.compositionType
== HWC_OVERLAY
) {
2948 if ((!isProcessingRequired(layer
) ||
2949 ((mLayerInfos
[i
]->mInternalMPP
== NULL
) && (mLayerInfos
[i
]->mExternalMPP
!= NULL
))) &&
2950 isOverlaySupportedByIDMA(layer
, i
) && (directFbNum
< mInternalDMAs
.size() || (mUseSecureDMA
&& isTopLayer
)))
2952 if (directFbNum
< mInternalDMAs
.size()) {
2953 DISPLAY_LOGD(eDebugResourceAssigning
, "assigning layer %u to DMA %u", i
, mInternalDMAs
[directFbNum
]);
2954 mLayerInfos
[i
]->mDmaType
= mInternalDMAs
[directFbNum
];
2955 mLayerInfos
[i
]->mWindowIndex
= nextWindow
;
2958 DISPLAY_LOGD(eDebugResourceAssigning
, "assigning layer %u to DMA %u", i
, IDMA_SECURE
);
2959 mLayerInfos
[i
]->mDmaType
= IDMA_SECURE
;
2960 mLayerInfos
[i
]->mWindowIndex
= NUM_HW_WINDOWS
- 1;
2963 DISPLAY_LOGD(eDebugResourceAssigning
, "%u layer can't use internalDMA, isProcessingRequired(%d)", i
, isProcessingRequired(layer
));
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
, 1) &&
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
);
3175 needDoubleOperation
|= ((dstW
< srcW
/ maxDownscaleExt
) && (dstW
>= srcW
/ (maxDownscaleExt
* maxDownscaleExt
))) ||
3176 ((dstH
< srcH
/ maxDownscaleExt
) && (dstH
>= srcH
/ (maxDownscaleExt
* maxDownscaleExt
)));
3179 * Both VPP and MSC should be used if
3180 * MSC should be used for DRM contents
3182 if (getDrmMode(srcHandle
->flags
) != NO_DRM
) {
3183 bool supportVPP
= false;
3184 for (size_t i
= 0; i
< mInternalMPPs
.size(); i
++ )
3186 if (mInternalMPPs
[i
]->isProcessingSupported(layer
, srcHandle
->format
) > 0) {
3191 if (supportVPP
== false)
3192 needDoubleOperation
|= true;
3197 * Destination format should be RGB if dstW or dstH is not aligned.
3198 * VPP is not required at this time.
3200 if (!isFormatRgb(srcHandle
->format
) &&
3201 (srcW
>= UHD_WIDTH
|| srcH
>= UHD_HEIGHT
) &&
3202 (mInternalMPPs
.size() > 0) &&
3203 (dstW
% mCheckIntMPP
->getCropWidthAlign(layer
) == 0) &&
3204 (dstH
% mCheckIntMPP
->getCropHeightAlign(layer
) == 0)) {
3205 needDoubleOperation
|= true;
3208 return needDoubleOperation
;
3211 bool ExynosDisplay::isBothMPPProcessingRequired(hwc_layer_1_t
&layer
, hwc_layer_1_t
*extMPPOutLayer
)
3213 bool needDoubleOperation
= false;
3214 if (layer
.handle
== NULL
)
3217 private_handle_t
*srcHandle
= private_handle_t::dynamicCast(layer
.handle
);
3218 if ((mExternalMPPs
.size() == 0) || (mInternalMPPs
.size() == 0))
3221 int maxUpscaleExt
= mExternalMPPs
[0]->getMaxUpscale();
3222 int maxUpscaleInt
= mCheckIntMPP
->getMaxUpscale();
3223 bool rot90or270
= !!(layer
.transform
& HAL_TRANSFORM_ROT_90
);
3224 int srcW
= WIDTH(layer
.sourceCropf
), srcH
= HEIGHT(layer
.sourceCropf
);
3227 dstW
= HEIGHT(layer
.displayFrame
);
3228 dstH
= WIDTH(layer
.displayFrame
);
3230 dstW
= WIDTH(layer
.displayFrame
);
3231 dstH
= HEIGHT(layer
.displayFrame
);
3234 int maxDownscaleExt
= mExternalMPPs
[0]->getMaxDownscale(layer
);
3235 int maxDownscaleInt
= mCheckIntMPP
->getMaxDownscale(layer
);
3237 needDoubleOperation
= isBothMPPProcessingRequired(layer
);
3239 /* set extMPPOutLayer */
3240 if (needDoubleOperation
&& extMPPOutLayer
!= NULL
) {
3241 memcpy(extMPPOutLayer
, &layer
, sizeof(hwc_layer_1_t
));
3242 extMPPOutLayer
->displayFrame
.left
= 0;
3243 extMPPOutLayer
->displayFrame
.top
= 0;
3245 if (dstW
> srcW
* maxUpscaleExt
) {
3246 extMPPOutLayer
->displayFrame
.right
= ALIGN_UP((int)ceilf((float)dstW
/ maxUpscaleInt
),
3247 mExternalMPPs
[0]->getDstWidthAlign(srcHandle
->format
));
3248 } else if (dstW
< srcW
/ maxDownscaleExt
) {
3249 extMPPOutLayer
->displayFrame
.right
= ALIGN(dstW
* maxDownscaleInt
,
3250 mExternalMPPs
[0]->getDstWidthAlign(srcHandle
->format
));
3252 extMPPOutLayer
->displayFrame
.right
= dstW
;
3255 if (dstH
> srcH
* maxUpscaleExt
) {
3256 extMPPOutLayer
->displayFrame
.bottom
= ALIGN_UP((int)ceilf((float)dstH
/ maxUpscaleInt
),
3257 mExternalMPPs
[0]->getDstHeightAlign(srcHandle
->format
));
3258 } else if (dstH
< srcH
/ maxDownscaleExt
) {
3259 extMPPOutLayer
->displayFrame
.bottom
= ALIGN(dstH
* maxDownscaleInt
,
3260 mExternalMPPs
[0]->getDstHeightAlign(srcHandle
->format
));
3262 extMPPOutLayer
->displayFrame
.bottom
= dstH
;
3266 dstW
= extMPPOutLayer
->displayFrame
.bottom
;
3267 dstH
= extMPPOutLayer
->displayFrame
.right
;
3268 extMPPOutLayer
->displayFrame
.right
= dstW
;
3269 extMPPOutLayer
->displayFrame
.bottom
= dstH
;
3273 return needDoubleOperation
;
3276 bool ExynosDisplay::isSourceCropfSupported(hwc_layer_1_t layer __unused
)
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 */
3283 if ((isFormatRgb(handle
->format
) && (bpp
== 32)) ||
3284 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 bool ExynosDisplay::checkConfigChanged(struct decon_win_config_data
&/*lastConfigData*/, struct decon_win_config_data
&/*newConfigData*/)
3317 /* Force this check to always return true, otherwise we have unreliable retire fences */
3322 void ExynosDisplay::removeIDMA(decon_idma_type idma
)
3324 for (size_t i
= mInternalDMAs
.size(); i
-- > 0;) {
3325 if (mInternalDMAs
[i
] == (unsigned int)idma
) {
3326 mInternalDMAs
.removeItemsAt(i
);
3331 int ExynosDisplay::getDisplayConfigs(uint32_t *configs
, size_t *numConfigs
)
3338 int ExynosDisplay::getDeconDMAType(ExynosMPPModule
* internalMPP
)
3340 if (internalMPP
->mType
== MPP_VG
)
3341 return IDMA_VG0
+ internalMPP
->mIndex
;
3342 else if (internalMPP
->mType
== MPP_VGR
)
3343 return IDMA_VGR0
+ internalMPP
->mIndex
;
3344 else if (internalMPP
->mType
== MPP_VPP_G
) {
3345 switch (internalMPP
->mIndex
) {
3361 void ExynosDisplay::dumpContents(android::String8
& result
, hwc_display_contents_1_t
*contents
)
3363 for (size_t i
= 0; i
< contents
->numHwLayers
; i
++) {
3364 hwc_layer_1_t
&layer
= contents
->hwLayers
[i
];
3365 result
.appendFormat("[%zu] type=%d, flags=%08x, handle=%p, tr=%02x, blend=%04x, "
3366 "{%7.1f,%7.1f,%7.1f,%7.1f}, {%d,%d,%d,%d}\n",
3368 layer
.compositionType
, layer
.flags
, layer
.handle
, layer
.transform
,
3370 layer
.sourceCropf
.left
,
3371 layer
.sourceCropf
.top
,
3372 layer
.sourceCropf
.right
,
3373 layer
.sourceCropf
.bottom
,
3374 layer
.displayFrame
.left
,
3375 layer
.displayFrame
.top
,
3376 layer
.displayFrame
.right
,
3377 layer
.displayFrame
.bottom
);
3382 int ExynosDisplay::checkConfigValidation(decon_win_config
*config
)
3384 bool flagValidConfig
= true;
3385 for (size_t i
= 0; i
< MAX_DECON_WIN
; i
++) {
3386 if (config
[i
].state
!= config
[i
].DECON_WIN_STATE_DISABLED
) {
3387 /* multiple dma mapping */
3388 for (size_t j
= (i
+1); j
< MAX_DECON_WIN
; j
++) {
3389 if ((config
[i
].state
== config
[i
].DECON_WIN_STATE_BUFFER
) &&
3390 (config
[j
].state
== config
[j
].DECON_WIN_STATE_BUFFER
)) {
3391 if (config
[i
].idma_type
== config
[j
].idma_type
) {
3392 ALOGE("WIN_CONFIG error: duplicated dma(%d) between win%d, win%d",
3393 config
[i
].idma_type
, i
, j
);
3394 config
[j
].state
= config
[j
].DECON_WIN_STATE_DISABLED
;
3395 flagValidConfig
= false;
3399 if ((config
[i
].src
.x
< 0) || (config
[i
].src
.y
< 0)||
3400 (config
[i
].dst
.x
< 0) || (config
[i
].dst
.y
< 0)||
3401 (config
[i
].dst
.x
+ config
[i
].dst
.w
> (uint32_t)mXres
) ||
3402 (config
[i
].dst
.y
+ config
[i
].dst
.h
> (uint32_t)mYres
)) {
3403 ALOGE("WIN_CONFIG error: invalid pos or size win%d", i
);
3404 config
[i
].state
= config
[i
].DECON_WIN_STATE_DISABLED
;
3405 flagValidConfig
= false;
3408 if (i
>= NUM_HW_WINDOWS
) {
3409 ALOGE("WIN_CONFIG error: invalid window number win%d", i
);
3410 config
[i
].state
= config
[i
].DECON_WIN_STATE_DISABLED
;
3411 flagValidConfig
= false;
3416 if (flagValidConfig
)
3422 int ExynosDisplay::setPowerMode(int mode
)
3424 #if defined(S3CFB_POWER_MODE)
3425 return ioctl(this->mDisplayFd
, S3CFB_POWER_MODE
, &mode
);
3427 return ioctl(this->mDisplayFd
, FBIOBLANK
, (mode
== HWC_POWER_MODE_OFF
? FB_BLANK_POWERDOWN
: FB_BLANK_UNBLANK
));