libhwjpeg: resolve compilation errors
[GitHub/LineageOS/android_hardware_samsung_slsi_exynos.git] / libvppdisplay / ExynosDisplay.cpp
1 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
2
3 //#define LOG_NDEBUG 0
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>
11 #include <inttypes.h>
12 #if defined(USES_DUAL_DISPLAY)
13 #include "ExynosSecondaryDisplayModule.h"
14 #endif
15
16 int getGCD(int a, int b)
17 {
18 if (b == 0)
19 return a;
20 else
21 return getGCD(b, a%b);
22 }
23
24 int getLCM(int a, int b)
25 {
26 return (a*b)/getGCD(a,b);
27 }
28
29 bool frameChanged(decon_frame *f1, decon_frame *f2)
30 {
31 return f1->x != f2->x ||
32 f1->y != f2->y ||
33 f1->w != f2->w ||
34 f1->h != f2->h ||
35 f1->f_w != f2->f_w ||
36 f1->f_h != f2->f_h;
37 }
38
39 bool winConfigChanged(decon_win_config *c1, decon_win_config *c2)
40 {
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;
50 }
51
52 void ExynosDisplay::dumpConfig(decon_win_config &c)
53 {
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);
67 }
68 }
69
70 void ExynosDisplay::dumpConfig(decon_win_config &c, android::String8& result)
71 {
72 result.appendFormat("\tstate = %u", c.state);
73 if (c.state == c.DECON_WIN_STATE_COLOR) {
74 result.appendFormat("\t\tcolor = %u", c.color);
75 } else {
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);
85 }
86 }
87
88 enum decon_pixel_format halFormatToS3CFormat(int format)
89 {
90 switch (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;
102 #endif
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;
119 #endif
120 #ifdef DECON_PIXEL_FORMAT_NV12N
121 case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN:
122 return DECON_PIXEL_FORMAT_NV12N;
123 #endif
124 default:
125 return DECON_PIXEL_FORMAT_MAX;
126 }
127 }
128
129 int S3CFormatToHalFormat(enum decon_pixel_format format)
130 {
131 switch (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;
143 #endif
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;
159 #endif
160 #ifdef DECON_PIXEL_FORMAT_NV12N_10B
161 case DECON_PIXEL_FORMAT_NV12N_10B:
162 return HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_S10B;
163 #endif
164 default:
165 return -1;
166 }
167 }
168
169 bool isFormatSupported(int format)
170 {
171 return halFormatToS3CFormat(format) < DECON_PIXEL_FORMAT_MAX;
172 }
173
174 enum decon_blending halBlendingToS3CBlending(int32_t blending)
175 {
176 switch (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;
183
184 default:
185 return DECON_BLENDING_MAX;
186 }
187 }
188
189 bool isBlendingSupported(int32_t blending)
190 {
191 return halBlendingToS3CBlending(blending) < DECON_BLENDING_MAX;
192 }
193
194 #define NUMA(a) (sizeof(a) / sizeof(a [0]))
195 const char *deconFormat2str(uint32_t format)
196 {
197 android::String8 result;
198
199 for (unsigned int n1 = 0; n1 < NUMA(deconFormat); n1++) {
200 if (format == deconFormat[n1].format) {
201 return deconFormat[n1].desc;
202 }
203 }
204
205 result.appendFormat("? %08x", format);
206 return result;
207 }
208
209 enum vpp_rotate halTransformToHWRot(uint32_t halTransform)
210 {
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:
217 return VPP_ROT_180;
218 case HAL_TRANSFORM_ROT_90:
219 return VPP_ROT_90;
220 case (HAL_TRANSFORM_ROT_90|HAL_TRANSFORM_FLIP_H):
221 /*
222 * HAL: HAL_TRANSFORM_FLIP_H -> HAL_TRANSFORM_ROT_90
223 * VPP: ROT_90 -> XFLIP
224 */
225 return VPP_ROT_90_XFLIP;
226 case (HAL_TRANSFORM_ROT_90|HAL_TRANSFORM_FLIP_V):
227 /*
228 * HAL: HAL_TRANSFORM_FLIP_V -> HAL_TRANSFORM_ROT_90
229 * VPP: ROT_90 -> YFLIP
230 */
231 return VPP_ROT_90_YFLIP;
232 case HAL_TRANSFORM_ROT_270:
233 return VPP_ROT_270;
234 default:
235 return VPP_ROT_NORMAL;
236 }
237 }
238
239 ExynosDisplay::ExynosDisplay(int __unused numGSCs)
240 : mDisplayFd(-1),
241 mType(0),
242 mPanelType(PANEL_LEGACY),
243 mDSCHSliceNum(WINUPDATE_DSC_H_SLICE_NUM),
244 mDSCYSliceSize(WINUPDATE_DSC_Y_SLICE_SIZE),
245 mXres(0),
246 mYres(0),
247 mXdpi(0),
248 mYdpi(0),
249 mVsyncPeriod(0),
250 mBlanked(true),
251 mHwc(NULL),
252 mAllocDevice(NULL),
253 mGrallocModule(NULL),
254 mLastFbWindow(NO_FB_NEEDED),
255 mVirtualOverlayFlag(0),
256 mBypassSkipStaticLayer(false),
257 mMPPLayers(0),
258 mYuvLayers(0),
259 mHasDrmSurface(false),
260 mFbNeeded(false),
261 mFirstFb(0),
262 mLastFb(0),
263 mFbWindow(0),
264 mForceFb(false),
265 mForceOverlayLayerIndex(-1),
266 mAllowedOverlays(5),
267 mOtfMode(OTF_OFF),
268 mGscUsed(false),
269 mMaxWindowOverlapCnt(NUM_HW_WINDOWS),
270 mUseSecureDMA(false),
271 mExternalMPPDstFormat(HAL_PIXEL_FORMAT_RGBX_8888),
272 mSkipStaticInitFlag(false),
273 mNumStaticLayers(0),
274 mLastRetireFenceFd(-1),
275 mFbPreAssigned(false),
276 mActiveConfigIndex(0),
277 mWinData(NULL)
278 {
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));
284
285 mPreProcessedInfo.mHasDrmSurface = false;
286 mCheckIntMPP = new ExynosMPPModule(NULL, MPP_VGR, 0);
287
288 mWinData = (struct decon_win_config_data *)malloc(sizeof(*mWinData));
289 if (mWinData == NULL)
290 DISPLAY_LOGE("Fail to allocate mWinData");
291 }
292 ExynosDisplay::ExynosDisplay(uint32_t type, struct exynos5_hwc_composer_device_1_t *pdev)
293 : mDisplayFd(-1),
294 mType(type),
295 mPanelType(PANEL_LEGACY),
296 mDSCHSliceNum(WINUPDATE_DSC_H_SLICE_NUM),
297 mDSCYSliceSize(WINUPDATE_DSC_Y_SLICE_SIZE),
298 mXres(0),
299 mYres(0),
300 mXdpi(0),
301 mYdpi(0),
302 mVsyncPeriod(0),
303 mBlanked(true),
304 mHwc(pdev),
305 mAllocDevice(NULL),
306 mGrallocModule(NULL),
307 mLastFbWindow(NO_FB_NEEDED),
308 mVirtualOverlayFlag(0),
309 mBypassSkipStaticLayer(false),
310 mMPPLayers(0),
311 mYuvLayers(0),
312 mHasDrmSurface(false),
313 mFbNeeded(false),
314 mFirstFb(0),
315 mLastFb(0),
316 mFbWindow(0),
317 mForceFb(false),
318 mForceOverlayLayerIndex(-1),
319 mAllowedOverlays(5),
320 mOtfMode(OTF_OFF),
321 mGscUsed(false),
322 mMaxWindowOverlapCnt(NUM_HW_WINDOWS),
323 mUseSecureDMA(false),
324 mExternalMPPDstFormat(HAL_PIXEL_FORMAT_RGBX_8888),
325 mSkipStaticInitFlag(false),
326 mNumStaticLayers(0),
327 mLastRetireFenceFd(-1),
328 mFbPreAssigned(false),
329 mActiveConfigIndex(0),
330 mWinData(NULL)
331 {
332 memset(mLastMPPMap, 0, sizeof(mLastMPPMap));
333 memset(mLastHandles, 0, sizeof(mLastHandles));
334 memset(&mLastConfigData, 0, sizeof(mLastConfigData));
335 memset(mLastLayerHandles, 0, sizeof(mLastLayerHandles));
336
337 switch (mType) {
338 case EXYNOS_VIRTUAL_DISPLAY:
339 mDisplayName = android::String8("VirtualDisplay");
340 break;
341 case EXYNOS_EXTERNAL_DISPLAY:
342 mDisplayName = android::String8("ExternalDisplay");
343 break;
344 case EXYNOS_PRIMARY_DISPLAY:
345 mDisplayName = android::String8("PrimaryDisplay");
346 break;
347 #if defined(USES_DUAL_DISPLAY)
348 case EXYNOS_SECONDARY_DISPLAY:
349 mDisplayName = android::String8("SecondaryDisplay");
350 break;
351 #endif
352 default:
353 mDisplayName = android::String8("Unknown");
354 break;
355 }
356 memset(&mFbUpdateRegion, 0, sizeof(mFbUpdateRegion));
357
358 mPreProcessedInfo.mHasDrmSurface = false;
359 mCheckIntMPP = new ExynosMPPModule(NULL, MPP_VGR, 0);
360
361 mWinData = (struct decon_win_config_data *)malloc(sizeof(*mWinData));
362 if (mWinData == NULL)
363 DISPLAY_LOGE("Fail to allocate mWinData");
364 }
365
366 ExynosDisplay::~ExynosDisplay()
367 {
368 if (!mLayerInfos.isEmpty()) {
369 for (size_t i = 0; i < mLayerInfos.size(); i++) {
370 delete mLayerInfos[i];
371 }
372 mLayerInfos.clear();
373 }
374 if (mCheckIntMPP != NULL) {
375 delete mCheckIntMPP;
376 mCheckIntMPP = NULL;
377 }
378
379 if (mWinData != NULL)
380 free(mWinData);
381 }
382
383 int ExynosDisplay::prepare(hwc_display_contents_1_t *contents)
384 {
385 ATRACE_CALL();
386 DISPLAY_LOGD(eDebugDefault, "preparing %u layers for FIMD", contents->numHwLayers);
387
388 if (!mForceFb)
389 skipStaticLayers(contents);
390
391 if (mVirtualOverlayFlag)
392 mFbNeeded = 0;
393
394 if (!mFbNeeded)
395 mFbWindow = NO_FB_NEEDED;
396
397 return 0;
398 }
399
400 int ExynosDisplay::set(hwc_display_contents_1_t *contents)
401 {
402 hwc_layer_1_t *fb_layer = NULL;
403 int err = 0;
404
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];
409
410 if (CC_UNLIKELY(!fb_layer)) {
411 DISPLAY_LOGE("framebuffer target expected, but not provided");
412 err = -EINVAL;
413 } else {
414 DISPLAY_LOGD(eDebugDefault, "framebuffer target buffer:");
415 dumpLayer(eDebugDefault, fb_layer);
416 }
417 }
418
419 int fence;
420 if (!err) {
421 fence = postFrame(contents);
422 if (fence < 0)
423 err = fence;
424 }
425
426 #if defined(USES_DUAL_DISPLAY)
427 if (mType != EXYNOS_SECONDARY_DISPLAY)
428 {
429 #endif
430 if (err < 0)
431 fence = clearDisplay();
432
433 if (fence == 0) {
434 /*
435 * WIN_CONFIG is skipped, not error
436 */
437 fence = -1;
438 if (mLastRetireFenceFd >= 0) {
439 int dup_fd = dup(mLastRetireFenceFd);
440 if (dup_fd >= 0) {
441 fence = dup_fd;
442 mLastRetireFenceFd = dup_fd;
443 dupFence(fence, contents);
444 } else {
445 DISPLAY_LOGW("mLastRetireFenceFd dup failed: %s", strerror(errno));
446 mLastRetireFenceFd = -1;
447 }
448 } else {
449 ALOGE("WIN_CONFIG is skipped, but mLastRetireFenceFd is not valid");
450 }
451 } else {
452 mLastRetireFenceFd = fence;
453 dupFence(fence, contents);
454 }
455 #if defined(USES_DUAL_DISPLAY)
456 }
457 #endif
458
459 uint32_t rectCount = 0;
460 for (size_t i = 0; i < contents->numHwLayers; i++) {
461 hwc_layer_1_t &layer = contents->hwLayers[i];
462 if (layer.handle) {
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++];
467 }
468 }
469 mOriginFrect.clear();
470 mBackUpFrect.clear();
471
472 return err;
473 }
474
475 void ExynosDisplay::dupFence(int fence, hwc_display_contents_1_t *contents)
476 {
477 if (contents == NULL)
478 return;
479
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);
485
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;
492 }
493 }
494
495 if ((mVirtualOverlayFlag == true) && (layer.compositionType == HWC_OVERLAY) &&
496 ((handle != NULL) && (getDrmMode(handle->flags) == NO_DRM)) &&
497 (mFirstFb <= i) && (i <= mLastFb))
498 continue;
499
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,
507 dup_fd);
508 if (dup_fd < 0)
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);
515 }
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;
521 }
522 exysnosMPP->mDstBufFence[exysnosMPP->mCurrentBuf] = dup_fd;
523 exysnosMPP->mCurrentBuf = (exysnosMPP->mCurrentBuf + 1) % exysnosMPP->mNumAvailableDstBuffers;
524 } else {
525 if (this->mVirtualOverlayFlag && (layer.compositionType == HWC_FRAMEBUFFER_TARGET)) {
526 if (layer.releaseFenceFd >= 0)
527 close(layer.releaseFenceFd);
528 }
529 layer.releaseFenceFd = dup_fd;
530 }
531 }
532 }
533
534 #if defined(USES_DUAL_DISPLAY)
535 if (mType == EXYNOS_SECONDARY_DISPLAY)
536 contents->retireFenceFd = dup(fence);
537 else
538 contents->retireFenceFd = fence;
539 #else
540 contents->retireFenceFd = fence;
541 #endif
542 }
543
544 void ExynosDisplay::dump(android::String8& result)
545 {
546 result.append(
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"
550
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", "-", "-", "-", "-", "-", "-", "-");
558 }
559 else {
560 if (config.state == config.DECON_WIN_STATE_COLOR)
561 result.appendFormat(" %8s | %12s | %8x | %5s | %2s | %13s", "COLOR",
562 "-", config.color, "-", "-", "-");
563 else
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));
568
569 result.appendFormat(" | [%5d,%5d] | [%5u,%5u]", config.dst.x, config.dst.y,
570 config.dst.w, config.dst.h);
571 }
572 if (mLastMPPMap[i].internal_mpp.type == -1) {
573 result.appendFormat(" | [%2s,%2s]", "-", "-");
574 } else {
575 result.appendFormat(" | [%2d,%2d]", mLastMPPMap[i].internal_mpp.type, mLastMPPMap[i].internal_mpp.index);
576 }
577
578 if (mLastMPPMap[i].external_mpp.type == -1) {
579 result.appendFormat(" | [%2s,%2s]", "-", "-");
580 } else {
581 result.appendFormat(" | [%2d,%2d]", mLastMPPMap[i].external_mpp.type, mLastMPPMap[i].external_mpp.index);
582 }
583 result.append("\n");
584 }
585 }
586
587 void ExynosDisplay::freeMPP()
588 {
589 }
590
591 void ExynosDisplay::doPreProcessing(hwc_display_contents_1_t* contents)
592 {
593 mPreProcessedInfo.mHasDrmSurface = false;
594 mForceOverlayLayerIndex = -1;
595 this->mHasDrmSurface = false;
596 mYuvLayers = 0;
597 mLayersNeedScaling = false;
598
599 for (size_t i = 0; i < contents->numHwLayers; i++) {
600 hwc_layer_1_t &layer = contents->hwLayers[i];
601 if (layer.handle) {
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;
607 }
608 if (!isFormatRgb(h->format)) {
609 this->mYuvLayers++;
610 }
611 if (isScaled(layer))
612 mLayersNeedScaling = true;
613 }
614 }
615 }
616
617 void ExynosDisplay::allocateLayerInfos(hwc_display_contents_1_t* contents)
618 {
619 if (contents == NULL)
620 return;
621
622 if (!mLayerInfos.isEmpty()) {
623 for (size_t i = 0; i < mLayerInfos.size(); i++) {
624 delete mLayerInfos[i];
625 }
626 mLayerInfos.clear();
627 }
628
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);
634 }
635
636 mForceFb = mHwc->force_gpu;
637
638 doPreProcessing(contents);
639 }
640
641 void ExynosDisplay::dumpLayerInfo(android::String8& result)
642 {
643 if (!mLayerInfos.isEmpty()) {
644 result.append(
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[] = {
651 "GLES",
652 "HWC",
653 "BACKGROUND",
654 "FB TARGET",
655 "UNKNOWN"};
656
657 if (type >= NELEM(compositionTypeName))
658 type = NELEM(compositionTypeName) - 1;
659 result.appendFormat(
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);
665
666 if (mLayerInfos[i]->mInternalMPP == NULL)
667 result.appendFormat(" | [%3s, %2s]", "-", "-");
668 else {
669 result.appendFormat(" | [%3s, %2d]", mLayerInfos[i]->mInternalMPP->getName().string(), mLayerInfos[i]->mInternalMPP->mIndex);
670 }
671
672 if (mLayerInfos[i]->mExternalMPP == NULL)
673 result.appendFormat(" | [%3s, %2s]", "-", "-");
674 else {
675 result.appendFormat(" | [%3s, %2d]", mLayerInfos[i]->mExternalMPP->getName().string(), mLayerInfos[i]->mExternalMPP->mIndex);
676 }
677 result.append("\n");
678 }
679 }
680 result.append("\n");
681 }
682
683 bool ExynosDisplay::handleTotalBandwidthOverload(hwc_display_contents_1_t *contents)
684 {
685 bool changed = false;
686 bool addFB = true;
687 if (mHwc->totPixels >= FIMD_TOTAL_BW_LIMIT) {
688 changed = true;
689 if (mFbNeeded) {
690 for (int i = mFirstFb - 1; i >= 0; i--) {
691 if (mForceOverlayLayerIndex == 0 && i == 0)
692 break;
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)
702 break;
703 }
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;
712 mLastFb = i;
713 mHwc->totPixels -= WIDTH(layer.displayFrame) * HEIGHT(layer.displayFrame);
714 if (mHwc->totPixels < FIMD_TOTAL_BW_LIMIT)
715 break;
716 }
717 }
718 } else {
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;
729 if (addFB) {
730 addFB = false;
731 mHwc->totPixels += mXres * mYres;
732 }
733 mHwc->totPixels -= WIDTH(layer.displayFrame) * HEIGHT(layer.displayFrame);
734 if (mHwc->totPixels < FIMD_TOTAL_BW_LIMIT)
735 break;
736 }
737 }
738 if (mForceOverlayLayerIndex == 0)
739 mFirstFb = 1;
740 else
741 mFirstFb = 0;
742 }
743 mFbNeeded = true;
744 }
745
746 return changed;
747 }
748
749 int ExynosDisplay::clearDisplay()
750 {
751 struct decon_win_config_data win_data;
752 memset(&win_data, 0, sizeof(win_data));
753
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
759
760 return win_data.fence;
761 }
762
763 int ExynosDisplay::getCompModeSwitch()
764 {
765 unsigned int updateFps = 0;
766 unsigned int lcd_size = this->mXres * this->mYres;
767 uint64_t TimeStampDiff;
768 float Temp;
769
770 if (!mHwc->hwc_ctrl.dynamic_recomp_mode) {
771 mHwc->LastModeSwitchTimeStamp = 0;
772 mHwc->CompModeSwitch = NO_MODE_SWITCH;
773 return 0;
774 }
775
776 /* initialize the Timestamps */
777 if (!mHwc->LastModeSwitchTimeStamp) {
778 mHwc->LastModeSwitchTimeStamp = mHwc->LastUpdateTimeStamp;
779 mHwc->CompModeSwitch = NO_MODE_SWITCH;
780 return 0;
781 }
782
783 /* If video layer is there, skip the mode switch */
784 if (mYuvLayers || mLayersNeedScaling) {
785 if (mHwc->CompModeSwitch != HWC_2_GLES) {
786 return 0;
787 } else {
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");
792 return GLES_2_HWC;
793 }
794 }
795
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) {
799 return 0;
800 } else {
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");
805 return GLES_2_HWC;
806 }
807 }
808
809 /*
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
812 */
813 TimeStampDiff = systemTime(SYSTEM_TIME_MONOTONIC) - mHwc->LastModeSwitchTimeStamp;
814
815 /*
816 * previous CompModeSwitch was GLES_2_HWC: check fps every 250ms from LastModeSwitchTimeStamp
817 * previous CompModeSwitch was HWC_2_GLES: check immediately
818 */
819 if ((mHwc->CompModeSwitch != HWC_2_GLES) && (TimeStampDiff < (VSYNC_INTERVAL * 15))) {
820 return 0;
821 }
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;
827 } else {
828 Temp = (VSYNC_INTERVAL * 60) / TimeStampDiff;
829 updateFps = (int)(mHwc->updateCallCnt * Temp + 0.5);
830 }
831 mHwc->updateCallCnt = 0;
832 /*
833 * FPS estimation.
834 * If FPS is lower than HWC_FPS_TH, try to switch the mode to GLES
835 */
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);
840 return HWC_2_GLES;
841 } else {
842 return 0;
843 }
844 } else {
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);
848 return GLES_2_HWC;
849 } else {
850 return 0;
851 }
852 }
853
854 return 0;
855 }
856
857 int32_t ExynosDisplay::getDisplayAttributes(const uint32_t attribute, uint32_t __unused config)
858 {
859 switch(attribute) {
860 case HWC_DISPLAY_VSYNC_PERIOD:
861 return this->mVsyncPeriod;
862
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;
867 else
868 return mXres;
869 #else
870 return this->mXres;
871 #endif
872
873 case HWC_DISPLAY_HEIGHT:
874 return this->mYres;
875
876 case HWC_DISPLAY_DPI_X:
877 return this->mXdpi;
878
879 case HWC_DISPLAY_DPI_Y:
880 return this->mYdpi;
881
882 default:
883 DISPLAY_LOGE("unknown display attribute %u", attribute);
884 return -EINVAL;
885 }
886 }
887
888 bool ExynosDisplay::isOverlaySupportedByIDMA(hwc_layer_1_t __unused &layer, size_t __unused index)
889 {
890 if (isCompressed(layer))
891 return false;
892 else
893 return true;
894 }
895
896 void ExynosDisplay::getIDMAMinSize(hwc_layer_1_t __unused &layer, int *w, int *h)
897 {
898 *w = 1;
899 *h = 1;
900 }
901
902 bool ExynosDisplay::isOverlaySupported(hwc_layer_1_t &layer, size_t index, bool useVPPOverlay,
903 ExynosMPPModule** supportedInternalMPP, ExynosMPPModule** supportedExternalMPP)
904 {
905 int ret = 0;
906 ExynosMPPModule* transitionInternalMPP = NULL;
907 private_handle_t *handle = NULL;
908 int handleFormat = 0;
909 bool firstFrameFramebufferTarget = false;
910
911 DISPLAY_LOGD(eDebugOverlaySupported, "isOverlaySupported:: index(%d), useVPPOverlay(%d)", index, useVPPOverlay);
912
913 if (layer.flags & HWC_SKIP_LAYER) {
914 mLayerInfos[index]->mCheckOverlayFlag |= eSkipLayer;
915 DISPLAY_LOGD(eDebugOverlaySupported, "\tlayer %u: skipping", index);
916 return false;
917 }
918
919 if (!layer.planeAlpha)
920 return true;
921
922 if (index == 0 && layer.planeAlpha < 255) {
923 DISPLAY_LOGD(eDebugOverlaySupported, "\tlayer %u: eUnsupportedPlaneAlpha", index);
924 mLayerInfos[index]->mCheckOverlayFlag |= eUnsupportedPlaneAlpha;
925 return false;
926 }
927
928 if (layer.handle) {
929 handle = private_handle_t::dynamicCast(layer.handle);
930 handleFormat = handle->format;
931 }
932
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;
936 return false;
937 }
938
939 if (!handle && (layer.compositionType == HWC_FRAMEBUFFER_TARGET)) {
940 firstFrameFramebufferTarget = true;
941 handleFormat = HAL_PIXEL_FORMAT_RGBA_8888;
942 }
943
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)
949 return false;
950 }
951
952 if (!isBlendingSupported(layer.blending)) {
953 DISPLAY_LOGD(eDebugOverlaySupported, "\tlayer %u: blending %d not supported", index, layer.blending);
954 mLayerInfos[index]->mCheckOverlayFlag |= eUnsupportedBlending;
955 return false;
956 }
957
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;
962
963 if ((bpp == 16) &&
964 ((layer.displayFrame.left % 2 != 0) || (layer.displayFrame.right % 2 != 0))) {
965 DISPLAY_LOGD(eDebugOverlaySupported, "\tlayer %u: eNotAlignedDstPosition", index);
966 mLayerInfos[index]->mCheckOverlayFlag |= eNotAlignedDstPosition;
967 return false;
968 }
969
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;
977 return false;
978 }
979 } else {
980 #endif
981 DISPLAY_LOGD(eDebugOverlaySupported, "\tlayer %u: visible area is too narrow", index);
982 mLayerInfos[index]->mCheckOverlayFlag |= eUnsupportedDstWidth;
983 return false;
984 #ifdef USE_DRM_BURST_LEN
985 }
986 #endif
987 }
988
989 if (!isProcessingRequired(layer) && !useVPPOverlay)
990 return true;
991
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);
997
998 if (isBothMPPUsed) {
999 if ((*supportedInternalMPP != NULL) && (*supportedExternalMPP != NULL))
1000 return true;
1001 } else {
1002 if ((*supportedInternalMPP != NULL) || (*supportedExternalMPP != NULL && !useVPPOverlay))
1003 return true;
1004 }
1005
1006 if (*supportedExternalMPP == NULL && isBothMPPUsed)
1007 {
1008 /* extMPPOutLayer is output of ExtMPP
1009 * The output of ExtMPP is the input of IntMPP
1010 */
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;
1017
1018 /* extMPPOutLayer is output of ExtMPP */
1019 for (size_t i = 0; i < mExternalMPPs.size(); i++)
1020 {
1021 ExynosMPPModule* externalMPP = mExternalMPPs[i];
1022 if (externalMPP->mState == MPP_STATE_FREE) {
1023 ret = externalMPP->isProcessingSupported(extMPPOutLayer, dst_format);
1024 if (ret > 0) {
1025 *supportedExternalMPP = externalMPP;
1026 break;
1027 } else {
1028 mLayerInfos[index]->mCheckMPPFlag |= -ret;
1029 }
1030 }
1031 }
1032
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;
1037 return false;
1038 }
1039 }
1040 if (*supportedInternalMPP == NULL) {
1041 for (size_t i = 0; i < mInternalMPPs.size(); i++)
1042 {
1043 ExynosMPPModule* internalMPP = mInternalMPPs[i];
1044 hwc_layer_1_t extMPPTempOutLayer = extMPPOutLayer;
1045 if (isBothMPPUsed) {
1046 if (internalMPP->mType == MPP_VPP_G)
1047 continue;
1048 /* extMPPOutLayer is output of ExtMPP
1049 * The output of ExtMPP is the input of IntMPP
1050 */
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;
1056
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;
1067 }
1068 ExynosDisplay *addedDisplay = (mHwc->hdmi_hpd ? (ExynosDisplay *)mHwc->externalDisplay : (ExynosDisplay *)mHwc->virtualDisplay);
1069 ExynosDisplay *otherDisplay = (mType ? (ExynosDisplay *)mHwc->primaryDisplay : addedDisplay);
1070
1071 /*
1072 * If MPP was assigned to other Device in previous frame
1073 * then doesn't assign it untill it is cleared
1074 */
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)
1079 ret = 1;
1080 else {
1081 ret = internalMPP->isProcessingSupported(extMPPTempOutLayer, ((private_handle_t *)extMPPTempOutLayer.handle)->format);
1082 handle->format = originalHandleFormt;
1083 }
1084 if (ret > 0) {
1085 *supportedInternalMPP = internalMPP;
1086 return true;
1087 } else {
1088 mLayerInfos[index]->mCheckMPPFlag |= -ret;
1089 }
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;
1094 }
1095 if (handle)
1096 handle->format = originalHandleFormt;
1097 }
1098 }
1099
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);
1106 }
1107 return false;
1108 }
1109
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);
1116 }
1117 mLayerInfos[index]->mCheckOverlayFlag |= eInsufficientMPP;
1118 return false;
1119 }
1120
1121 if (*supportedExternalMPP == NULL) {
1122 for (size_t i = 0; i < mExternalMPPs.size(); i++)
1123 {
1124 ExynosMPPModule* externalMPP = mExternalMPPs[i];
1125 int dst_format = handleFormat;
1126 if (!isFormatRgb(handleFormat))
1127 dst_format = mExternalMPPDstFormat;
1128
1129 if (externalMPP->mState == MPP_STATE_FREE) {
1130 if (firstFrameFramebufferTarget)
1131 ret = 1;
1132 else
1133 ret = externalMPP->isProcessingSupported(layer, dst_format);
1134 if (ret > 0) {
1135 *supportedExternalMPP = externalMPP;
1136 if (useVPPOverlay)
1137 break;
1138 return true;
1139 } else {
1140 mLayerInfos[index]->mCheckMPPFlag |= -ret;
1141 }
1142 }
1143 }
1144 }
1145
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++)
1152 {
1153 extMPPOutLayer = layer;
1154 /* extMPPOutLayer is output of ExtMPP
1155 * The output of ExtMPP is the input of IntMPP
1156 */
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;
1162 if (handle)
1163 ((private_handle_t *)extMPPOutLayer.handle)->format = dst_format;
1164 ExynosMPPModule* internalMPP = mInternalMPPs[i];
1165
1166 /*
1167 * If MPP was assigned to other Device in previous frame
1168 * then doesn't assign it untill it is cleared
1169 */
1170 if ((internalMPP->mState == MPP_STATE_FREE) &&
1171 (internalMPP->mDisplay == NULL || internalMPP->mDisplay == this)) {
1172 if (firstFrameFramebufferTarget)
1173 ret = 1;
1174 else {
1175 ret = internalMPP->isProcessingSupported(extMPPOutLayer, ((private_handle_t *)extMPPOutLayer.handle)->format);
1176 handle->format = originalHandleFormt;
1177 }
1178 if (ret > 0) {
1179 *supportedInternalMPP = internalMPP;
1180 return true;
1181 } else {
1182 mLayerInfos[index]->mCheckMPPFlag |= -ret;
1183 }
1184 } else {
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;
1190 } else {
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;
1196 }
1197 }
1198
1199 if (handle)
1200 handle->format = originalHandleFormt;
1201 }
1202 }
1203
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);
1208 }
1209
1210 /* Can't find valid MPP */
1211 DISPLAY_LOGD(eDebugOverlaySupported, "\tlayer %u: can't find valid MPP", index);
1212 mLayerInfos[index]->mCheckOverlayFlag |= eInsufficientMPP;
1213 return false;
1214
1215 }
1216
1217 void ExynosDisplay::configureHandle(private_handle_t *handle, size_t index,
1218 hwc_layer_1_t &layer, int fence_fd, decon_win_config &cfg)
1219 {
1220 int isOpaque = 0;
1221
1222 if (handle == NULL)
1223 return;
1224
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;
1229 isOpaque = 1;
1230 }
1231 #endif
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;
1236 uint32_t x, y;
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;
1243
1244 #ifdef USES_DECON_AFBC_DECODER
1245 cfg.compression = isCompressed(layer);
1246 #endif
1247
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",
1251 crop);
1252 x = 0;
1253 w -= crop;
1254 offset += crop * bpp / 8;
1255 } else {
1256 x = displayFrame.left;
1257 }
1258
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",
1262 crop);
1263 w -= crop;
1264 }
1265
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",
1269 crop);
1270 y = 0;
1271 h -= crop;
1272 offset += handle->stride * crop * bpp / 8;
1273 } else {
1274 y = displayFrame.top;
1275 }
1276
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",
1280 crop);
1281 h -= crop;
1282 }
1283
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;
1289 } else {
1290 cfg.state = cfg.DECON_WIN_STATE_BUFFER;
1291 cfg.idma_type = (decon_idma_type)mLayerInfos[index]->mDmaType;
1292 }
1293 cfg.dst.x = x;
1294 cfg.dst.y = y;
1295 cfg.dst.w = w;
1296 cfg.dst.h = h;
1297 cfg.dst.f_w = mXres;
1298 cfg.dst.f_h = mYres;
1299 cfg.format = halFormatToS3CFormat(handle->format);
1300
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);
1308 if (metaData)
1309 interlacedType = *(int *)metaData;
1310 else
1311 interlacedType = -1;
1312
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;
1317 }
1318 if (metaData)
1319 munmap(metaData, 64);
1320 }
1321 }
1322
1323 cfg.src.x = (int)sourceCrop.left;
1324 cfg.src.y = (int)sourceCrop.top;
1325
1326 if (cfg.src.x < 0)
1327 cfg.src.x = 0;
1328 if (cfg.src.y < 0)
1329 cfg.src.y = 0;
1330
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));
1338
1339 cfg.src.x = ALIGN((unsigned int)sourceCrop.left, internalMPP->getSrcXOffsetAlign(layer));
1340 cfg.src.y = ALIGN((unsigned int)sourceCrop.top, internalMPP->getSrcYOffsetAlign(layer));
1341 }
1342
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;
1349
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));
1357 }
1358
1359 if (isSrcCropFloat(layer.sourceCropf))
1360 {
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;
1370 } else {
1371 if (externalMPP == NULL)
1372 ALOGE("float sourceCrop should be handled by MPP");
1373 }
1374 #if 0
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);
1379 #endif
1380 }
1381
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;
1387 }
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;
1391
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)
1398 cfg.src.w /= 2;
1399 else if (S3DFormat == S3D_TB)
1400 cfg.src.h /= 2;
1401 }
1402 }
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;
1407
1408 /* opaque region coordinates is on screen */
1409 //getLayerRegion(layer, cfg.covered_opaque_area, eCoveredOpaqueRegion);
1410
1411 if (isOpaque && (handle->format == HAL_PIXEL_FORMAT_RGBX_8888)) {
1412 handle->format = HAL_PIXEL_FORMAT_RGBA_8888;
1413 isOpaque = 0;
1414 }
1415 }
1416
1417 void ExynosDisplay::configureOverlay(hwc_layer_1_t *layer, size_t index, decon_win_config &cfg)
1418 {
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;
1423 cfg.dst.x = 0;
1424 cfg.dst.y = 0;
1425 cfg.dst.w = this->mXres;
1426 cfg.dst.h = this->mYres;
1427 return;
1428 }
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);
1440 } else {
1441 getIDMAMinSize(*layer, &minCropWidth, &minCropHeight);
1442 }
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;
1446 #else
1447 int32_t minLeftPosition = 0;
1448 int32_t maxRightPosition = mXres;
1449 #endif
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;
1458
1459 if ((WIDTH(mFbUpdateRegion) % cropWidthAlign) != 0) {
1460 mFbUpdateRegion.left = ALIGN_DOWN(mFbUpdateRegion.left, cropWidthAlign);
1461 mFbUpdateRegion.right = ALIGN_UP(mFbUpdateRegion.right, cropWidthAlign);
1462 }
1463 if (WIDTH(mFbUpdateRegion) < minCropWidth) {
1464 #if defined(USES_DUAL_DISPLAY)
1465 if (mFbUpdateRegion.left + minCropWidth <= maxRightPosition)
1466 mFbUpdateRegion.right = mFbUpdateRegion.left + minCropWidth;
1467 else
1468 mFbUpdateRegion.left = mFbUpdateRegion.right - minCropWidth;
1469 #else
1470 if (mFbUpdateRegion.left + minCropWidth <= mXres)
1471 mFbUpdateRegion.right = mFbUpdateRegion.left + minCropWidth;
1472 else
1473 mFbUpdateRegion.left = mFbUpdateRegion.right - minCropWidth;
1474 #endif
1475 }
1476 if (HEIGHT(mFbUpdateRegion) < minCropHeight) {
1477 if (mFbUpdateRegion.top + minCropHeight <= mYres)
1478 mFbUpdateRegion.bottom = mFbUpdateRegion.top + minCropHeight;
1479 else
1480 mFbUpdateRegion.top = mFbUpdateRegion.bottom - minCropHeight;
1481 }
1482
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);
1489 } else {
1490 layer->sourceCropf.left = (double)mFbUpdateRegion.left;
1491 layer->sourceCropf.right = (double)mFbUpdateRegion.right;
1492 }
1493 #else
1494 layer->sourceCropf.left = (double)mFbUpdateRegion.left;
1495 layer->sourceCropf.right = (double)mFbUpdateRegion.right;
1496 #endif
1497 layer->sourceCropf.top = (double)mFbUpdateRegion.top;
1498 layer->sourceCropf.bottom = (double)mFbUpdateRegion.bottom;
1499 } else {
1500 mFbUpdateRegion = layer->displayFrame;
1501 }
1502 }
1503 configureHandle(handle, index, *layer, layer->acquireFenceFd, cfg);
1504 layer->sourceCropf = originalCrop;
1505 }
1506
1507 int ExynosDisplay::handleWindowUpdate(hwc_display_contents_1_t __unused *contents,
1508 struct decon_win_config __unused *config)
1509 {
1510 int layerIdx = -1;
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;
1520 int xAlign = 0;
1521 int wAlign = 0;
1522 int yAlign = 0;
1523 int hAlign = 0;
1524
1525 #if defined(USES_DUAL_DISPLAY)
1526 return -eWindowUpdateDisabled;
1527 #endif
1528
1529
1530 char value[PROPERTY_VALUE_MAX];
1531 property_get("debug.hwc.winupdate", value, "1");
1532
1533 if (!(!strcmp(value, "1") || !strcmp(value, "true")))
1534 return -eWindowUpdateDisabled;
1535
1536 if (DECON_WIN_UPDATE_IDX < 0)
1537 return -eWindowUpdateInvalidIndex;
1538 winUpdateInfoIdx = DECON_WIN_UPDATE_IDX;
1539
1540 if (contents->flags & HWC_GEOMETRY_CHANGED)
1541 return -eWindowUpdateGeometryChanged;
1542
1543 if (mPanelType == PANEL_DSC) {
1544 xAlign = this->mXres / mDSCHSliceNum;
1545 wAlign = this->mXres / mDSCHSliceNum;
1546 yAlign = mDSCYSliceSize;
1547 hAlign = mDSCYSliceSize;
1548 } else {
1549 xAlign = WINUPDATE_X_ALIGNMENT;
1550 wAlign = WINUPDATE_W_ALIGNMENT;
1551 yAlign = 1;
1552 hAlign = 1;
1553 }
1554
1555 for (size_t i = 0; i < contents->numHwLayers; i++) {
1556 if (contents->hwLayers[i].compositionType == HWC_FRAMEBUFFER)
1557 continue;
1558
1559 if (!mFbNeeded && contents->hwLayers[i].compositionType == HWC_FRAMEBUFFER_TARGET)
1560 continue;
1561 int32_t windowIndex = mLayerInfos[i]->mWindowIndex;
1562 if ((windowIndex < 0) || (windowIndex > MAX_DECON_WIN))
1563 return -eWindowUpdateInvalidConfig;
1564
1565 if (config[windowIndex].state != config[windowIndex].DECON_WIN_STATE_DISABLED) {
1566 totalWinCnt++;
1567
1568 if (winConfigChanged(&config[windowIndex], &this->mLastConfigData.config[windowIndex])) {
1569 updatedWinCnt++;
1570
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;
1575
1576 if (hwcHasApiVersion((hwc_composer_device_1_t*)mHwc, HWC_DEVICE_API_VERSION_1_5))
1577 {
1578 private_handle_t *handle = NULL;
1579 hwc_rect damageRect = {0, 0, 0, 0};
1580 hwc_layer_1_t &layer = contents->hwLayers[i];
1581 if (layer.handle)
1582 handle = private_handle_t::dynamicCast(layer.handle);
1583 unsigned int damageRegionMod = getLayerRegion(layer, damageRect, eDamageRegion);
1584
1585 if (damageRegionMod == eDamageRegionSkip)
1586 continue;
1587
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);
1591
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);
1597
1598 }
1599 }
1600
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;
1605 }
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);
1609 }
1610 }
1611 }
1612 if (updatedWinCnt == 0)
1613 return -eWindowUpdateNotUpdated;
1614
1615 /* Alignment check */
1616 for (size_t i = 0; i < contents->numHwLayers; i++) {
1617 if (contents->hwLayers[i].compositionType == HWC_FRAMEBUFFER)
1618 continue;
1619
1620 if (!mFbNeeded && contents->hwLayers[i].compositionType == HWC_FRAMEBUFFER_TARGET)
1621 continue;
1622
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;
1628
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];
1633 if (layer.handle)
1634 handle = private_handle_t::dynamicCast(layer.handle);
1635 else
1636 return -eWindowUpdateInvalidConfig;
1637
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;
1645
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));
1655 } else {
1656 handle->format = originalFormat;
1657 layer.transform = originalTransform;
1658 return -eWindowUpdateInvalidConfig;
1659 }
1660 }
1661 handle->format = originalFormat;
1662 layer.transform = originalTransform;
1663 }
1664 }
1665
1666 updateRect.left = ALIGN_DOWN(updateRect.left, xAlign);
1667 updateRect.top = ALIGN_DOWN(updateRect.top, yAlign);
1668
1669 if (HEIGHT(updateRect) < WINUPDATE_MIN_HEIGHT) {
1670 if (updateRect.top + WINUPDATE_MIN_HEIGHT <= mYres)
1671 updateRect.bottom = updateRect.top + WINUPDATE_MIN_HEIGHT;
1672 else
1673 updateRect.top = updateRect.bottom - WINUPDATE_MIN_HEIGHT;
1674 }
1675
1676 if ((100 * (WIDTH(updateRect) * HEIGHT(updateRect)) / (this->mXres * this->mYres)) > WINUPDATE_THRESHOLD)
1677 return -eWindowUpdateOverThreshold;
1678
1679 alignAdjustment = getLCM(alignAdjustment, xAlign);
1680 alignAdjustment = getLCM(alignAdjustment, wAlign);
1681
1682 while (1) {
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;
1690
1691 for (size_t i = 0; i < contents->numHwLayers; i++) {
1692 if (contents->hwLayers[i].compositionType == HWC_FRAMEBUFFER)
1693 continue;
1694 if (!mFbNeeded && contents->hwLayers[i].compositionType == HWC_FRAMEBUFFER_TARGET)
1695 continue;
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)
1700 bitsPerPixel = 16;
1701 else if (fmt == DECON_PIXEL_FORMAT_NV12 || fmt == DECON_PIXEL_FORMAT_NV21 ||
1702 fmt == DECON_PIXEL_FORMAT_NV12M || fmt == DECON_PIXEL_FORMAT_NV21M)
1703 bitsPerPixel = 12;
1704 else
1705 bitsPerPixel = 32;
1706
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;
1711
1712 intersectionWidth = WIDTH(intersection(currentRect, updateRect));
1713
1714 DISPLAY_LOGD(eDebugWindowUpdate, "[WIN_UPDATE] win[%d] left(%d) right(%d) intersection(%d)", windowIndex, currentRect.left, currentRect.right, intersectionWidth);
1715
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;
1722 break;
1723
1724 }
1725 } else {
1726 #endif
1727 DISPLAY_LOGD(eDebugWindowUpdate, "[WIN_UPDATE] win[%d] insufficient burst length (%d)*(%d) < %d", windowIndex, intersectionWidth, bitsPerPixel, BURSTLEN_BYTES);
1728 burstLengthCheckDone = false;
1729 break;
1730 #ifdef USE_DRM_BURST_LEN
1731 }
1732 #endif
1733 }
1734 }
1735 }
1736
1737 if (burstLengthCheckDone)
1738 break;
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;
1744 } else {
1745 DISPLAY_LOGD(eDebugWindowUpdate, "[WIN_UPDATE] Error during update width adjustment");
1746 return -eWindowUpdateAdjustmentFail;
1747 }
1748 }
1749
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);
1755
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);
1760
1761 /* Final check */
1762 for (size_t i = 0; i < contents->numHwLayers; i++) {
1763 if (contents->hwLayers[i].compositionType == HWC_FRAMEBUFFER)
1764 continue;
1765
1766 if (!mFbNeeded && contents->hwLayers[i].compositionType == HWC_FRAMEBUFFER_TARGET)
1767 continue;
1768
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;
1774
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];
1780 if (layer.handle)
1781 handle = private_handle_t::dynamicCast(layer.handle);
1782 else
1783 return -eWindowUpdateInvalidConfig;
1784
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;
1800 }
1801 }
1802 handle->format = originalFormat;
1803 layer.transform = originalTransform;
1804 }
1805 }
1806
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);
1809
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));
1817 #endif
1818 }
1819 }
1820
1821 return 1;
1822 }
1823
1824 void ExynosDisplay::getLayerRegion(hwc_layer_1_t &layer __unused, decon_win_rect &rect_area, uint32_t regionType)
1825 {
1826 hwc_rect_t const *hwcRects = NULL;
1827 unsigned int numRects = 0;
1828 switch (regionType) {
1829 #if 0
1830 case eTransparentRegion:
1831 hwcRects = layer.transparentRegion.rects;
1832 numRects = layer.transparentRegion.numRects;
1833 break;
1834 case eCoveredOpaqueRegion:
1835 hwcRects = layer.coveredOpaqueRegion.rects;
1836 numRects = layer.coveredOpaqueRegion.numRects;
1837 break;
1838 #endif
1839 default:
1840 ALOGE("%s:: Invalid regionType (%d)", __func__, regionType);
1841 return;
1842 }
1843
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++) {
1847 hwc_rect_t rect;
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);
1860 }
1861 }
1862 }
1863 }
1864
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;
1868
1869 switch (regionType) {
1870 case eDamageRegion:
1871 hwcRects = layer.surfaceDamage.rects;
1872 numRects = layer.surfaceDamage.numRects;
1873 break;
1874 default:
1875 ALOGE("%s:: Invalid regionType (%d)", __func__, regionType);
1876 return eDamageRegionError;
1877 }
1878
1879 if ((numRects == 0) || (hwcRects == NULL))
1880 return eDamageRegionFull;
1881
1882 if ((numRects == 1) && (hwcRects[0].left == 0) && (hwcRects[0].top == 0) &&
1883 (hwcRects[0].right == 0) && (hwcRects[0].bottom == 0))
1884 return eDamageRegionSkip;
1885
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++) {
1891 hwc_rect_t rect;
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);
1899 }
1900 }
1901
1902 return eDamageRegionPartial;
1903 }
1904
1905 bool ExynosDisplay::getPreviousDRMDMA(int *dma)
1906 {
1907 *dma = -1;
1908
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;
1912 return true;
1913 }
1914 }
1915 return false;
1916 }
1917
1918 int ExynosDisplay::winconfigIoctl(decon_win_config_data *win_data)
1919 {
1920 ATRACE_CALL();
1921 return ioctl(this->mDisplayFd, S3CFB_WIN_CONFIG, win_data);
1922 }
1923
1924 int ExynosDisplay::postFrame(hwc_display_contents_1_t* contents)
1925 {
1926 ATRACE_CALL();
1927
1928 if (mWinData == NULL) {
1929 DISPLAY_LOGE("mWinData is not valid");
1930 return -1;
1931 }
1932 struct decon_win_config *config = mWinData->config;
1933
1934 int tot_ovly_wins = 0;
1935 uint32_t rectCount = 0;
1936 int ret = 0;
1937
1938 memset(mLastHandles, 0, sizeof(mLastHandles));
1939 memset(mLastMPPMap, 0, sizeof(mLastMPPMap));
1940 memset(config, 0, sizeof(mWinData->config));
1941
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;
1946 }
1947 for (size_t i = 0; i < contents->numHwLayers; i++) {
1948 hwc_layer_1_t &layer = contents->hwLayers[i];
1949 if (layer.handle) {
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++];
1954 }
1955 }
1956
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;
1961 if (layer.handle)
1962 handle = private_handle_t::dynamicCast(layer.handle);
1963
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;
1971
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);
1976 result.clear();
1977 dumpLayerInfo(result);
1978 }
1979 continue;
1980 }
1981
1982 if ((mVirtualOverlayFlag == true) && (layer.compositionType == HWC_OVERLAY) &&
1983 handle && (getDrmMode(handle->flags) == NO_DRM) &&
1984 (mFirstFb <= i) && (i <= mLastFb))
1985 continue;
1986
1987 if (((layer.compositionType == HWC_OVERLAY) ||
1988 (mFbNeeded == true && layer.compositionType == HWC_FRAMEBUFFER_TARGET))) {
1989 mLastHandles[window_index] = layer.handle;
1990
1991 if (handle && (getDrmMode(handle->flags) == SECURE_DRM))
1992 config[window_index].protection = 1;
1993 else
1994 config[window_index].protection = 0;
1995
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;
1999 }
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)
2004 continue;
2005 } else {
2006 configureOverlay(&layer, i, config[window_index]);
2007 }
2008 }
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;
2012 }
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;
2018 }
2019 }
2020
2021 if (this->mVirtualOverlayFlag) {
2022 handleStaticLayers(contents, *mWinData, tot_ovly_wins);
2023 }
2024
2025 if ((ret = handleWindowUpdate(contents, config)) < 0)
2026 DISPLAY_LOGD(eDebugWindowUpdate, "[WIN_UPDATE] UpdateRegion is FullScreen, ret(%d)", ret);
2027
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;
2034 break;
2035 }
2036 }
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];
2040 int8_t index = 0;
2041 if (indexLastConfig == NUM_HW_WINDOWS) {
2042 DISPLAY_LOGE("primaryDisplay last config index is not valid(primaryLastIndex: %d)",
2043 indexLastConfig);
2044 break;
2045 }
2046 if (i == (NUM_HW_WINDOWS - 1))
2047 index = i;
2048 else
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);
2056 } else {
2057 memcpy(&config[index],&secondary_config, sizeof(struct decon_win_config));
2058 mLastHandles[index] = mHwc->secondaryDisplay->mLastHandles[i];
2059 }
2060 }
2061 }
2062 }
2063 }
2064
2065 if (mType != EXYNOS_SECONDARY_DISPLAY)
2066 {
2067 #endif
2068 for (size_t i = 0; i <= NUM_HW_WINDOWS; i++) {
2069 DISPLAY_LOGD(eDebugWinConfig, "window %u configuration:", i);
2070 dumpConfig(config[i]);
2071 }
2072
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);
2079 }
2080 result.clear();
2081 dumpContents(result, contents);
2082 result.clear();
2083 dumpLayerInfo(result);
2084 }
2085
2086 if (checkConfigChanged(*mWinData, mLastConfigData) == false) {
2087 ret = 0;
2088 } else {
2089 ret = winconfigIoctl(mWinData);
2090 if (ret < 0) {
2091 DISPLAY_LOGE("ioctl S3CFB_WIN_CONFIG failed: %s", strerror(errno));
2092 } else {
2093 ret = mWinData->fence;
2094 memcpy(&(this->mLastConfigData), mWinData, sizeof(*mWinData));
2095 }
2096 }
2097
2098 /*
2099 * Acquire fence of all of OVERLAY layers(including layers for secondary LCD)
2100 * should be closed even if WIN_CONFIG is skipped
2101 */
2102 for (size_t i = 0; i < NUM_HW_WINDOWS; i++) {
2103 if (config[i].fence_fd != -1)
2104 close(config[i].fence_fd);
2105 }
2106 #if defined(USES_DUAL_DISPLAY)
2107 } else {
2108 memcpy(&(this->mLastConfigData), mWinData, sizeof(*mWinData));
2109 }
2110 #endif
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;
2117 }
2118
2119 if (!this->mVirtualOverlayFlag && (ret >= 0))
2120 this->mLastFbWindow = mFbWindow;
2121
2122 return ret;
2123 }
2124
2125 void ExynosDisplay::skipStaticLayers(hwc_display_contents_1_t* contents)
2126 {
2127 mVirtualOverlayFlag = 0;
2128 int fbIndex = contents->numHwLayers - 1;
2129
2130 if (!mHwc->hwc_ctrl.skip_static_layer_mode)
2131 return;
2132
2133 if (mBypassSkipStaticLayer)
2134 return;
2135
2136 if (contents->flags & HWC_GEOMETRY_CHANGED) {
2137 mSkipStaticInitFlag = false;
2138 return;
2139 }
2140
2141 if (!mFbNeeded || ((mLastFb - mFirstFb + 1) > NUM_VIRT_OVER)) {
2142 mSkipStaticInitFlag = false;
2143 return;
2144 }
2145
2146 if (mSkipStaticInitFlag) {
2147 if (mNumStaticLayers != (mLastFb - mFirstFb + 1)) {
2148 mSkipStaticInitFlag = false;
2149 return;
2150 }
2151
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;
2156 return;
2157 }
2158 }
2159
2160 if ((mLastFbWindow >= NUM_HW_WINDOWS) || (fbIndex < 0)) {
2161 mSkipStaticInitFlag = false;
2162 DISPLAY_LOGE("skipStaticLayers:: invalid mLastFbWindow(%d), fbIndex(%d)", mLastFbWindow, fbIndex);
2163 return;
2164 }
2165 /* DMA mapping is changed */
2166 if (mLastConfigData.config[mLastFbWindow].idma_type != mLayerInfos[fbIndex]->mDmaType) {
2167 mSkipStaticInitFlag = false;
2168 return;
2169 }
2170
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;
2178 }
2179 }
2180 mLastFbWindow = mFbWindow;
2181 return;
2182 }
2183
2184 mSkipStaticInitFlag = true;
2185 for (size_t i = 0; i < NUM_VIRT_OVER; i++)
2186 mLastLayerHandles[i] = 0;
2187
2188 for (size_t i = mFirstFb; i <= mLastFb; i++) {
2189 hwc_layer_1_t &layer = contents->hwLayers[i];
2190 mLastLayerHandles[i - mFirstFb] = layer.handle;
2191 }
2192 mNumStaticLayers = (mLastFb - mFirstFb + 1);
2193
2194 return;
2195 }
2196
2197 void ExynosDisplay::dumpMPPs(android::String8& result)
2198 {
2199 result.appendFormat("displayType(%d)\n", mType);
2200 result.appendFormat("Internal MPPs number: %zu\n", mInternalMPPs.size());
2201 result.append(
2202 " mType | mIndex | mState \n"
2203 "-------+--------+-----------\n");
2204 // 5____ | 6_____ | 9________ \n
2205
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);
2210 }
2211
2212 result.append("\n");
2213 result.appendFormat("External MPPs number: %zu\n", mExternalMPPs.size());
2214 result.append(
2215 " mType | mIndex | mState \n"
2216 "-------+--------+-----------\n");
2217 // 5____ | 6_____ | 9________ \n
2218
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);
2223 }
2224 }
2225
2226 void ExynosDisplay::preAssignFbTarget(hwc_display_contents_1_t *contents, bool assign)
2227 {
2228 ExynosMPPModule* supportedInternalMPP = NULL;
2229 ExynosMPPModule* supportedExternalMPP = NULL;
2230
2231 int fbIndex = contents->numHwLayers - 1;
2232 hwc_layer_1_t &layer = contents->hwLayers[fbIndex];
2233 mFbPreAssigned = false;
2234
2235 if (!assign)
2236 return;
2237
2238 if (layer.compositionType != HWC_FRAMEBUFFER_TARGET) {
2239 ALOGE("preAssignFbTarget: FRAMEBUFFER_TARGET is not set properly");
2240 return;
2241 }
2242
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);
2252 }
2253 }
2254 mFbPreAssigned = true;
2255 } else {
2256 ALOGE("preAssignFbTarget: preassigning FB failed");
2257 return;
2258 }
2259 }
2260
2261 void ExynosDisplay::determineYuvOverlay(hwc_display_contents_1_t *contents)
2262 {
2263 mYuvLayers = 0;
2264 bool useVPPOverlayFlag = false, hasDrmLayer = mHasDrmSurface;
2265 uint32_t rectCount = 0;
2266 int drmLayerIndex = mForceOverlayLayerIndex;
2267 size_t i;
2268 mForceOverlayLayerIndex = -1;
2269 mHasDrmSurface = false;
2270
2271 for (size_t j = 0; j < contents->numHwLayers; j++) {
2272 i = hasDrmLayer ? ((j + drmLayerIndex) % contents->numHwLayers) : j;
2273
2274 ExynosMPPModule* supportedInternalMPP = NULL;
2275 ExynosMPPModule* supportedExternalMPP = NULL;
2276 hwc_layer_1_t &layer = contents->hwLayers[i];
2277 useVPPOverlayFlag = false;
2278 if (layer.handle) {
2279 private_handle_t *handle = private_handle_t::dynamicCast(layer.handle);
2280
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;
2285 continue;
2286 } else
2287 layer.flags &= ~HWC_SKIP_RENDERING;
2288 }
2289
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;
2296 continue;
2297 }
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);
2303
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);
2309
2310 if (handle->fd2 >= 0) {
2311 metaData = mmap(0, 64, PROT_READ|PROT_WRITE, MAP_SHARED, handle->fd2, 0);
2312 if (metaData)
2313 interlacedType = *(int *)metaData;
2314 else
2315 interlacedType = -1;
2316 }
2317
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;
2322 }
2323 }
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;
2327 }
2328 mBackUpFrect.push(layer.sourceCropf);
2329
2330 if (metaData)
2331 munmap(metaData, 64);
2332 }
2333
2334 if (isOverlaySupported(contents->hwLayers[i], i, useVPPOverlayFlag, &supportedInternalMPP, &supportedExternalMPP)) {
2335 this->mYuvLayers++;
2336 if (this->mHasDrmSurface == false) {
2337 /* Assign MPP */
2338 if (supportedExternalMPP != NULL)
2339 supportedExternalMPP->mState = MPP_STATE_ASSIGNED;
2340 if (supportedInternalMPP != NULL)
2341 supportedInternalMPP->mState = MPP_STATE_ASSIGNED;
2342
2343 mForceOverlayLayerIndex = i;
2344 layer.compositionType = HWC_OVERLAY;
2345 mLayerInfos[i]->mExternalMPP = supportedExternalMPP;
2346 mLayerInfos[i]->mInternalMPP = supportedInternalMPP;
2347 mLayerInfos[i]->compositionType = layer.compositionType;
2348
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));
2356 }
2357
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));
2365 }
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));
2371 }
2372 }
2373 }
2374 } else {
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;
2380 }
2381 }
2382 }
2383
2384 if (getDrmMode(handle->flags) != NO_DRM) {
2385 this->mHasDrmSurface = true;
2386 mForceOverlayLayerIndex = i;
2387 }
2388 }
2389 if (layer.handle) {
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++];
2394 }
2395 }
2396 }
2397
2398 void ExynosDisplay::determineSupportedOverlays(hwc_display_contents_1_t *contents)
2399 {
2400 bool videoLayer = false;
2401
2402 mFbNeeded = false;
2403 mFirstFb = ~0;
2404 mLastFb = 0;
2405 uint32_t rectCount = 0;
2406
2407 // find unsupported overlays
2408 for (size_t i = 0; i < contents->numHwLayers; i++) {
2409 hwc_layer_1_t &layer = contents->hwLayers[i];
2410
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;
2415 continue;
2416 }
2417
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;
2422 continue;
2423 }
2424
2425 if (layer.flags & HWC_SKIP_RENDERING) {
2426 layer.compositionType = HWC_OVERLAY;
2427 mLayerInfos[i]->compositionType = layer.compositionType;
2428 continue;
2429 }
2430
2431 if (layer.handle) {
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++];
2436
2437 ExynosMPPModule* supportedInternalMPP = NULL;
2438 ExynosMPPModule* supportedExternalMPP = NULL;
2439
2440 if ((int)get_yuv_planes(halFormatToV4L2Format(handle->format)) > 0) {
2441 videoLayer = true;
2442 if (!mHwc->hdmi_hpd && mHwc->mS3DMode == S3D_MODE_READY)
2443 mHwc->mS3DMode = S3D_MODE_RUNNING;
2444 }
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,
2449 layer.blending,
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)
2460 continue;
2461
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;
2469 }
2470 if (supportedInternalMPP != NULL) {
2471 supportedInternalMPP->mState = MPP_STATE_ASSIGNED;
2472 mLayerInfos[i]->mInternalMPP = supportedInternalMPP;
2473 }
2474
2475 layer.compositionType = HWC_OVERLAY;
2476 mLayerInfos[i]->compositionType = layer.compositionType;
2477
2478 dumpLayer(eDebugOverlaySupported, &contents->hwLayers[i]);
2479 continue;
2480 } else {
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);
2484 if (mForceFb)
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;
2490 }
2491 } else {
2492 mLayerInfos[i]->mCheckOverlayFlag |= eInvalidHandle;
2493 }
2494
2495 if (!mFbNeeded) {
2496 mFirstFb = i;
2497 mFbNeeded = true;
2498 }
2499 mLastFb = i;
2500 layer.compositionType = HWC_FRAMEBUFFER;
2501 mLayerInfos[i]->compositionType = layer.compositionType;
2502
2503 dumpLayer(eDebugOverlaySupported, &contents->hwLayers[i]);
2504 }
2505
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) {
2513 if (i == 0) {
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);
2524 mFbNeeded = true;
2525 break;
2526 }
2527 }
2528 } else {
2529 // if one of the bottom layer is HWC_FRAMEBUFFER type, no need to force the alpha layer to FRAMEBUFFER type.
2530 break;
2531 }
2532 }
2533 mFirstFb = min(mFirstFb, (size_t)NUM_HW_WINDOWS-1);
2534 // can't composite overlays sandwiched between framebuffers
2535 if (mFbNeeded) {
2536 private_handle_t *handle = NULL;
2537 for (size_t i = mFirstFb; i < mLastFb; i++) {
2538 if (contents->hwLayers[i].flags & HWC_SKIP_RENDERING)
2539 continue;
2540
2541 hwc_layer_1_t &layer = contents->hwLayers[i];
2542 handle = NULL;
2543 if (layer.handle)
2544 handle = private_handle_t::dynamicCast(layer.handle);
2545 if (handle && getDrmMode(handle->flags) != NO_DRM) {
2546 layer.hints = HWC_HINT_CLEAR_FB;
2547 } else {
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;
2554 }
2555 if (mLayerInfos[i]->mInternalMPP != NULL) {
2556 mLayerInfos[i]->mInternalMPP->mState = MPP_STATE_FREE;
2557 mLayerInfos[i]->mInternalMPP = NULL;
2558 }
2559 }
2560 }
2561 }
2562 }
2563
2564 void ExynosDisplay::determineBandwidthSupport(hwc_display_contents_1_t *contents)
2565 {
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.)
2571 bool changed;
2572 this->mBypassSkipStaticLayer = false;
2573 unsigned int cannotComposeFlag = 0;
2574 int retry = 0;
2575 int fbIndex = contents->numHwLayers - 1;
2576
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;
2585
2586 do {
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;
2594 bool ret = 0;
2595
2596 for (size_t i = 0; i < mInternalMPPs.size(); i++) {
2597 if (mInternalMPPs[i]->mState != MPP_STATE_TRANSITION &&
2598 (!mHasDrmSurface ||
2599 (mLayerInfos[mForceOverlayLayerIndex]->mInternalMPP != mInternalMPPs[i]))) {
2600 mInternalMPPs[i]->mState = MPP_STATE_FREE;
2601 }
2602 }
2603
2604 for (size_t i = 0; i < mExternalMPPs.size(); i++) {
2605 if (mExternalMPPs[i]->mState != MPP_STATE_TRANSITION &&
2606 (!mHasDrmSurface ||
2607 (mLayerInfos[mForceOverlayLayerIndex]->mExternalMPP != mExternalMPPs[i]))) {
2608 mExternalMPPs[i]->mState = MPP_STATE_FREE;
2609 }
2610 }
2611
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;
2616 }
2617 }
2618
2619 changed = false;
2620 mMPPLayers = 0;
2621
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;
2636 directFbNum++;
2637 } else {
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) {
2648 #else
2649 if (mLayerInfos[fbIndex]->mDmaType >= IDMA_MAX) {
2650 #endif
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;
2654 }
2655 win_idx = (win_idx == mFirstFb) ? (win_idx + 1) : win_idx;
2656 } else {
2657 ALOGE("VPP should be assigned to FramebufferTarget but it was failed ret(%d)", ret);
2658 }
2659 }
2660 mHwc->totPixels += mXres * mYres;
2661 } else {
2662 windows_left = min(mAllowedOverlays, mHwc->hwc_ctrl.max_num_ovly);
2663 }
2664
2665 DISPLAY_LOGD(eDebugResourceAssigning, "determineBandwidthSupport:: retry(%d), mAllowedOverlays(%d), windows_left(%d), win_idx(%d)",
2666 retry, mAllowedOverlays, windows_left, win_idx);
2667
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;
2672
2673 if (layer.flags & HWC_SKIP_RENDERING)
2674 continue;
2675
2676 if ((layer.flags & HWC_SKIP_LAYER) ||
2677 (layer.compositionType == HWC_FRAMEBUFFER_TARGET))
2678 continue;
2679
2680 if (!layer.planeAlpha)
2681 continue;
2682
2683 if (layer.handle)
2684 handle = private_handle_t::dynamicCast(layer.handle);
2685 else
2686 continue;
2687
2688 // we've already accounted for the framebuffer above
2689 if (layer.compositionType == HWC_FRAMEBUFFER)
2690 continue;
2691
2692 // only layer 0 can be HWC_BACKGROUND, so we can
2693 // unconditionally allow it without extra checks
2694 if (layer.compositionType == HWC_BACKGROUND) {
2695 windows_left--;
2696 continue;
2697 }
2698
2699 cannotComposeFlag = 0;
2700 bool can_compose = windows_left && (win_idx < NUM_HW_WINDOWS);
2701 if (mUseSecureDMA && !isCompressed(layer) && isTopLayer)
2702 can_compose = true;
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;
2708 }
2709
2710 /* mInternalMPP, mExternalMPP could be set by determineYuvOverlay */
2711 supportedInternalMPP = mLayerInfos[i]->mInternalMPP;
2712 supportedExternalMPP = mLayerInfos[i]->mExternalMPP;
2713
2714 if (can_compose && !isProcessingRequired(layer) && isOverlaySupportedByIDMA(layer, i) &&
2715 (directFbNum < mInternalDMAs.size() || (mUseSecureDMA && isTopLayer))) {
2716 if (directFbNum < mInternalDMAs.size())
2717 directFbNum++;
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);
2729 }
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];
2738 directFbNum++;
2739 } else {
2740 mLayerInfos[i]->mDmaType = IDMA_SECURE;
2741 }
2742 }
2743 }
2744 mMPPLayers++;
2745 if (!isFormatRgb(handle->format))
2746 videoOverlays++;
2747 } else {
2748 DISPLAY_LOGD(eDebugResourceAssigning, "layer(%d) is changed to FRAMEBUFFER", i);
2749 can_compose = false;
2750 }
2751
2752 if (!can_compose) {
2753 size_t changed_index = i;
2754 hwc_layer_1_t *layer_for_gles = &contents->hwLayers[i];
2755 if (getDrmMode(handle->flags) != NO_DRM) {
2756 int j = 0;
2757 for (j = i - 1; j >= 0 ; j--) {
2758 layer_for_gles = &contents->hwLayers[j];
2759 if (layer_for_gles->compositionType == HWC_OVERLAY) {
2760 changed_index = j;
2761 break;
2762 }
2763 }
2764 if (j < 0) {
2765 mFirstFb = 0;
2766 changed_index = 0;
2767 layer_for_gles = &contents->hwLayers[changed_index];
2768 }
2769 }
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;
2779 if (!mFbNeeded) {
2780 mFirstFb = mLastFb = changed_index;
2781 mFbNeeded = true;
2782 mHwc->totPixels += mXres * mYres;
2783 }
2784 else {
2785 mFirstFb = min(changed_index, mFirstFb);
2786 mLastFb = max(changed_index, mLastFb);
2787 }
2788 changed = true;
2789 mFirstFb = min(mFirstFb, (size_t)NUM_HW_WINDOWS-1);
2790 break;
2791 } else {
2792 mHwc->totPixels += WIDTH(layer.displayFrame) * HEIGHT(layer.displayFrame);
2793 }
2794
2795 if ((mUseSecureDMA == false) || (isTopLayer == false)) {
2796 win_idx++;
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));
2801 windows_left--;
2802 }
2803 }
2804
2805 if (changed)
2806 for (size_t i = mFirstFb; i < mLastFb; i++) {
2807 hwc_layer_1_t &layer = contents->hwLayers[i];
2808 private_handle_t *handle = NULL;
2809 if (layer.handle)
2810 handle = private_handle_t::dynamicCast(layer.handle);
2811 if (handle && getDrmMode(handle->flags) != NO_DRM) {
2812 layer.hints = HWC_HINT_CLEAR_FB;
2813 } else {
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))
2824 videoOverlays--;
2825 }
2826 }
2827 if (handleTotalBandwidthOverload(contents))
2828 changed = true;
2829 retry++;
2830
2831 if (retry > 100) {
2832 DISPLAY_LOGE("%s", "retry 100, can't allocate vpp, dump error state");
2833 android::String8 result;
2834 result.clear();
2835 dumpLayerInfo(result);
2836 DISPLAY_LOGE("%s", result.string());
2837 break;
2838 }
2839 } while(changed);
2840
2841 uint32_t rectCount = 0;
2842 for (size_t i = 0; i < contents->numHwLayers; i++) {
2843 hwc_layer_1_t &layer = contents->hwLayers[i];
2844 if (layer.handle) {
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++];
2849 }
2850 }
2851
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);
2856 }
2857
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);
2862 }
2863
2864 int minWidth = 0;
2865 #ifdef USE_DRM_BURST_LEN
2866 if (mHasDrmSurface)
2867 minWidth = DRM_BURSTLEN_BYTES * 8 / formatToBpp(HAL_PIXEL_FORMAT_RGBA_8888);
2868 else
2869 #endif
2870 minWidth = BURSTLEN_BYTES * 8 / formatToBpp(HAL_PIXEL_FORMAT_RGBA_8888);
2871
2872 int w = WIDTH(mFbUpdateRegion);
2873 if (w < minWidth) {
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;
2878 else
2879 mFbUpdateRegion.left = mFbUpdateRegion.right - minWidth;
2880 #else
2881 if (mFbUpdateRegion.left + minWidth <= mXres)
2882 mFbUpdateRegion.right = mFbUpdateRegion.left + minWidth;
2883 else
2884 mFbUpdateRegion.left = mFbUpdateRegion.right - minWidth;
2885 #endif
2886 }
2887 }
2888
2889 void ExynosDisplay::assignWindows(hwc_display_contents_1_t *contents)
2890 {
2891 unsigned int nextWindow = 0;
2892 unsigned int directFbNum = 0;
2893 bool isTopLayer = false;
2894
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];
2902 directFbNum++;
2903 } else {
2904 /* mDmaType was set by determineBandwidthSupport() */
2905 }
2906
2907 DISPLAY_LOGD(eDebugResourceAssigning, "assigning layer %u to DMA %u", contents->numHwLayers - 1, mLayerInfos[contents->numHwLayers - 1]->mDmaType);
2908 }
2909
2910 if (mFbNeeded && mUseSecureDMA && !isCompressed(fbLayer) && (mLastFb == (contents->numHwLayers - 2)))
2911 mFbWindow = NUM_HW_WINDOWS - 1;
2912 else
2913 mFbWindow = NO_FB_NEEDED;
2914
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;
2919
2920 if (mFbNeeded && (mFbWindow != NUM_HW_WINDOWS - 1)) {
2921 if (i == mLastFb) {
2922 mFbWindow = nextWindow;
2923 nextWindow++;
2924 continue;
2925 }
2926 }
2927
2928 if (layer.flags & HWC_SKIP_RENDERING)
2929 continue;
2930
2931 if (!layer.planeAlpha) {
2932 if (layer.acquireFenceFd >= 0)
2933 close(layer.acquireFenceFd);
2934 layer.acquireFenceFd = -1;
2935 layer.releaseFenceFd = -1;
2936 continue;
2937 }
2938
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);
2945 continue;
2946 }
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)))
2951 {
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;
2956 directFbNum++;
2957 } else {
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;
2961 }
2962 } else {
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);
2969 } else {
2970 /* Find unused DMA connected with VPP */
2971 for (size_t j = 0; j < mInternalMPPs.size(); j++ )
2972 {
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);
2980 break;
2981 }
2982 }
2983 }
2984 }
2985 if (mLayerInfos[i]->mExternalMPP != NULL)
2986 mLayerInfos[i]->mExternalMPP->setDisplay(this);
2987 }
2988 if (mLayerInfos[i]->mWindowIndex != NUM_HW_WINDOWS - 1)
2989 nextWindow++;
2990 }
2991 }
2992
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;
3000 }
3001 }
3002 }
3003 }
3004
3005 int ExynosDisplay::postMPPM2M(hwc_layer_1_t &layer, struct decon_win_config *config, int win_map, int index)
3006 {
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;
3014
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;
3021 return -1;
3022 }
3023
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;
3028
3029 bool bothMPPUsed = isBothMPPProcessingRequired(layer, &extMPPOutLayer);
3030 if (bothMPPUsed) {
3031 sourceCrop.right = extMPPOutLayer.displayFrame.right;
3032 sourceCrop.bottom = extMPPOutLayer.displayFrame.bottom;
3033 layer.displayFrame = extMPPOutLayer.displayFrame;
3034 }
3035
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;
3044 } else {
3045 exynosMPP->mS3DMode = S3D_NONE;
3046 }
3047 }
3048
3049 /* OFF_Screen to ON_Screen changes */
3050 if (getDrmMode(handle->flags) != NO_DRM)
3051 recalculateDisplayFrame(layer, mXres, mYres);
3052
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);
3063
3064 /* Restore displayFrame*/
3065 layer.displayFrame = originalDisplayFrame;
3066
3067 if (err < 0) {
3068 DISPLAY_LOGE("failed to configure MPP (type:%u, index:%u) for layer %u",
3069 exynosMPP->mType, exynosMPP->mIndex, index);
3070 return -1;
3071 }
3072
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;
3079
3080 /* ExtMPP out is the input of Decon
3081 * and Trsform was processed by ExtMPP
3082 */
3083 layer.sourceCropf = sourceCrop;
3084 layer.transform = 0;
3085 handle->format = dst_format;
3086 configureHandle(dst_handle, index, layer, fence, config[win_map]);
3087
3088 /* Restore sourceCropf and transform */
3089 layer.sourceCropf = originalCrop;
3090 layer.transform = originalTransform;
3091 handle->format = originalFormat;
3092 return 0;
3093 }
3094
3095 void ExynosDisplay::handleStaticLayers(hwc_display_contents_1_t *contents, struct decon_win_config_data &win_data, int __unused tot_ovly_wins)
3096 {
3097 int win_map = 0;
3098 if (mLastFbWindow >= NUM_HW_WINDOWS) {
3099 DISPLAY_LOGE("handleStaticLayers:: invalid mLastFbWindow(%d)", mLastFbWindow);
3100 return;
3101 }
3102 win_map = mLastFbWindow;
3103 DISPLAY_LOGD(eDebugSkipStaicLayer, "[USE] SKIP_STATIC_LAYER_COMP, mLastFbWindow(%d), win_map(%d)\n", mLastFbWindow, win_map);
3104
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;
3108
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)
3113 continue;
3114 else
3115 handle = private_handle_t::dynamicCast(layer.handle);
3116
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;
3124 }
3125 }
3126 }
3127
3128 bool ExynosDisplay::multipleRGBScaling(int format)
3129 {
3130 return isFormatRgb(format) &&
3131 mMPPLayers >= 1;
3132 }
3133
3134 bool ExynosDisplay::isProcessingRequired(hwc_layer_1_t &layer)
3135 {
3136 if (!layer.handle)
3137 return false;
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);
3143 }
3144
3145 bool ExynosDisplay::isBothMPPProcessingRequired(hwc_layer_1_t &layer)
3146 {
3147 bool needDoubleOperation = false;
3148 private_handle_t *srcHandle = NULL;
3149
3150 if (layer.handle == NULL)
3151 return false;
3152
3153 srcHandle = private_handle_t::dynamicCast(layer.handle);
3154 if ((mExternalMPPs.size() == 0) || (mInternalMPPs.size() == 0))
3155 return false;
3156
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);
3162 int dstW, dstH;
3163 if (rot90or270) {
3164 dstW = HEIGHT(layer.displayFrame);
3165 dstH = WIDTH(layer.displayFrame);
3166 } else {
3167 dstW = WIDTH(layer.displayFrame);
3168 dstH = HEIGHT(layer.displayFrame);
3169 }
3170 needDoubleOperation = ((dstW > srcW * maxUpscaleExt) && (dstW <= srcW * maxUpscaleExt * maxUpscaleInt)) ||
3171 ((dstH > srcH * maxUpscaleExt) && (dstH <= srcH * maxUpscaleExt * maxUpscaleInt));
3172
3173 int maxDownscaleExt = mExternalMPPs[0]->getMaxDownscale(layer);
3174
3175 needDoubleOperation |= ((dstW < srcW / maxDownscaleExt) && (dstW >= srcW / (maxDownscaleExt * maxDownscaleExt))) ||
3176 ((dstH < srcH / maxDownscaleExt) && (dstH >= srcH / (maxDownscaleExt * maxDownscaleExt)));
3177
3178 /*
3179 * Both VPP and MSC should be used if
3180 * MSC should be used for DRM contents
3181 */
3182 if (getDrmMode(srcHandle->flags) != NO_DRM) {
3183 bool supportVPP = false;
3184 for (size_t i = 0; i < mInternalMPPs.size(); i++ )
3185 {
3186 if (mInternalMPPs[i]->isProcessingSupported(layer, srcHandle->format) > 0) {
3187 supportVPP = true;
3188 break;
3189 }
3190 }
3191 if (supportVPP == false)
3192 needDoubleOperation |= true;
3193 }
3194
3195 /*
3196 * UHD case
3197 * Destination format should be RGB if dstW or dstH is not aligned.
3198 * VPP is not required at this time.
3199 */
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;
3206 }
3207
3208 return needDoubleOperation;
3209 }
3210
3211 bool ExynosDisplay::isBothMPPProcessingRequired(hwc_layer_1_t &layer, hwc_layer_1_t *extMPPOutLayer)
3212 {
3213 bool needDoubleOperation = false;
3214 if (layer.handle == NULL)
3215 return false;
3216
3217 private_handle_t *srcHandle = private_handle_t::dynamicCast(layer.handle);
3218 if ((mExternalMPPs.size() == 0) || (mInternalMPPs.size() == 0))
3219 return false;
3220
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);
3225 int dstW, dstH;
3226 if (rot90or270) {
3227 dstW = HEIGHT(layer.displayFrame);
3228 dstH = WIDTH(layer.displayFrame);
3229 } else {
3230 dstW = WIDTH(layer.displayFrame);
3231 dstH = HEIGHT(layer.displayFrame);
3232 }
3233
3234 int maxDownscaleExt = mExternalMPPs[0]->getMaxDownscale(layer);
3235 int maxDownscaleInt = mCheckIntMPP->getMaxDownscale(layer);
3236
3237 needDoubleOperation = isBothMPPProcessingRequired(layer);
3238
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;
3244
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));
3251 } else {
3252 extMPPOutLayer->displayFrame.right = dstW;
3253 }
3254
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));
3261 } else {
3262 extMPPOutLayer->displayFrame.bottom = dstH;
3263 }
3264
3265 if (rot90or270) {
3266 dstW = extMPPOutLayer->displayFrame.bottom;
3267 dstH = extMPPOutLayer->displayFrame.right;
3268 extMPPOutLayer->displayFrame.right = dstW;
3269 extMPPOutLayer->displayFrame.bottom = dstH;
3270 }
3271 }
3272
3273 return needDoubleOperation;
3274 }
3275
3276 bool ExynosDisplay::isSourceCropfSupported(hwc_layer_1_t layer __unused)
3277 {
3278 #if 0
3279 private_handle_t *handle = private_handle_t::dynamicCast(layer.handle);
3280 unsigned int bpp = formatToBpp(handle->format);
3281
3282 /* HACK: Disable overlay if the layer have float position or size */
3283 if ((isFormatRgb(handle->format) && (bpp == 32)) ||
3284 isFormatYUV420(handle->format))
3285 return true;
3286 #endif
3287
3288 return false;
3289 }
3290
3291 #if 0
3292 bool ExynosDisplay::checkConfigChanged(struct decon_win_config_data &lastConfigData, struct decon_win_config_data &newConfigData)
3293 {
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))
3310 return true;
3311 }
3312 return false;
3313 }
3314 #else
3315 bool ExynosDisplay::checkConfigChanged(struct decon_win_config_data &/*lastConfigData*/, struct decon_win_config_data &/*newConfigData*/)
3316 {
3317 /* Force this check to always return true, otherwise we have unreliable retire fences */
3318 return true;
3319 }
3320 #endif
3321
3322 void ExynosDisplay::removeIDMA(decon_idma_type idma)
3323 {
3324 for (size_t i = mInternalDMAs.size(); i-- > 0;) {
3325 if (mInternalDMAs[i] == (unsigned int)idma) {
3326 mInternalDMAs.removeItemsAt(i);
3327 }
3328 }
3329 }
3330
3331 int ExynosDisplay::getDisplayConfigs(uint32_t *configs, size_t *numConfigs)
3332 {
3333 configs[0] = 0;
3334 *numConfigs = 1;
3335 return 0;
3336 }
3337
3338 int ExynosDisplay::getDeconDMAType(ExynosMPPModule* internalMPP)
3339 {
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) {
3346 case 0:
3347 return IDMA_G0;
3348 case 1:
3349 return IDMA_G1;
3350 case 2:
3351 return IDMA_G2;
3352 case 3:
3353 return IDMA_G3;
3354 default:
3355 return -1;
3356 }
3357 } else
3358 return -1;
3359 }
3360
3361 void ExynosDisplay::dumpContents(android::String8& result, hwc_display_contents_1_t *contents)
3362 {
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",
3367 i,
3368 layer.compositionType, layer.flags, layer.handle, layer.transform,
3369 layer.blending,
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);
3378
3379 }
3380 }
3381
3382 int ExynosDisplay::checkConfigValidation(decon_win_config *config)
3383 {
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;
3396 }
3397 }
3398 }
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;
3406 }
3407
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;
3412 }
3413 }
3414 }
3415
3416 if (flagValidConfig)
3417 return 0;
3418 else
3419 return -1;
3420 }
3421
3422 int ExynosDisplay::setPowerMode(int mode)
3423 {
3424 #if defined(S3CFB_POWER_MODE)
3425 return ioctl(this->mDisplayFd, S3CFB_POWER_MODE, &mode);
3426 #else
3427 return ioctl(this->mDisplayFd, FBIOBLANK, (mode == HWC_POWER_MODE_OFF ? FB_BLANK_POWERDOWN : FB_BLANK_UNBLANK));
3428 #endif
3429 }