Commit | Line | Data |
---|---|---|
5763fb39 T |
1 | #define ATRACE_TAG ATRACE_TAG_GRAPHICS |
2 | #include "ExynosOverlayDisplay.h" | |
3 | #include "ExynosHWCUtils.h" | |
4 | #include "ExynosMPPModule.h" | |
5 | #include <utils/Trace.h> | |
6 | ||
7 | #ifdef G2D_COMPOSITION | |
8 | #include "ExynosG2DWrapper.h" | |
9 | #endif | |
10 | ||
11 | ExynosOverlayDisplay::ExynosOverlayDisplay(int numMPPs, struct exynos5_hwc_composer_device_1_t *pdev) | |
12 | : ExynosDisplay(numMPPs), | |
13 | mLastFbWindow(NO_FB_NEEDED), | |
14 | mGrallocModule(NULL), | |
15 | mLastOverlayWindowIndex(-1), | |
16 | mLastOverlayLayerIndex(-1), | |
17 | mVirtualOverlayFlag(0), | |
18 | mForceFbYuvLayer(0), | |
19 | mCountSameConfig(0), | |
20 | mConfigMode(0), | |
21 | mGscLayers(0), | |
22 | mPopupPlayYuvContents(false), | |
23 | mHasCropSurface(false), | |
24 | mYuvLayers(0), | |
25 | mBypassSkipStaticLayer(false), | |
26 | mGscUsed(false), | |
27 | mCurrentGscIndex(0), | |
28 | mFbNeeded(false), | |
29 | mFirstFb(0), | |
30 | mLastFb(0), | |
31 | mForceFb(false), | |
32 | mForceOverlayLayerIndex(-1), | |
33 | mRetry(false), | |
34 | mBlanked(true), | |
35 | mMaxWindowOverlapCnt(NUM_HW_WINDOWS), | |
36 | mAllowedOverlays(5) | |
37 | { | |
38 | mMPPs = new ExynosMPPModule*[mNumMPPs]; | |
39 | for (int i = 0; i < mNumMPPs; i++) | |
40 | mMPPs[i] = new ExynosMPPModule(this, i); | |
41 | ||
42 | for (size_t i = 0; i < MAX_NUM_FIMD_DMA_CH; i++) { | |
43 | mDmaChannelMaxBandwidth[i] = 2560 * 1600; | |
44 | mDmaChannelMaxOverlapCount[i] = 1; | |
45 | } | |
46 | ||
47 | memset(&mPostData, 0, sizeof(mPostData)); | |
48 | memset(&mLastConfigData, 0, sizeof(mLastConfigData)); | |
49 | memset(mLastGscMap, 0, sizeof(mLastGscMap)); | |
50 | memset(mLastHandles, 0, sizeof(mLastHandles)); | |
51 | memset(mLastLayerHandles, 0, sizeof(mLastLayerHandles)); | |
52 | memset(mPrevDstConfig, 0, sizeof(mPrevDstConfig)); | |
53 | ||
54 | mCurrentRGBMPPIndex = 0; | |
55 | memset(&mFbUpdateRegion, 0, sizeof(mFbUpdateRegion)); | |
56 | ||
57 | mOtfMode = OTF_OFF; | |
58 | this->mHwc = pdev; | |
59 | } | |
60 | ||
61 | ExynosOverlayDisplay::~ExynosOverlayDisplay() | |
62 | { | |
63 | for (int i = 0; i < mNumMPPs; i++) | |
64 | delete mMPPs[i]; | |
65 | delete[] mMPPs; | |
66 | } | |
67 | ||
68 | bool ExynosOverlayDisplay::isOverlaySupported(hwc_layer_1_t &layer, size_t i) | |
69 | { | |
70 | int mMPPIndex = 0; | |
71 | int ret = 0; | |
72 | ||
73 | if (layer.flags & HWC_SKIP_LAYER) { | |
74 | mLayerInfos[i]->mCheckOverlayFlag |= eSkipLayer; | |
75 | ALOGV("\tlayer %u: skipping", i); | |
76 | return false; | |
77 | } | |
78 | ||
79 | if (!layer.planeAlpha) | |
80 | return true; | |
81 | ||
82 | if (i == 0 && layer.planeAlpha < 255) { | |
83 | mLayerInfos[i]->mCheckOverlayFlag |= eUnsupportedPlaneAlpha; | |
84 | return false; | |
85 | } | |
86 | ||
87 | private_handle_t *handle = private_handle_t::dynamicCast(layer.handle); | |
88 | ||
89 | if (!handle) { | |
90 | ALOGV("\tlayer %u: handle is NULL", i); | |
91 | mLayerInfos[i]->mCheckOverlayFlag |= eInvalidHandle; | |
92 | return false; | |
93 | } | |
94 | ||
95 | if (isFormatRgb(handle->format) && handle->stride >= MAX_BUF_STRIDE) { | |
96 | mLayerInfos[i]->mCheckOverlayFlag |= eExceedHStrideMaximum; | |
97 | return false; | |
98 | } | |
99 | ||
100 | mMPPIndex = getMPPForUHD(layer); | |
101 | if (isFormatRgb(handle->format)) | |
102 | mMPPIndex = getRGBMPPIndex(0); | |
103 | ||
104 | if (!(mMPPs[mMPPIndex]->formatRequiresGsc(handle->format)) && | |
105 | (formatToBpp(handle->format) == 16) && ((layer.displayFrame.left % 2 != 0) || (layer.displayFrame.right % 2 != 0))) | |
106 | return false; | |
107 | ||
108 | if (isSrcCropFloat(layer.sourceCropf) && | |
109 | getDrmMode(handle->flags) == NO_DRM) { | |
110 | ALOGV("\tlayer %u: has floating crop info [%7.1f %7.1f %7.1f %7.1f]", i, | |
111 | layer.sourceCropf.left, layer.sourceCropf.top, layer.sourceCropf.right, | |
112 | layer.sourceCropf.bottom); | |
113 | mLayerInfos[i]->mCheckOverlayFlag |= eHasFloatSrcCrop; | |
114 | return false; | |
115 | } | |
116 | ||
117 | if (visibleWidth(mMPPs[mMPPIndex], layer, handle->format, this->mXres) < BURSTLEN_BYTES) { | |
118 | ALOGV("\tlayer %u: visible area is too narrow", i); | |
119 | mLayerInfos[i]->mCheckOverlayFlag |= eUnsupportedDstWidth; | |
120 | return false; | |
121 | } | |
122 | ||
123 | if (mMPPs[mMPPIndex]->isProcessingRequired(layer, handle->format)) { | |
124 | int downNumerator, downDenominator; | |
125 | int downError = mMPPs[mMPPIndex]->getDownscaleRatio(&downNumerator, &downDenominator); | |
126 | /* Check whether GSC can handle using local or M2M */ | |
127 | ret = mMPPs[mMPPIndex]->isProcessingSupported(layer, handle->format, false); | |
128 | if (ret < 0) { | |
129 | ALOGV("\tlayer %u: MPP M2M required but not supported", i); | |
130 | mLayerInfos[i]->mCheckOverlayFlag |= eMPPUnsupported; | |
131 | mLayerInfos[i]->mCheckMPPFlag |= -ret; | |
132 | ||
133 | ret = mMPPs[mMPPIndex]->isProcessingSupported(layer, handle->format, true, downNumerator, downDenominator); | |
134 | if (ret < 0) { | |
135 | ALOGV("\tlayer %u: MPP OTF required but not supported", i); | |
136 | mLayerInfos[i]->mCheckOverlayFlag |= eMPPUnsupported; | |
137 | mLayerInfos[i]->mCheckMPPFlag |= -ret; | |
138 | return false; | |
139 | } | |
140 | } | |
141 | } else { | |
142 | #ifdef USE_FB_PHY_LINEAR | |
143 | #ifdef G2D_COMPOSITION | |
144 | if ((this->mG2dComposition) && (this->mG2dLayers < (int)(NUM_HW_WIN_FB_PHY - 1))) | |
145 | this->mG2d.ovly_lay_idx[this->mG2dLayers++] = i; | |
146 | else | |
147 | #endif | |
148 | return false; | |
149 | #endif | |
150 | if (!isFormatSupported(handle->format)) { | |
151 | mLayerInfos[i]->mCheckOverlayFlag |= eUnsupportedFormat; | |
152 | ALOGV("\tlayer %u: pixel format %u not supported", i, handle->format); | |
153 | return false; | |
154 | } | |
155 | } | |
156 | ||
157 | if (!isBlendingSupported(layer.blending)) { | |
158 | ALOGV("\tlayer %u: blending %d not supported", i, layer.blending); | |
159 | mLayerInfos[i]->mCheckOverlayFlag |= eUnsupportedBlending; | |
160 | return false; | |
161 | } | |
162 | ||
163 | #ifdef USE_FB_PHY_LINEAR | |
164 | if (CC_UNLIKELY(isOffscreen(layer, mXres, mYres))) { | |
165 | ALOGW("\tlayer %u: off-screen", i); | |
166 | return false; | |
167 | } | |
168 | #endif | |
169 | ||
170 | return true; | |
171 | } | |
172 | ||
173 | int ExynosOverlayDisplay::prepare(hwc_display_contents_1_t* contents) | |
174 | { | |
175 | ATRACE_CALL(); | |
176 | ALOGV("preparing %u layers for FIMD", contents->numHwLayers); | |
177 | ||
178 | memset(mPostData.gsc_map, 0, sizeof(mPostData.gsc_map)); | |
179 | ||
180 | mForceFb = mHwc->force_gpu; | |
181 | ||
182 | checkTVBandwidth(); | |
183 | ||
184 | mForceFbYuvLayer = 0; | |
185 | mConfigMode = 0; | |
186 | mRetry = false; | |
187 | ||
188 | ExynosDisplay::allocateLayerInfos(contents); | |
189 | /* | |
190 | * check whether same config or different config, | |
191 | * should be waited until meeting the NUM_COFIG)STABLE | |
192 | * before stablizing config, should be composed by GPU | |
193 | * faster stablizing config, should be returned by OVERLAY | |
194 | */ | |
195 | forceYuvLayersToFb(contents); | |
196 | ||
197 | if (mHwc->force_gpu == true) | |
198 | mForceFb = true; | |
199 | ||
200 | do { | |
201 | #ifdef G2D_COMPOSITION | |
202 | int tot_pixels = 0; | |
203 | mG2dLayers= 0; | |
204 | memset(&mG2d, 0, sizeof(mG2d)); | |
205 | mG2dComposition = 0; | |
206 | ||
207 | if (contents->flags & HWC_GEOMETRY_CHANGED) { | |
208 | mG2dBypassCount = 4; | |
209 | goto SKIP_G2D_OVERLAY; | |
210 | } | |
211 | ||
212 | if (mG2dBypassCount > 0) | |
213 | goto SKIP_G2D_OVERLAY; | |
214 | ||
215 | for (size_t i = 0; i < contents->numHwLayers; i++) { | |
216 | hwc_layer_1_t &layer = contents->hwLayers[i]; | |
217 | ||
218 | if ((layer.compositionType == HWC_FRAMEBUFFER_TARGET) || | |
219 | (layer.compositionType == HWC_BACKGROUND && !mForceFb)) | |
220 | continue; | |
221 | ||
222 | if (is_transformed(layer) || is_scaled(layer) || (!layer.handle)) | |
223 | goto SKIP_G2D_OVERLAY; | |
224 | ||
225 | private_handle_t *handle = private_handle_t::dynamicCast(layer.handle); | |
226 | if (!exynos5_format_is_rgb(handle->format)) | |
227 | goto SKIP_G2D_OVERLAY; | |
228 | ||
229 | tot_pixels += WIDTH(layer.displayFrame) * HEIGHT(layer.displayFrame); | |
230 | } | |
231 | ||
232 | if ((tot_pixels == mXres * mYres) && | |
233 | (contents->numHwLayers <= NUM_HW_WINDOWS + 1)) | |
234 | mG2dComposition = 1; | |
235 | else | |
236 | mG2dComposition = 0; | |
237 | ||
238 | SKIP_G2D_OVERLAY: | |
239 | #endif | |
240 | ||
241 | determineYuvOverlay(contents); | |
242 | determineSupportedOverlays(contents); | |
243 | determineBandwidthSupport(contents); | |
244 | assignWindows(contents); | |
245 | } while (mRetry); | |
246 | ||
247 | #ifdef G2D_COMPOSITION | |
248 | int alloc_fail = 0; | |
249 | CHANGE_COMPOS_MODE: | |
250 | if (mG2dComposition) { | |
251 | if (mGscUsed || mFbNeeded || alloc_fail) { | |
252 | //use SKIP_STATIC_LAYER_COMP | |
253 | for (size_t i = 0; i < (size_t)mG2dLayers; i++) { | |
254 | int lay_idx = mG2d.ovly_lay_idx[i]; | |
255 | hwc_layer_1_t &layer = contents->hwLayers[lay_idx]; | |
256 | layer.compositionType = HWC_FRAMEBUFFER; | |
257 | mFbNeeded = true; | |
258 | for (size_t j = 0; j < NUM_HW_WIN_FB_PHY; j++) { | |
259 | if (mPostData.overlay_map[j] == lay_idx) { | |
260 | mPostData.overlay_map[j] = -1; | |
261 | break; | |
262 | } | |
263 | } | |
264 | } | |
265 | if (mFbNeeded) | |
266 | mFirstFb = min(mFirstFb, (size_t)mG2d.ovly_lay_idx[0]); | |
267 | mG2dLayers= 0; | |
268 | mG2dComposition = 0; | |
269 | } | |
270 | } | |
271 | ||
272 | if (mG2dComposition) { | |
273 | alloc_fail = exynos5_g2d_buf_alloc(mHwc, contents); | |
274 | if (alloc_fail) | |
275 | goto CHANGE_COMPOS_MODE; | |
276 | } | |
277 | ||
278 | if (contents->flags & HWC_GEOMETRY_CHANGED) { | |
279 | for (int i = 0; i < (int)NUM_HW_WIN_FB_PHY; i++) | |
280 | mLastG2dLayerHandle[i] = 0; | |
281 | } | |
282 | #endif | |
283 | ||
284 | if (mPopupPlayYuvContents) | |
285 | mVirtualOverlayFlag = 0; | |
286 | else | |
287 | skipStaticLayers(contents); | |
288 | if (mVirtualOverlayFlag) | |
289 | mFbNeeded = 0; | |
290 | ||
291 | if (!mFbNeeded) | |
292 | mPostData.fb_window = NO_FB_NEEDED; | |
293 | else | |
294 | if (mPopupPlayYuvContents) | |
295 | mPostData.fb_window = 1; | |
296 | ||
297 | return 0; | |
298 | } | |
299 | ||
300 | void ExynosOverlayDisplay::configureOtfWindow(hwc_rect_t &displayFrame, | |
301 | int32_t blending, int32_t planeAlpha, int fence_fd, int format, s3c_fb_win_config &cfg) | |
302 | { | |
303 | uint8_t bpp = formatToBpp(format); | |
304 | ||
305 | cfg.state = cfg.S3C_FB_WIN_STATE_OTF; | |
306 | cfg.fd = -1; | |
307 | cfg.x = displayFrame.left; | |
308 | cfg.y = displayFrame.top; | |
309 | cfg.w = WIDTH(displayFrame); | |
310 | cfg.h = HEIGHT(displayFrame); | |
311 | cfg.format = halFormatToS3CFormat(format); | |
312 | cfg.offset = 0; | |
313 | cfg.stride = cfg.w * bpp / 8; | |
314 | cfg.blending = halBlendingToS3CBlending(blending); | |
315 | cfg.fence_fd = fence_fd; | |
316 | cfg.plane_alpha = 255; | |
317 | if (planeAlpha && (planeAlpha < 255)) { | |
318 | cfg.plane_alpha = planeAlpha; | |
319 | } | |
320 | } | |
321 | ||
322 | void ExynosOverlayDisplay::configureHandle(private_handle_t *handle, | |
323 | hwc_frect_t &sourceCrop, hwc_rect_t &displayFrame, | |
324 | int32_t blending, int32_t planeAlpha, int fence_fd, s3c_fb_win_config &cfg) | |
325 | { | |
326 | uint32_t x, y; | |
327 | uint32_t w = WIDTH(displayFrame); | |
328 | uint32_t h = HEIGHT(displayFrame); | |
329 | uint8_t bpp = formatToBpp(handle->format); | |
330 | uint32_t offset = ((uint32_t)sourceCrop.top * handle->stride + (uint32_t)sourceCrop.left) * bpp / 8; | |
331 | ||
332 | if (displayFrame.left < 0) { | |
333 | unsigned int crop = -displayFrame.left; | |
334 | ALOGV("layer off left side of screen; cropping %u pixels from left edge", | |
335 | crop); | |
336 | x = 0; | |
337 | w -= crop; | |
338 | offset += crop * bpp / 8; | |
339 | } else { | |
340 | x = displayFrame.left; | |
341 | } | |
342 | ||
343 | if (displayFrame.right > this->mXres) { | |
344 | unsigned int crop = displayFrame.right - this->mXres; | |
345 | ALOGV("layer off right side of screen; cropping %u pixels from right edge", | |
346 | crop); | |
347 | w -= crop; | |
348 | } | |
349 | ||
350 | if (displayFrame.top < 0) { | |
351 | unsigned int crop = -displayFrame.top; | |
352 | ALOGV("layer off top side of screen; cropping %u pixels from top edge", | |
353 | crop); | |
354 | y = 0; | |
355 | h -= crop; | |
356 | offset += handle->stride * crop * bpp / 8; | |
357 | } else { | |
358 | y = displayFrame.top; | |
359 | } | |
360 | ||
361 | if (displayFrame.bottom > this->mYres) { | |
362 | int crop = displayFrame.bottom - this->mYres; | |
363 | ALOGV("layer off bottom side of screen; cropping %u pixels from bottom edge", | |
364 | crop); | |
365 | h -= crop; | |
366 | } | |
367 | ||
368 | cfg.state = cfg.S3C_FB_WIN_STATE_BUFFER; | |
369 | cfg.fd = handle->fd; | |
370 | cfg.x = x; | |
371 | cfg.y = y; | |
372 | cfg.w = w; | |
373 | cfg.h = h; | |
374 | cfg.format = halFormatToS3CFormat(handle->format); | |
375 | cfg.offset = offset; | |
376 | cfg.stride = handle->stride * bpp / 8; | |
377 | cfg.blending = halBlendingToS3CBlending(blending); | |
378 | cfg.fence_fd = fence_fd; | |
379 | cfg.plane_alpha = 255; | |
380 | if (planeAlpha && (planeAlpha < 255)) { | |
381 | cfg.plane_alpha = planeAlpha; | |
382 | } | |
383 | #ifdef USES_DRM_SETTING_BY_DECON | |
384 | if (getDrmMode(handle->flags) != NO_DRM) | |
385 | cfg.protection = 1; | |
386 | else | |
387 | cfg.protection = 0; | |
388 | #endif | |
389 | } | |
390 | ||
391 | void ExynosOverlayDisplay::configureOverlay(hwc_layer_1_t *layer, s3c_fb_win_config &cfg) | |
392 | { | |
393 | hwc_rect_t displayFrame; | |
394 | ||
395 | displayFrame.left = layer->displayFrame.left; | |
396 | displayFrame.top = layer->displayFrame.top; | |
397 | displayFrame.right = layer->displayFrame.right; | |
398 | displayFrame.bottom = layer->displayFrame.bottom; | |
399 | ||
400 | if (layer->compositionType == HWC_BACKGROUND) { | |
401 | hwc_color_t color = layer->backgroundColor; | |
402 | cfg.state = cfg.S3C_FB_WIN_STATE_COLOR; | |
403 | cfg.color = (color.r << 16) | (color.g << 8) | color.b; | |
404 | cfg.x = 0; | |
405 | cfg.y = 0; | |
406 | cfg.w = this->mXres; | |
407 | cfg.h = this->mYres; | |
408 | return; | |
409 | } | |
410 | if ((layer->acquireFenceFd >= 0) && this->mForceFbYuvLayer) { | |
411 | if (sync_wait(layer->acquireFenceFd, 1000) < 0) | |
412 | ALOGE("sync_wait error"); | |
413 | close(layer->acquireFenceFd); | |
414 | layer->acquireFenceFd = -1; | |
415 | } | |
416 | private_handle_t *handle = private_handle_t::dynamicCast(layer->handle); | |
417 | hwc_frect_t originalCrop = layer->sourceCropf; | |
418 | if (layer->compositionType == HWC_FRAMEBUFFER_TARGET) { | |
419 | layer->sourceCropf.left = (double)mFbUpdateRegion.left; | |
420 | layer->sourceCropf.top = (double)mFbUpdateRegion.top; | |
421 | layer->sourceCropf.right = (double)mFbUpdateRegion.right; | |
422 | layer->sourceCropf.bottom = (double)mFbUpdateRegion.bottom; | |
423 | displayFrame.left = mFbUpdateRegion.left; | |
424 | displayFrame.top = mFbUpdateRegion.top; | |
425 | displayFrame.right = mFbUpdateRegion.right; | |
426 | displayFrame.bottom = mFbUpdateRegion.bottom; | |
427 | } | |
428 | configureHandle(handle, layer->sourceCropf, displayFrame, | |
429 | layer->blending, layer->planeAlpha, layer->acquireFenceFd, cfg); | |
430 | layer->sourceCropf = originalCrop; | |
431 | } | |
432 | ||
433 | void ExynosOverlayDisplay::configureDummyOverlay(hwc_layer_1_t *layer, s3c_fb_win_config &cfg) | |
434 | { | |
435 | hwc_rect_t displayFrame; | |
436 | ||
437 | displayFrame.left = layer->displayFrame.left; | |
438 | displayFrame.top = layer->displayFrame.top; | |
439 | displayFrame.right = layer->displayFrame.right; | |
440 | displayFrame.bottom = layer->displayFrame.bottom; | |
441 | ||
442 | if (layer->acquireFenceFd >= 0) { | |
443 | close(layer->acquireFenceFd); | |
444 | layer->acquireFenceFd = -1; | |
445 | } | |
446 | ||
447 | uint32_t x, y; | |
448 | uint32_t w = WIDTH(displayFrame); | |
449 | uint32_t h = HEIGHT(displayFrame); | |
450 | ||
451 | if (displayFrame.left < 0) { | |
452 | unsigned int crop = -displayFrame.left; | |
453 | x = 0; | |
454 | w -= crop; | |
455 | } else { | |
456 | x = displayFrame.left; | |
457 | } | |
458 | ||
459 | if (displayFrame.right > this->mXres) { | |
460 | unsigned int crop = displayFrame.right - this->mXres; | |
461 | w -= crop; | |
462 | } | |
463 | ||
464 | if (displayFrame.top < 0) { | |
465 | unsigned int crop = -displayFrame.top; | |
466 | y = 0; | |
467 | h -= crop; | |
468 | } else { | |
469 | y = displayFrame.top; | |
470 | } | |
471 | ||
472 | if (displayFrame.bottom > this->mYres) { | |
473 | int crop = displayFrame.bottom - this->mYres; | |
474 | h -= crop; | |
475 | } | |
476 | ||
477 | cfg.state = cfg.S3C_FB_WIN_STATE_COLOR; | |
478 | cfg.color = 0; | |
479 | ||
480 | cfg.x = x; | |
481 | cfg.y = y; | |
482 | cfg.w = w; | |
483 | cfg.h = h; | |
484 | cfg.fence_fd = -1; | |
485 | ||
486 | return; | |
487 | } | |
488 | ||
489 | int ExynosOverlayDisplay::handleWindowUpdate(hwc_display_contents_1_t* contents, | |
490 | struct s3c_fb_win_config *config) | |
491 | { | |
492 | exynos5_hwc_post_data_t *pdata = &mPostData; | |
493 | int layerIdx = -1; | |
494 | int updatedWinCnt = 0; | |
495 | int totalWinCnt = 0; | |
496 | int bytePerPixel = 0; | |
497 | size_t winUpdateInfoIdx; | |
498 | hwc_rect updateRect = {this->mXres, this->mYres, 0, 0}; | |
499 | hwc_rect currentRect = {0, 0, 0, 0}; | |
500 | bool burstLengthCheckDone = false; | |
501 | int alignAdjustment = 0; | |
502 | int intersectionWidth = 0; | |
503 | ||
504 | char value[PROPERTY_VALUE_MAX]; | |
2bd61160 | 505 | property_get("debug.hwc.winupdate", value, "1"); |
5763fb39 T |
506 | |
507 | if (!(!strcmp(value, "1") || !strcmp(value, "true"))) | |
508 | return 0; | |
509 | ||
510 | if (S3C_WIN_UPDATE_IDX < 0) | |
511 | return 0; | |
512 | winUpdateInfoIdx = S3C_WIN_UPDATE_IDX; | |
513 | ||
514 | if (contents->flags & HWC_GEOMETRY_CHANGED) | |
515 | return 0; | |
516 | ||
517 | for (size_t i = 0; i < NUM_HW_WINDOWS; i++) { | |
518 | if (config[i].state != config[i].S3C_FB_WIN_STATE_DISABLED) { | |
519 | if (mLastGscMap[i].mode == exynos5_gsc_map_t::GSC_LOCAL) { | |
520 | HLOGV("[WIN_UPDATE] disabled by GSC-OTF in window(%d)", i); | |
521 | return 0; | |
522 | } | |
523 | totalWinCnt++; | |
524 | layerIdx = pdata->overlay_map[totalWinCnt - 1]; | |
525 | ||
526 | if (winConfigChanged(&config[i], &this->mLastConfigData.config[i])) { | |
527 | updatedWinCnt++; | |
528 | ||
529 | currentRect.left = config[i].x; | |
530 | currentRect.right = config[i].x + config[i].w; | |
531 | currentRect.top = config[i].y; | |
532 | currentRect.bottom = config[i].y + config[i].h; | |
533 | ||
534 | if (hwcHasApiVersion((hwc_composer_device_1_t*)mHwc, HWC_DEVICE_API_VERSION_1_5)) | |
535 | { | |
536 | private_handle_t *handle = NULL; | |
537 | hwc_rect damageRect = {0, 0, 0, 0}; | |
538 | hwc_layer_1_t &layer = contents->hwLayers[i]; | |
539 | if (layer.handle) | |
540 | handle = private_handle_t::dynamicCast(layer.handle); | |
541 | unsigned int damageRegionMod = getLayerRegion(layer, damageRect, eDamageRegion); | |
542 | ||
543 | if (damageRegionMod == eDamageRegionSkip) | |
544 | continue; | |
545 | ||
546 | if (handle && !isScaled(layer) && !isRotated(layer) | |
547 | && (damageRegionMod == eDamageRegionPartial)) { | |
548 | HLOGD("[WIN_UPDATE][surfaceDamage] layer w(%4d) h(%4d), dirty (%4d, %4d) - (%4d, %4d)", | |
549 | handle->width, handle->height, damageRect.left, damageRect.top, damageRect.right, damageRect.bottom); | |
550 | ||
551 | currentRect.left = config[i].x - (int32_t)layer.sourceCropf.left + damageRect.left; | |
552 | currentRect.right = config[i].x - (int32_t)layer.sourceCropf.left + damageRect.right; | |
553 | currentRect.top = config[i].y - (int32_t)layer.sourceCropf.top + damageRect.top; | |
554 | currentRect.bottom = config[i].y - (int32_t)layer.sourceCropf.top + damageRect.bottom; | |
555 | adjustRect(currentRect, mXres, mYres); | |
556 | ||
557 | } | |
558 | } | |
559 | if ((currentRect.left > currentRect.right) || (currentRect.top > currentRect.bottom)) { | |
560 | HLOGD("[WIN_UPDATE] window(%d) layer(%d) invalid region (%4d, %4d) - (%4d, %4d)", | |
561 | i, layerIdx, currentRect.left, currentRect.top, currentRect.right, currentRect.bottom); | |
562 | return 0; | |
563 | } | |
564 | HLOGD("[WIN_UPDATE] Updated Window(%d) Layer(%d) (%4d, %4d) - (%4d, %4d)", | |
565 | i, layerIdx, currentRect.left, currentRect.top, currentRect.right, currentRect.bottom); | |
566 | updateRect = expand(updateRect, currentRect); | |
567 | } | |
568 | } | |
569 | } | |
570 | if (updatedWinCnt == 0) | |
571 | return 0; | |
572 | ||
573 | updateRect.left = ALIGN_DOWN(updateRect.left, WINUPDATE_X_ALIGNMENT); | |
574 | updateRect.right = updateRect.left + ALIGN_UP(WIDTH(updateRect), WINUPDATE_W_ALIGNMENT); | |
575 | ||
576 | if ((100 * (WIDTH(updateRect) * HEIGHT(updateRect)) / (this->mXres * this->mYres)) > WINUPDATE_THRESHOLD) | |
577 | return 0; | |
578 | ||
579 | alignAdjustment = max(WINUPDATE_X_ALIGNMENT, WINUPDATE_W_ALIGNMENT); | |
580 | ||
581 | while (1) { | |
582 | burstLengthCheckDone = true; | |
583 | ||
584 | for (int i = 0; i < NUM_HW_WINDOWS; i++) { | |
585 | if (config[i].state != config[i].S3C_FB_WIN_STATE_DISABLED) { | |
586 | if (config[i].format == S3C_FB_PIXEL_FORMAT_RGB_565) | |
587 | bytePerPixel = 2; | |
588 | else | |
589 | bytePerPixel = 4; | |
590 | ||
591 | currentRect.left = config[i].x; | |
592 | currentRect.right = config[i].x + config[i].w; | |
593 | currentRect.top = config[i].y; | |
594 | currentRect.bottom = config[i].y + config[i].h; | |
595 | ||
596 | intersectionWidth = WIDTH(intersection(currentRect, updateRect)); | |
597 | ||
598 | HLOGV("[WIN_UPDATE] win[%d] left(%d) right(%d) intersection(%d)", i, currentRect.left, currentRect.right, intersectionWidth); | |
599 | ||
600 | if (intersectionWidth != 0 && intersectionWidth * bytePerPixel < BURSTLEN_BYTES) { | |
601 | HLOGV("[WIN_UPDATE] win[%d] insufficient burst length (%d)*(%d) < %d", i, intersectionWidth, bytePerPixel, BURSTLEN_BYTES); | |
602 | burstLengthCheckDone = false; | |
603 | break; | |
604 | } | |
605 | } | |
606 | } | |
607 | if (burstLengthCheckDone) | |
608 | break; | |
609 | HLOGD("[WIN_UPDATE] Adjusting update width. current left(%d) right(%d)", updateRect.left, updateRect.right); | |
610 | if (updateRect.left >= alignAdjustment) { | |
611 | updateRect.left -= alignAdjustment; | |
612 | } else if (updateRect.right + alignAdjustment <= this->mXres) { | |
613 | updateRect.right += alignAdjustment; | |
614 | } else { | |
615 | ALOGD("[WIN_UPDATE] Error during update width adjustment"); | |
616 | return 0; | |
617 | } | |
618 | } | |
619 | ||
620 | config[winUpdateInfoIdx].state = config[winUpdateInfoIdx].S3C_FB_WIN_STATE_UPDATE; | |
621 | config[winUpdateInfoIdx].x = updateRect.left; | |
622 | config[winUpdateInfoIdx].y = updateRect.top; | |
623 | config[winUpdateInfoIdx].w = ALIGN_UP(WIDTH(updateRect), WINUPDATE_W_ALIGNMENT); | |
624 | config[winUpdateInfoIdx].h = HEIGHT(updateRect); | |
625 | ||
626 | HLOGD("[WIN_UPDATE] UpdateRegion cfg (%4d, %4d) w(%4d) h(%4d) updatedWindowCnt(%d)", | |
627 | config[winUpdateInfoIdx].x, config[winUpdateInfoIdx].y, config[winUpdateInfoIdx].w, config[winUpdateInfoIdx].h, updatedWinCnt); | |
628 | ||
629 | return 1; | |
630 | } | |
631 | ||
632 | int ExynosOverlayDisplay::winconfigIoctl(s3c_fb_win_config_data *win_data) | |
633 | { | |
634 | ATRACE_CALL(); | |
635 | return ioctl(this->mDisplayFd, S3CFB_WIN_CONFIG, win_data); | |
636 | } | |
637 | ||
638 | int ExynosOverlayDisplay::postFrame(hwc_display_contents_1_t* contents) | |
639 | { | |
640 | ATRACE_CALL(); | |
641 | exynos5_hwc_post_data_t *pdata = &mPostData; | |
642 | struct s3c_fb_win_config_data win_data; | |
643 | struct s3c_fb_win_config *config = win_data.config; | |
644 | int win_map = 0; | |
645 | int tot_ovly_wins = 0; | |
646 | ||
647 | #ifdef G2D_COMPOSITION | |
648 | int num_g2d_overlayed = 0; | |
649 | #endif | |
650 | ||
651 | memset(config, 0, sizeof(win_data.config)); | |
652 | for (size_t i = 0; i < NUM_HW_WINDOWS; i++) | |
653 | config[i].fence_fd = -1; | |
654 | ||
655 | for (size_t i = 0; i < NUM_HW_WINDOWS; i++) { | |
656 | if ( pdata->overlay_map[i] != -1) | |
657 | tot_ovly_wins++; | |
658 | } | |
659 | if (mVirtualOverlayFlag) | |
660 | tot_ovly_wins++; | |
661 | ||
662 | for (size_t i = 0; i < NUM_HW_WINDOWS; i++) { | |
663 | int layer_idx = pdata->overlay_map[i]; | |
664 | if (layer_idx != -1) { | |
665 | hwc_layer_1_t &layer = contents->hwLayers[layer_idx]; | |
666 | win_map = getDeconWinMap(i, tot_ovly_wins); | |
667 | if (pdata->gsc_map[i].mode == exynos5_gsc_map_t::GSC_M2M) { | |
668 | if (contents->flags & HWC_GEOMETRY_CHANGED) | |
669 | mMPPs[pdata->gsc_map[i].idx]->mLastGSCLayerHandle = -1; | |
670 | if (postGscM2M(layer, config, win_map, i, !!(i == 0)) < 0) | |
671 | continue; | |
672 | } else if (pdata->gsc_map[i].idx == FIMD_GSC_IDX && this->mOtfMode == OTF_RUNNING && | |
673 | pdata->gsc_map[i].mode == exynos5_gsc_map_t::GSC_LOCAL) { | |
674 | postGscOtf(layer, config, win_map, i); | |
675 | #ifdef G2D_COMPOSITION | |
676 | } else if (this->mG2dComposition && (num_g2d_overlayed < this->mG2dLayers)){ | |
677 | waitForRenderFinish(&layer.handle, 1); | |
678 | private_handle_t dstHandle(*(private_handle_t::dynamicCast(layer.handle))); | |
679 | hwc_frect_t sourceCrop = {0, 0, WIDTH(layer.displayFrame), HEIGHT(layer.displayFrame)}; | |
680 | int fence = exynos5_config_g2d(mHwc, layer, &dstHandle, config[win_map], num_g2d_overlayed, i); | |
681 | if (fence < 0) { | |
682 | ALOGE("config_g2d failed for layer %u", i); | |
683 | continue; | |
684 | } | |
685 | configureHandle(&dstHandle, sourceCrop, layer.displayFrame, | |
686 | layer.blending, layer.planeAlpha, fence, *config); | |
687 | num_g2d_overlayed++; | |
688 | this->mG2d.win_used[i] = num_g2d_overlayed; | |
689 | #endif | |
690 | } else { | |
691 | waitForRenderFinish(&layer.handle, 1); | |
692 | configureOverlay(&layer, config[win_map]); | |
693 | } | |
694 | } | |
695 | if (i == 0 && config[i].blending != S3C_FB_BLENDING_NONE) { | |
696 | ALOGV("blending not supported on window 0; forcing BLENDING_NONE"); | |
697 | config[i].blending = S3C_FB_BLENDING_NONE; | |
698 | } | |
699 | if ((i < S3C_WIN_UPDATE_IDX) && | |
700 | (config[i].state != config[i].S3C_FB_WIN_STATE_DISABLED) && | |
701 | (config[i].w == 0 || config[i].h == 0)) { | |
702 | config[i].state = config[i].S3C_FB_WIN_STATE_DISABLED; | |
703 | } | |
704 | ||
705 | ALOGV("window %u configuration:", i); | |
706 | dumpConfig(config[win_map]); | |
707 | } | |
708 | ||
709 | if (this->mVirtualOverlayFlag) { | |
710 | handleStaticLayers(contents, win_data, tot_ovly_wins); | |
711 | } | |
712 | ||
713 | if (!handleWindowUpdate(contents, config)) | |
714 | HLOGD("[WIN_UPDATE] Not Triggered"); | |
715 | ||
716 | int ret = winconfigIoctl(&win_data); | |
717 | for (size_t i = 0; i < NUM_HW_WINDOWS; i++) | |
718 | if (config[i].fence_fd != -1) | |
719 | close(config[i].fence_fd); | |
720 | if (ret < 0) { | |
721 | ALOGE("ioctl S3CFB_WIN_CONFIG failed: %s", strerror(errno)); | |
722 | return ret; | |
723 | } | |
724 | if (contents->numHwLayers == 1) { | |
725 | hwc_layer_1_t &layer = contents->hwLayers[0]; | |
726 | if (layer.acquireFenceFd >= 0) | |
727 | close(layer.acquireFenceFd); | |
728 | } | |
729 | ||
730 | if (!mGscLayers || this->mOtfMode == OTF_TO_M2M) { | |
731 | cleanupGscs(); | |
732 | } | |
733 | ||
734 | #ifdef G2D_COMPOSITION | |
735 | if (!this->mG2dComposition) | |
736 | exynos5_cleanup_g2d(mHwc, 0); | |
737 | ||
738 | this->mG2dBypassCount = max( this->mG2dBypassCount-1, 0); | |
739 | #endif | |
740 | ||
741 | memcpy(&(this->mLastConfigData), &win_data, sizeof(win_data)); | |
742 | memcpy(this->mLastGscMap, pdata->gsc_map, sizeof(pdata->gsc_map)); | |
743 | if (!this->mVirtualOverlayFlag) | |
744 | this->mLastFbWindow = pdata->fb_window; | |
745 | for (size_t i = 0; i < NUM_HW_WINDOWS; i++) { | |
746 | int layer_idx = pdata->overlay_map[i]; | |
747 | if (layer_idx != -1) { | |
748 | hwc_layer_1_t &layer = contents->hwLayers[layer_idx]; | |
749 | win_map = getDeconWinMap(i, tot_ovly_wins); | |
750 | this->mLastHandles[win_map] = layer.handle; | |
751 | } | |
752 | } | |
753 | ||
754 | return win_data.fence; | |
755 | } | |
756 | ||
757 | int ExynosOverlayDisplay::clearDisplay() | |
758 | { | |
759 | struct s3c_fb_win_config_data win_data; | |
760 | memset(&win_data, 0, sizeof(win_data)); | |
761 | ||
762 | int ret = ioctl(this->mDisplayFd, S3CFB_WIN_CONFIG, &win_data); | |
763 | LOG_ALWAYS_FATAL_IF(ret < 0, | |
764 | "ioctl S3CFB_WIN_CONFIG failed to clear screen: %s", | |
765 | strerror(errno)); | |
766 | // the causes of an empty config failing are all unrecoverable | |
767 | ||
768 | return win_data.fence; | |
769 | } | |
770 | ||
771 | int ExynosOverlayDisplay::set(hwc_display_contents_1_t* contents) | |
772 | { | |
773 | hwc_layer_1_t *fb_layer = NULL; | |
774 | int err = 0; | |
775 | ||
776 | if (this->mPostData.fb_window != NO_FB_NEEDED) { | |
777 | for (size_t i = 0; i < contents->numHwLayers; i++) { | |
778 | if (contents->hwLayers[i].compositionType == | |
779 | HWC_FRAMEBUFFER_TARGET) { | |
780 | this->mPostData.overlay_map[this->mPostData.fb_window] = i; | |
781 | fb_layer = &contents->hwLayers[i]; | |
782 | break; | |
783 | } | |
784 | } | |
785 | ||
786 | if (CC_UNLIKELY(!fb_layer)) { | |
787 | ALOGE("framebuffer target expected, but not provided"); | |
788 | err = -EINVAL; | |
789 | } else { | |
790 | ALOGV("framebuffer target buffer:"); | |
791 | dumpLayer(fb_layer); | |
792 | } | |
793 | } | |
794 | ||
795 | for (size_t i = 0; i < contents->numHwLayers; i++) { | |
796 | if (contents->hwLayers[i].compositionType == HWC_OVERLAY && | |
797 | contents->hwLayers[i].planeAlpha == 0) { | |
798 | close(contents->hwLayers[i].acquireFenceFd); | |
799 | contents->hwLayers[i].acquireFenceFd = -1; | |
800 | contents->hwLayers[i].releaseFenceFd = -1; | |
801 | } | |
802 | } | |
803 | ||
804 | int fence; | |
805 | if (!err) { | |
806 | fence = postFrame(contents); | |
807 | if (fence < 0) | |
808 | err = fence; | |
809 | } | |
810 | ||
811 | if (err) | |
812 | fence = clearDisplay(); | |
813 | ||
814 | for (size_t i = 0; i < NUM_HW_WINDOWS; i++) { | |
815 | if (this->mPostData.overlay_map[i] != -1) { | |
816 | hwc_layer_1_t &layer = | |
817 | contents->hwLayers[this->mPostData.overlay_map[i]]; | |
818 | int dup_fd = dup(fence); | |
819 | if (dup_fd < 0) | |
820 | ALOGW("release fence(%d) dup failed : %s", fence, strerror(errno)); | |
821 | if (this->mPostData.gsc_map[i].mode == exynos5_gsc_map_t::GSC_M2M) { | |
822 | int gsc_idx = this->mPostData.gsc_map[i].idx; | |
823 | ExynosMPP &gsc = *mMPPs[gsc_idx]; | |
824 | if (gsc.mDstBufFence[gsc.mCurrentBuf] >= 0) { | |
825 | close (gsc.mDstBufFence[gsc.mCurrentBuf]); | |
826 | gsc.mDstBufFence[gsc.mCurrentBuf] = -1; | |
827 | } | |
828 | gsc.mDstBufFence[gsc.mCurrentBuf] = dup_fd; | |
829 | gsc.mCurrentBuf = (gsc.mCurrentBuf + 1) % gsc.mNumAvailableDstBuffers; | |
830 | } else if (this->mPostData.gsc_map[i].mode == exynos5_gsc_map_t::GSC_LOCAL) { | |
831 | layer.releaseFenceFd = dup_fd; | |
832 | #ifdef G2D_COMPOSITION | |
833 | } else if (this->mG2dComposition && this->mG2d.win_used[i]) { | |
834 | int idx = this->mG2d.win_used[i] - 1; | |
835 | this->mWinBufFence[idx][this->mG2dCurrentBuffer[idx]] = dup_fd; | |
836 | this->mG2dCurrentBuffer[idx] = (this->mG2dCurrentBuffer[idx] + 1) % NUM_GSC_DST_BUFS; | |
837 | #endif | |
838 | } else { | |
839 | layer.releaseFenceFd = dup_fd; | |
840 | } | |
841 | } | |
842 | } | |
843 | ||
844 | if (contents->numHwLayers >= 1) { | |
845 | hwc_layer_1_t &layer = contents->hwLayers[contents->numHwLayers-1]; | |
846 | ||
847 | if (mVirtualOverlayFlag && layer.compositionType == HWC_FRAMEBUFFER_TARGET) { | |
848 | int dup_fd = dup(fence); | |
849 | if (dup_fd < 0) { | |
850 | ALOGW("release fence(%d) dup failed in FB_TARGET: %s", fence, strerror(errno)); | |
851 | } else { | |
852 | layer.releaseFenceFd = dup_fd; | |
853 | } | |
854 | } | |
855 | } | |
856 | ||
857 | contents->retireFenceFd = fence; | |
858 | ||
859 | mHwc->hwc_ctrl.max_num_ovly = mAllowedOverlays; | |
860 | ||
861 | return err; | |
862 | } | |
863 | ||
864 | int ExynosOverlayDisplay::getCompModeSwitch() | |
865 | { | |
866 | unsigned int tot_win_size = 0, updateFps = 0; | |
867 | unsigned int lcd_size = this->mXres * this->mYres; | |
868 | uint64_t TimeStampDiff; | |
869 | float Temp; | |
870 | ||
871 | if (!mHwc->hwc_ctrl.dynamic_recomp_mode) { | |
872 | mHwc->LastModeSwitchTimeStamp = 0; | |
873 | mHwc->CompModeSwitch = NO_MODE_SWITCH; | |
874 | return 0; | |
875 | } | |
876 | ||
877 | /* initialize the Timestamps */ | |
878 | if (!mHwc->LastModeSwitchTimeStamp) { | |
879 | mHwc->LastModeSwitchTimeStamp = mHwc->LastUpdateTimeStamp; | |
880 | mHwc->CompModeSwitch = NO_MODE_SWITCH; | |
881 | return 0; | |
882 | } | |
883 | ||
884 | /* If video layer is there, skip the mode switch */ | |
885 | if (mYuvLayers || mGscLayers >= 2 ) { | |
886 | if (mHwc->CompModeSwitch != HWC_2_GLES) { | |
887 | return 0; | |
888 | } else { | |
889 | mHwc->CompModeSwitch = GLES_2_HWC; | |
890 | mHwc->updateCallCnt = 0; | |
891 | mHwc->LastModeSwitchTimeStamp = mHwc->LastUpdateTimeStamp; | |
892 | ALOGI("[DYNAMIC_RECOMP] GLES_2_HWC by video layer"); | |
893 | return GLES_2_HWC; | |
894 | } | |
895 | } | |
896 | ||
897 | /* Mode Switch is not required if total pixels are not more than the threshold */ | |
898 | if ((uint32_t)mHwc->incomingPixels <= lcd_size * HWC_FIMD_BW_TH) { | |
899 | if (mHwc->CompModeSwitch != HWC_2_GLES) { | |
900 | return 0; | |
901 | } else { | |
902 | mHwc->CompModeSwitch = GLES_2_HWC; | |
903 | mHwc->updateCallCnt = 0; | |
904 | mHwc->LastModeSwitchTimeStamp = mHwc->LastUpdateTimeStamp; | |
905 | ALOGI("[DYNAMIC_RECOMP] GLES_2_HWC by BW check"); | |
906 | return GLES_2_HWC; | |
907 | } | |
908 | } | |
909 | ||
910 | /* | |
911 | * There will be at least one composition call per one minute (because of time update) | |
912 | * To minimize the analysis overhead, just analyze it once in a second | |
913 | */ | |
914 | TimeStampDiff = systemTime(SYSTEM_TIME_MONOTONIC) - mHwc->LastModeSwitchTimeStamp; | |
915 | ||
916 | /* check fps every 250ms from LastModeSwitchTimeStamp*/ | |
917 | if (TimeStampDiff < (VSYNC_INTERVAL * 15)) { | |
918 | return 0; | |
919 | } | |
920 | mHwc->LastModeSwitchTimeStamp = mHwc->LastUpdateTimeStamp; | |
921 | Temp = (VSYNC_INTERVAL * 60) / TimeStampDiff; | |
922 | updateFps = (int)(mHwc->updateCallCnt * Temp + 0.5); | |
923 | mHwc->updateCallCnt = 0; | |
924 | /* | |
925 | * FPS estimation. | |
926 | * If FPS is lower than HWC_FPS_TH, try to switch the mode to GLES | |
927 | */ | |
928 | if (updateFps < HWC_FPS_TH) { | |
929 | if (mHwc->CompModeSwitch != HWC_2_GLES) { | |
930 | mHwc->CompModeSwitch = HWC_2_GLES; | |
931 | ALOGI("[DYNAMIC_RECOMP] HWC_2_GLES by low FPS(%d)", updateFps); | |
932 | return HWC_2_GLES; | |
933 | } else { | |
934 | return 0; | |
935 | } | |
936 | } else { | |
937 | if (mHwc->CompModeSwitch == HWC_2_GLES) { | |
938 | mHwc->CompModeSwitch = GLES_2_HWC; | |
939 | ALOGI("[DYNAMIC_RECOMP] GLES_2_HWC by high FPS(%d)", updateFps); | |
940 | return GLES_2_HWC; | |
941 | } else { | |
942 | return 0; | |
943 | } | |
944 | } | |
945 | ||
946 | return 0; | |
947 | } | |
948 | ||
949 | int32_t ExynosOverlayDisplay::getDisplayAttributes(const uint32_t attribute) | |
950 | { | |
951 | switch(attribute) { | |
952 | case HWC_DISPLAY_VSYNC_PERIOD: | |
953 | return this->mVsyncPeriod; | |
954 | ||
955 | case HWC_DISPLAY_WIDTH: | |
956 | return this->mXres; | |
957 | ||
958 | case HWC_DISPLAY_HEIGHT: | |
959 | return this->mYres; | |
960 | ||
961 | case HWC_DISPLAY_DPI_X: | |
962 | return this->mXdpi; | |
963 | ||
964 | case HWC_DISPLAY_DPI_Y: | |
965 | return this->mYdpi; | |
966 | ||
967 | default: | |
968 | ALOGE("unknown display attribute %u", attribute); | |
969 | return -EINVAL; | |
970 | } | |
971 | } | |
972 | ||
973 | void ExynosOverlayDisplay::skipStaticLayers(hwc_display_contents_1_t* contents) | |
974 | { | |
975 | static int init_flag = 0; | |
976 | int last_ovly_lay_idx = -1; | |
977 | ||
978 | mVirtualOverlayFlag = 0; | |
979 | mLastOverlayWindowIndex = -1; | |
980 | ||
981 | if (!mHwc->hwc_ctrl.skip_static_layer_mode) | |
982 | return; | |
983 | ||
984 | if (mBypassSkipStaticLayer) | |
985 | return; | |
986 | ||
987 | if (contents->flags & HWC_GEOMETRY_CHANGED) { | |
988 | init_flag = 0; | |
989 | return; | |
990 | } | |
991 | ||
992 | for (size_t i = 0; i < NUM_HW_WINDOWS; i++) { | |
993 | if (mPostData.overlay_map[i] != -1) { | |
994 | last_ovly_lay_idx = mPostData.overlay_map[i]; | |
995 | mLastOverlayWindowIndex = i; | |
996 | } | |
997 | } | |
998 | ||
999 | if ((last_ovly_lay_idx == -1) || !mFbNeeded || | |
1000 | ((mLastFb - mFirstFb + 1) > NUM_VIRT_OVER)) { | |
1001 | init_flag = 0; | |
1002 | return; | |
1003 | } | |
1004 | mLastOverlayLayerIndex = last_ovly_lay_idx; | |
1005 | ||
1006 | if (init_flag == 1) { | |
1007 | for (size_t i = mFirstFb; i <= mLastFb; i++) { | |
1008 | hwc_layer_1_t &layer = contents->hwLayers[i]; | |
1009 | if (!layer.handle || (layer.flags & HWC_SKIP_LAYER) || (mLastLayerHandles[i - mFirstFb] != layer.handle)) { | |
1010 | init_flag = 0; | |
1011 | return; | |
1012 | } | |
1013 | } | |
1014 | ||
1015 | mVirtualOverlayFlag = 1; | |
1016 | for (size_t i = 0; i < contents->numHwLayers-1; i++) { | |
1017 | hwc_layer_1_t &layer = contents->hwLayers[i]; | |
1018 | if (layer.compositionType == HWC_FRAMEBUFFER) { | |
1019 | layer.compositionType = HWC_OVERLAY; | |
1020 | mLayerInfos[i]->compositionType = layer.compositionType; | |
1021 | mLayerInfos[i]->mCheckOverlayFlag |= eSkipStaticLayer; | |
1022 | } | |
1023 | } | |
1024 | mLastFbWindow = mPostData.fb_window; | |
1025 | return; | |
1026 | } | |
1027 | ||
1028 | init_flag = 1; | |
1029 | for (size_t i = 0; i < NUM_VIRT_OVER; i++) | |
1030 | mLastLayerHandles[i] = 0; | |
1031 | ||
1032 | for (size_t i = mFirstFb; i <= mLastFb; i++) { | |
1033 | hwc_layer_1_t &layer = contents->hwLayers[i]; | |
1034 | mLastLayerHandles[i - mFirstFb] = layer.handle; | |
1035 | } | |
1036 | ||
1037 | return; | |
1038 | } | |
1039 | ||
1040 | void ExynosOverlayDisplay::forceYuvLayersToFb(hwc_display_contents_1_t *contents) | |
1041 | { | |
1042 | } | |
1043 | ||
1044 | void ExynosOverlayDisplay::handleOffscreenRendering(hwc_layer_1_t &layer, hwc_display_contents_1_t *contents, int index) | |
1045 | { | |
1046 | } | |
1047 | ||
1048 | void ExynosOverlayDisplay::determineYuvOverlay(hwc_display_contents_1_t *contents) | |
1049 | { | |
1050 | mPopupPlayYuvContents = false; | |
1051 | mForceOverlayLayerIndex = -1; | |
1052 | mHasDrmSurface = false; | |
1053 | mYuvLayers = 0; | |
1054 | mHasCropSurface = false; | |
1055 | for (size_t i = 0; i < contents->numHwLayers; i++) { | |
1056 | hwc_layer_1_t &layer = contents->hwLayers[i]; | |
1057 | if (layer.handle) { | |
1058 | private_handle_t *handle = private_handle_t::dynamicCast(layer.handle); | |
1059 | if (getDrmMode(handle->flags) != NO_DRM) { | |
1060 | this->mHasDrmSurface = true; | |
1061 | mForceOverlayLayerIndex = i; | |
1062 | } | |
1063 | ||
1064 | /* check yuv surface */ | |
1065 | if (mMPPs[0]->formatRequiresGsc(handle->format)) { | |
1066 | layer.sourceCropf.top = (int)layer.sourceCropf.top; | |
1067 | layer.sourceCropf.left = (int)layer.sourceCropf.left; | |
1068 | layer.sourceCropf.bottom = (int)(layer.sourceCropf.bottom + 0.9); | |
1069 | layer.sourceCropf.right = (int)(layer.sourceCropf.right + 0.9); | |
1070 | if (isOverlaySupported(contents->hwLayers[i], i)) { | |
1071 | this->mYuvLayers++; | |
1072 | if (this->mHasDrmSurface == false) | |
1073 | mForceOverlayLayerIndex = i; | |
1074 | } else if (i > 0 && layer.planeAlpha > 0) { | |
1075 | mForceFb = true; | |
1076 | } | |
1077 | } | |
1078 | ||
1079 | if (handle->flags & GRALLOC_USAGE_HW_CAMERA_MASK) { | |
1080 | mAllowedOverlays = mHwc->hwc_ctrl.max_num_ovly; | |
1081 | mHwc->hwc_ctrl.max_num_ovly = 3; | |
1082 | } | |
1083 | ||
1084 | handleOffscreenRendering(layer, contents, i); | |
1085 | } | |
1086 | ||
1087 | #if defined(USE_GRALLOC_FLAG_FOR_HDMI) || defined(USES_VIRTUAL_DISPLAY) | |
1088 | /* during rotation, it use gpu comosition */ | |
1089 | if (layer.flags & HWC_SCREENSHOT_ANIMATOR_LAYER) | |
1090 | mForceFb = true; | |
1091 | #endif | |
1092 | } | |
1093 | mPopupPlayYuvContents = !!(((mYuvLayers == 1) || (this->mHasDrmSurface)) && (mForceOverlayLayerIndex > 0)); | |
1094 | if (mYuvLayers > 1) { | |
1095 | mHwc->allowOTF = false; | |
1096 | if (mMPPs[0]->isOTF()) | |
1097 | mForceFb = true; | |
1098 | } else { | |
1099 | mHwc->allowOTF = true; | |
1100 | } | |
1101 | ||
1102 | #ifdef USE_FB_PHY_LINEAR | |
1103 | if ((!mHasDrmSurface) && | |
1104 | #ifdef G2D_COMPOSITION | |
1105 | (mG2dBypassCount > 0) && | |
1106 | #endif | |
1107 | (contents->flags & HWC_GEOMETRY_CHANGED)) | |
1108 | mForceFb = true; | |
1109 | #endif | |
1110 | } | |
1111 | ||
1112 | void ExynosOverlayDisplay::determineSupportedOverlays(hwc_display_contents_1_t *contents) | |
1113 | { | |
1114 | bool videoLayer = false; | |
1115 | ||
1116 | mFbNeeded = false; | |
1117 | mFirstFb = ~0; | |
1118 | mLastFb = 0; | |
1119 | ||
1120 | for (size_t i = 0; i < NUM_HW_WINDOWS; i++) | |
1121 | mPostData.overlay_map[i] = -1; | |
1122 | ||
1123 | // find unsupported overlays | |
1124 | for (size_t i = 0; i < contents->numHwLayers; i++) { | |
1125 | hwc_layer_1_t &layer = contents->hwLayers[i]; | |
1126 | ||
1127 | if (layer.compositionType == HWC_FRAMEBUFFER_TARGET) { | |
1128 | ALOGV("\tlayer %u: framebuffer target", i); | |
1129 | mLayerInfos[i]->compositionType = layer.compositionType; | |
1130 | continue; | |
1131 | } | |
1132 | ||
1133 | if (layer.compositionType == HWC_BACKGROUND && !mForceFb) { | |
1134 | ALOGV("\tlayer %u: background supported", i); | |
1135 | dumpLayer(&contents->hwLayers[i]); | |
1136 | mLayerInfos[i]->compositionType = layer.compositionType; | |
1137 | continue; | |
1138 | } | |
1139 | ||
1140 | if (layer.handle) { | |
1141 | private_handle_t *handle = private_handle_t::dynamicCast(layer.handle); | |
1142 | if ((int)get_yuv_planes(halFormatToV4L2Format(handle->format)) > 0) { | |
1143 | videoLayer = true; | |
1144 | if (!mHwc->hdmi_hpd && mHwc->mS3DMode == S3D_MODE_READY) | |
1145 | mHwc->mS3DMode = S3D_MODE_RUNNING; | |
1146 | } | |
1147 | if ((!mPopupPlayYuvContents) | |
1148 | || ((uint32_t)mForceOverlayLayerIndex == i)) { | |
1149 | mHwc->incomingPixels += WIDTH(layer.displayFrame) * HEIGHT(layer.displayFrame); | |
1150 | if ((!mHasCropSurface || mPopupPlayYuvContents) || | |
1151 | ((mHasDrmSurface) && ((uint32_t)mForceOverlayLayerIndex == i))) { | |
1152 | if (isOverlaySupported(contents->hwLayers[i], i) && | |
1153 | !(mForceFb && (getDrmMode(handle->flags) == NO_DRM)) && (!mHwc->hwc_ctrl.dynamic_recomp_mode || | |
1154 | ((mHwc->CompModeSwitch != HWC_2_GLES) || | |
1155 | (getDrmMode(handle->flags) != NO_DRM)))) { | |
1156 | mHwc->totPixels += WIDTH(layer.displayFrame) * HEIGHT(layer.displayFrame); | |
1157 | ALOGV("\tlayer %u: overlay supported", i); | |
1158 | layer.compositionType = HWC_OVERLAY; | |
1159 | mLayerInfos[i]->compositionType = layer.compositionType; | |
1160 | if (mPopupPlayYuvContents) | |
1161 | layer.hints = HWC_HINT_CLEAR_FB; | |
1162 | dumpLayer(&contents->hwLayers[i]); | |
1163 | continue; | |
1164 | } else { | |
1165 | if (mForceFb) | |
1166 | mLayerInfos[i]->mCheckOverlayFlag |= eForceFbEnabled; | |
1167 | else if (mHwc->hwc_ctrl.dynamic_recomp_mode && mHwc->CompModeSwitch == HWC_2_GLES) | |
1168 | mLayerInfos[i]->mCheckOverlayFlag |= eDynamicRecomposition; | |
1169 | else if (isOverlaySupported(contents->hwLayers[i], i)) | |
1170 | mLayerInfos[i]->mCheckOverlayFlag |= eUnknown; | |
1171 | } | |
1172 | } else { | |
1173 | if (mHasCropSurface == true) | |
1174 | mLayerInfos[i]->mCheckOverlayFlag |= eUnsupportedCoordinate; | |
1175 | else | |
1176 | mLayerInfos[i]->mCheckOverlayFlag |= eUnknown; | |
1177 | } | |
1178 | } else { | |
1179 | /* There is popup video but this layer is not popup video layer */ | |
1180 | mLayerInfos[i]->mCheckOverlayFlag |= eHasPopupVideo; | |
1181 | } | |
1182 | } else { | |
1183 | mLayerInfos[i]->mCheckOverlayFlag |= eInvalidHandle; | |
1184 | } | |
1185 | ||
1186 | if (!mFbNeeded) { | |
1187 | mFirstFb = i; | |
1188 | mFbNeeded = true; | |
1189 | } | |
1190 | mLastFb = i; | |
1191 | layer.compositionType = HWC_FRAMEBUFFER; | |
1192 | mLayerInfos[i]->compositionType = layer.compositionType; | |
1193 | ||
1194 | dumpLayer(&contents->hwLayers[i]); | |
1195 | } | |
1196 | ||
1197 | if (!mHwc->hdmi_hpd && mHwc->mS3DMode == S3D_MODE_RUNNING && !videoLayer && !mForceFb) | |
1198 | mHwc->mS3DMode = S3D_MODE_DISABLED; | |
1199 | hwc_rect_t base_rect; | |
1200 | hwc_rect_t intersect_rect; | |
1201 | private_handle_t *handle = NULL; | |
1202 | for (size_t i = 0; i < contents->numHwLayers; i++) { | |
1203 | hwc_layer_1_t &layer = contents->hwLayers[i]; | |
1204 | if (layer.handle) | |
1205 | handle = private_handle_t::dynamicCast(layer.handle); | |
1206 | if (layer.compositionType == HWC_OVERLAY) { | |
1207 | if (i == 0) { | |
1208 | base_rect = layer.displayFrame; | |
1209 | } else if (hasPlaneAlpha(layer) || (handle && hasAlpha(handle->format) && mMPPs[0]->isProcessingRequired(layer, handle->format))) { | |
1210 | //if alpha layer is not completely overlapped with base layer, bypass the alpha layer to GLES. | |
1211 | intersect_rect = intersection(base_rect, layer.displayFrame); | |
1212 | if (!rectEqual(intersect_rect, layer.displayFrame)) { | |
1213 | layer.compositionType = HWC_FRAMEBUFFER; | |
1214 | mLayerInfos[i]->mCheckOverlayFlag |= eUnsupportedBlending; | |
1215 | mFirstFb = min(mFirstFb, i); | |
1216 | mLastFb = max(mLastFb, i); | |
1217 | mFbNeeded = true; | |
1218 | break; | |
1219 | } | |
1220 | } | |
1221 | } else { | |
1222 | // if one of the bottom layer is HWC_FRAMEBUFFER type, no need to force the alpha layer to FRAMEBUFFER type. | |
1223 | break; | |
1224 | } | |
1225 | } | |
1226 | mFirstFb = min(mFirstFb, (size_t)NUM_HW_WINDOWS-1); | |
1227 | // can't composite overlays sandwiched between framebuffers | |
1228 | if (mFbNeeded) { | |
1229 | for (size_t i = mFirstFb; i < mLastFb; i++) { | |
1230 | if (mPopupPlayYuvContents && ((uint32_t)mForceOverlayLayerIndex == i)) { | |
1231 | mFirstFb = 1; | |
1232 | break; | |
1233 | } | |
1234 | hwc_layer_1_t &layer = contents->hwLayers[i]; | |
1235 | if (layer.handle) { | |
1236 | private_handle_t *handle = private_handle_t::dynamicCast(layer.handle); | |
1237 | if (getDrmMode(handle->flags) == NO_DRM) { | |
1238 | contents->hwLayers[i].compositionType = HWC_FRAMEBUFFER; | |
1239 | mLayerInfos[i]->compositionType = contents->hwLayers[i].compositionType; | |
1240 | mLayerInfos[i]->mCheckOverlayFlag |= eSandwitchedBetweenGLES; | |
1241 | } | |
1242 | } | |
1243 | } | |
1244 | } | |
1245 | } | |
1246 | ||
1247 | void ExynosOverlayDisplay::determineBandwidthSupport(hwc_display_contents_1_t *contents) | |
1248 | { | |
1249 | // Incrementally try to add our supported layers to hardware windows. | |
1250 | // If adding a layer would violate a hardware constraint, force it | |
1251 | // into the framebuffer and try again. (Revisiting the entire list is | |
1252 | // necessary because adding a layer to the framebuffer can cause other | |
1253 | // windows to retroactively violate constraints.) | |
1254 | bool changed; | |
1255 | this->mBypassSkipStaticLayer = false; | |
1256 | unsigned int cannotComposeFlag = 0; | |
1257 | bool addFB = true; | |
1258 | hwc_rect windowIntersection; | |
1259 | windowIntersection.left = 0; | |
1260 | windowIntersection.top = 0; | |
1261 | windowIntersection.right = mXres; | |
1262 | windowIntersection.bottom = mYres; | |
1263 | int intersectionCnt = 0; | |
1264 | bool reduceAvailableWindowCnt = false; | |
1265 | // Initialize to inverse values so that | |
1266 | // min(left, l) = l, min(top, t) = t | |
1267 | // max(right, r) = r, max(bottom, b) = b | |
1268 | // for all l, t, r, b | |
1269 | mFbUpdateRegion.left = mXres; | |
1270 | mFbUpdateRegion.top = mYres; | |
1271 | mFbUpdateRegion.right = 0; | |
1272 | mFbUpdateRegion.bottom = 0; | |
1273 | ||
1274 | uint32_t pixel_used[MAX_NUM_FIMD_DMA_CH]; | |
1275 | do { | |
1276 | android::Vector<hwc_rect> rects[MAX_NUM_FIMD_DMA_CH]; | |
1277 | android::Vector<hwc_rect> overlaps[MAX_NUM_FIMD_DMA_CH]; | |
1278 | int dma_ch_idx; | |
1279 | size_t win_idx = 0; | |
1280 | size_t windows_left; | |
1281 | memset(&pixel_used[0], 0, sizeof(pixel_used)); | |
1282 | mGscUsed = false; | |
1283 | windowIntersection.left = 0; | |
1284 | windowIntersection.top = 0; | |
1285 | windowIntersection.right = mXres; | |
1286 | windowIntersection.bottom = mYres; | |
1287 | intersectionCnt = 0; | |
1288 | ||
1289 | if (mFbNeeded) { | |
1290 | hwc_rect_t fb_rect; | |
1291 | fb_rect.top = fb_rect.left = 0; | |
1292 | fb_rect.right = this->mXres - 1; | |
1293 | fb_rect.bottom = this->mYres - 1; | |
1294 | dma_ch_idx = FIMD_DMA_CH_IDX[mFirstFb]; | |
1295 | pixel_used[dma_ch_idx] = (uint32_t) (this->mXres * this->mYres); | |
1296 | win_idx = (win_idx == mFirstFb) ? (win_idx + 1) : win_idx; | |
1297 | #ifdef USE_FB_PHY_LINEAR | |
1298 | windows_left = 1; | |
1299 | #ifdef G2D_COMPOSITION | |
1300 | if (this->mG2dComposition) | |
1301 | windows_left = NUM_HW_WIN_FB_PHY - 1; | |
1302 | #endif | |
1303 | #else | |
1304 | windows_left = mHwc->hwc_ctrl.max_num_ovly - 1; | |
1305 | #endif | |
1306 | if (reduceAvailableWindowCnt) | |
1307 | windows_left = min(windows_left, mMaxWindowOverlapCnt - 1); | |
1308 | rects[dma_ch_idx].push_back(fb_rect); | |
1309 | if (addFB) { | |
1310 | addFB = false; | |
1311 | mHwc->totPixels += mXres * mYres; | |
1312 | } | |
1313 | } | |
1314 | else { | |
1315 | #ifdef USE_FB_PHY_LINEAR | |
1316 | windows_left = 1; | |
1317 | #ifdef G2D_COMPOSITION | |
1318 | if (this->mG2dComposition) | |
1319 | windows_left = NUM_HW_WIN_FB_PHY; | |
1320 | #endif | |
1321 | #else | |
1322 | windows_left = mHwc->hwc_ctrl.max_num_ovly; | |
1323 | #endif | |
1324 | if (reduceAvailableWindowCnt) | |
1325 | windows_left = min(windows_left, mMaxWindowOverlapCnt); | |
1326 | } | |
1327 | ||
1328 | changed = false; | |
1329 | mGscLayers = 0; | |
1330 | mCurrentGscIndex = 0; | |
1331 | mCurrentRGBMPPIndex = 0; | |
1332 | bool switchingOTF = false; | |
1333 | reduceAvailableWindowCnt = false; | |
1334 | for (size_t i = 0; i < contents->numHwLayers; i++) { | |
1335 | hwc_layer_1_t &layer = contents->hwLayers[i]; | |
1336 | if ((layer.flags & HWC_SKIP_LAYER) || | |
1337 | layer.compositionType == HWC_FRAMEBUFFER_TARGET) | |
1338 | continue; | |
1339 | ||
1340 | private_handle_t *handle = private_handle_t::dynamicCast( | |
1341 | layer.handle); | |
1342 | ||
1343 | if (!layer.planeAlpha) | |
1344 | continue; | |
1345 | ||
1346 | // we've already accounted for the framebuffer above | |
1347 | if (layer.compositionType == HWC_FRAMEBUFFER) | |
1348 | continue; | |
1349 | ||
1350 | // only layer 0 can be HWC_BACKGROUND, so we can | |
1351 | // unconditionally allow it without extra checks | |
1352 | if (layer.compositionType == HWC_BACKGROUND) { | |
1353 | windows_left--; | |
1354 | continue; | |
1355 | } | |
1356 | dma_ch_idx = FIMD_DMA_CH_IDX[win_idx]; | |
1357 | ||
1358 | size_t pixels_needed = 0; | |
1359 | if (getDrmMode(handle->flags) != SECURE_DRM) | |
1360 | pixels_needed = getRequiredPixels(layer, mXres, mYres); | |
1361 | else | |
1362 | pixels_needed = WIDTH(layer.displayFrame) * | |
1363 | HEIGHT(layer.displayFrame); | |
1364 | ||
1365 | cannotComposeFlag = 0; | |
1366 | bool can_compose = windows_left && (win_idx < NUM_HW_WINDOWS) && | |
1367 | ((pixel_used[dma_ch_idx] + pixels_needed) <= | |
1368 | (uint32_t)this->mDmaChannelMaxBandwidth[dma_ch_idx]); | |
1369 | if (windows_left <= 0 || (win_idx >= NUM_HW_WINDOWS)) | |
1370 | cannotComposeFlag |= eInsufficientWindow; | |
1371 | if ((pixel_used[dma_ch_idx] + pixels_needed) > (uint32_t)this->mDmaChannelMaxBandwidth[dma_ch_idx]) | |
1372 | cannotComposeFlag |= eInsufficientBandwidth; | |
1373 | ||
1374 | int gsc_index = getMPPForUHD(layer); | |
1375 | ||
1376 | bool gsc_required = mMPPs[gsc_index]->isProcessingRequired(layer, handle->format); | |
1377 | if (gsc_required) { | |
1378 | if (mHasDrmSurface && getDrmMode(handle->flags) == NO_DRM && MAX_VIDEO_LAYERS == 1) { | |
1379 | can_compose = false; | |
1380 | cannotComposeFlag = eHasDRMVideo; | |
1381 | } | |
1382 | if (mGscLayers >= MAX_VIDEO_LAYERS) { | |
1383 | can_compose = can_compose && !mGscUsed; | |
1384 | if (mGscUsed) | |
1385 | cannotComposeFlag |= eInsufficientMPP; | |
1386 | } | |
1387 | if (mHwc->hwc_ctrl.num_of_video_ovly <= mGscLayers) { | |
1388 | can_compose = false; | |
1389 | cannotComposeFlag |= eInsufficientMPP; | |
1390 | } | |
1391 | if (switchingOTF) { | |
1392 | can_compose = false; | |
1393 | cannotComposeFlag |= eSwitchingLocalPath; | |
1394 | } | |
1395 | if (mOtfMode == OTF_RUNNING && win_idx > 0) | |
1396 | switchingOTF = true; | |
1397 | if (multipleRGBScaling(handle->format)) { | |
1398 | can_compose = false; | |
1399 | cannotComposeFlag |= eRGBLayerDuringVideoPlayback; | |
1400 | } | |
1401 | } | |
1402 | ||
1403 | // hwc_rect_t right and bottom values are normally exclusive; | |
1404 | // the intersection logic is simpler if we make them inclusive | |
1405 | hwc_rect_t visible_rect = layer.displayFrame; | |
1406 | visible_rect.right--; visible_rect.bottom--; | |
1407 | ||
1408 | if (can_compose) { | |
1409 | switch (this->mDmaChannelMaxOverlapCount[dma_ch_idx]) { | |
1410 | case 1: // It means, no layer overlap is allowed | |
1411 | for (size_t j = 0; j < rects[dma_ch_idx].size(); j++) | |
1412 | if (intersect(visible_rect, rects[dma_ch_idx].itemAt(j))) { | |
1413 | can_compose = false; | |
1414 | cannotComposeFlag |= eInsufficientOverlapCount; | |
1415 | } | |
1416 | break; | |
1417 | case 2: //It means, upto 2 layer overlap is allowed. | |
1418 | for (size_t j = 0; j < overlaps[dma_ch_idx].size(); j++) | |
1419 | if (intersect(visible_rect, overlaps[dma_ch_idx].itemAt(j))) { | |
1420 | can_compose = false; | |
1421 | cannotComposeFlag |= eInsufficientOverlapCount; | |
1422 | } | |
1423 | break; | |
1424 | default: | |
1425 | break; | |
1426 | } | |
1427 | if (!can_compose) | |
1428 | this->mBypassSkipStaticLayer = true; | |
1429 | } | |
1430 | ||
1431 | if (!can_compose) { | |
1432 | if (getDrmMode(handle->flags) != NO_DRM) { | |
1433 | mFirstFb = 1; | |
1434 | changed = true; | |
1435 | break; | |
1436 | } else { | |
1437 | layer.compositionType = HWC_FRAMEBUFFER; | |
1438 | mLayerInfos[i]->compositionType = layer.compositionType; | |
1439 | mLayerInfos[i]->mCheckOverlayFlag |= cannotComposeFlag; | |
1440 | if (!mFbNeeded) { | |
1441 | mFirstFb = mLastFb = i; | |
1442 | mFbNeeded = true; | |
1443 | } | |
1444 | else { | |
1445 | mFirstFb = min(i, mFirstFb); | |
1446 | mLastFb = max(i, mLastFb); | |
1447 | } | |
1448 | changed = true; | |
1449 | mFirstFb = min(mFirstFb, (size_t)NUM_HW_WINDOWS-1); | |
1450 | mHwc->totPixels -= WIDTH(layer.displayFrame) * HEIGHT(layer.displayFrame); | |
1451 | break; | |
1452 | } | |
1453 | } | |
1454 | ||
1455 | for (size_t j = 0; j < rects[dma_ch_idx].size(); j++) { | |
1456 | const hwc_rect_t &other_rect = rects[dma_ch_idx].itemAt(j); | |
1457 | if (intersect(visible_rect, other_rect)) | |
1458 | overlaps[dma_ch_idx].push_back(intersection(visible_rect, other_rect)); | |
1459 | } | |
1460 | ||
1461 | rects[dma_ch_idx].push_back(visible_rect); | |
1462 | pixel_used[dma_ch_idx] += pixels_needed; | |
1463 | win_idx++; | |
1464 | win_idx = (win_idx == mFirstFb) ? (win_idx + 1) : win_idx; | |
1465 | win_idx = min(win_idx, NUM_HW_WINDOWS - 1); | |
1466 | windows_left--; | |
1467 | if (gsc_required) { | |
1468 | mGscUsed = true; | |
1469 | mGscLayers++; | |
1470 | } | |
1471 | ||
1472 | if (intersect(visible_rect, windowIntersection)) { | |
1473 | windowIntersection = intersection(visible_rect, windowIntersection); | |
1474 | intersectionCnt++; | |
1475 | } else { | |
1476 | windowIntersection = {0, 0, 0, 0}; | |
1477 | intersectionCnt = 0; | |
1478 | } | |
1479 | } | |
1480 | if (mFbNeeded && intersectionCnt != 0) | |
1481 | intersectionCnt++; | |
1482 | if (changed) { | |
1483 | for (size_t i = mFirstFb; i < mLastFb; i++) { | |
1484 | hwc_layer_1_t &layer = contents->hwLayers[i]; | |
1485 | if (layer.handle) { | |
1486 | private_handle_t *handle = private_handle_t::dynamicCast(layer.handle); | |
1487 | if (getDrmMode(handle->flags) == NO_DRM) { | |
1488 | contents->hwLayers[i].compositionType = HWC_FRAMEBUFFER; | |
1489 | mLayerInfos[i]->compositionType = contents->hwLayers[i].compositionType; | |
1490 | mLayerInfos[i]->mCheckOverlayFlag |= eSandwitchedBetweenGLES; | |
1491 | } | |
1492 | } | |
1493 | } | |
1494 | } | |
1495 | handleTotalBandwidthOverload(contents); | |
1496 | if (intersectionCnt > mMaxWindowOverlapCnt) { | |
1497 | HLOGD("Total Overlap Cnt(%d) > Max Overlap Cnt(%d)", intersectionCnt, mMaxWindowOverlapCnt); | |
1498 | changed = true; | |
1499 | reduceAvailableWindowCnt = true; | |
1500 | } | |
1501 | } while(changed); | |
1502 | ||
1503 | if (mGscLayers == 0) | |
1504 | mHwc->allowOTF = true; | |
1505 | ||
1506 | if (mPopupPlayYuvContents) { | |
1507 | mFbUpdateRegion.left = 0; | |
1508 | mFbUpdateRegion.top = 0; | |
1509 | mFbUpdateRegion.right = mXres; | |
1510 | mFbUpdateRegion.bottom = mYres; | |
1511 | return; | |
1512 | } | |
1513 | ||
1514 | for (size_t i = mFirstFb; i <= mLastFb; i++) | |
1515 | mFbUpdateRegion = expand(mFbUpdateRegion, contents->hwLayers[i].displayFrame); | |
1516 | ||
1517 | for (size_t i = mLastFb + 1; i < contents->numHwLayers; i++) { | |
1518 | hwc_layer_1_t &layer = contents->hwLayers[i]; | |
1519 | if (layer.compositionType == HWC_OVERLAY && layer.planeAlpha > 0 && layer.planeAlpha < 255) | |
1520 | mFbUpdateRegion = expand(mFbUpdateRegion, contents->hwLayers[i].displayFrame); | |
1521 | } | |
1522 | ||
1523 | int minWidth = BURSTLEN_BYTES * 8 / formatToBpp(HAL_PIXEL_FORMAT_RGBA_8888); | |
1524 | int w = WIDTH(mFbUpdateRegion); | |
1525 | if (w < minWidth) { | |
1526 | if (mFbUpdateRegion.left + minWidth <= mXres) | |
1527 | mFbUpdateRegion.right = mFbUpdateRegion.left + minWidth; | |
1528 | else | |
1529 | mFbUpdateRegion.left = mFbUpdateRegion.right - minWidth; | |
1530 | } | |
1531 | } | |
1532 | ||
1533 | void ExynosOverlayDisplay::assignWindows(hwc_display_contents_1_t *contents) | |
1534 | { | |
1535 | unsigned int nextWindow = 0; | |
1536 | ||
1537 | for (size_t i = 0; i < contents->numHwLayers; i++) { | |
1538 | hwc_layer_1_t &layer = contents->hwLayers[i]; | |
1539 | ||
1540 | if (!layer.planeAlpha) | |
1541 | continue; | |
1542 | ||
1543 | if (!mPopupPlayYuvContents) { | |
1544 | if (mFbNeeded && i == mFirstFb) { | |
1545 | ALOGV("assigning framebuffer to window %u\n", | |
1546 | nextWindow); | |
1547 | mPostData.fb_window = nextWindow; | |
1548 | nextWindow++; | |
1549 | continue; | |
1550 | } | |
1551 | } | |
1552 | ||
1553 | if (layer.handle) { | |
1554 | private_handle_t *handle = private_handle_t::dynamicCast(layer.handle); | |
1555 | if (ExynosMPP::isFormatSupportedByGscOtf(handle->format)) { | |
1556 | /* in case of changing compostiontype form GSC to FRAMEBUFFER for yuv layer */ | |
1557 | if ((mConfigMode == 1) && (layer.compositionType == HWC_FRAMEBUFFER)) { | |
1558 | mForceFbYuvLayer = 1; | |
1559 | mConfigMode = 0; | |
1560 | mCountSameConfig = 0; | |
1561 | /* for prepare */ | |
1562 | mForceFb = 1; | |
1563 | mRetry = true; | |
1564 | return; | |
1565 | } | |
1566 | } | |
1567 | } | |
1568 | if (layer.compositionType != HWC_FRAMEBUFFER && | |
1569 | layer.compositionType != HWC_FRAMEBUFFER_TARGET) { | |
1570 | ALOGV("assigning layer %u to window %u", i, nextWindow); | |
1571 | this->mPostData.overlay_map[nextWindow] = i; | |
1572 | if (layer.compositionType == HWC_OVERLAY) { | |
1573 | private_handle_t *handle = | |
1574 | private_handle_t::dynamicCast(layer.handle); | |
1575 | if (mMPPs[0]->isProcessingRequired(layer, handle->format)) { | |
1576 | if (assignGscLayer(layer, i, nextWindow)) | |
1577 | mCurrentGscIndex++; | |
1578 | } | |
1579 | } | |
1580 | nextWindow++; | |
1581 | } | |
1582 | } | |
1583 | } | |
1584 | ||
1585 | bool ExynosOverlayDisplay::assignGscLayer(hwc_layer_1_t &layer, int index, int nextWindow) | |
1586 | { | |
1587 | private_handle_t *handle = private_handle_t::dynamicCast(layer.handle); | |
1588 | size_t gscIndex = 0; | |
1589 | int downNumerator, downDenominator; | |
1590 | int downError = mMPPs[0]->getDownscaleRatio(&downNumerator, &downDenominator); | |
1591 | bool ret = true; | |
1592 | if (nextWindow == 0 && | |
1593 | !(handle->flags & GRALLOC_USAGE_HW_CAMERA_MASK) && | |
1594 | !downError && | |
1595 | (mMPPs[0]->isProcessingSupported(layer, handle->format, true, downNumerator, downDenominator) > 0)) { | |
1596 | gscIndex = mCurrentGscIndex; | |
1597 | ALOGV("\tusing gscaler %u in LOCAL-PATH", AVAILABLE_GSC_UNITS[gscIndex]); | |
1598 | if (!mMPPs[gscIndex]->isOTF()) | |
1599 | mMPPs[gscIndex]->cleanupM2M(true); | |
1600 | mPostData.gsc_map[nextWindow].mode = exynos5_gsc_map_t::GSC_LOCAL; | |
1601 | mMPPs[gscIndex]->setMode(exynos5_gsc_map_t::GSC_LOCAL); | |
1602 | mPostData.gsc_map[nextWindow].idx = FIMD_GSC_IDX; | |
1603 | if (mOtfMode == OTF_OFF) | |
1604 | mOtfMode = OTF_RUNNING; | |
1605 | mMPPs[0]->mNeedReqbufs = false; | |
1606 | } else { | |
1607 | gscIndex = getMPPForUHD(layer); | |
1608 | if (gscIndex == FIMD_GSC_IDX) { | |
1609 | gscIndex = mCurrentGscIndex; | |
1610 | ret = true; | |
1611 | } else { | |
1612 | ret = false; | |
1613 | } | |
1614 | if (isFormatRgb(handle->format)) { | |
1615 | gscIndex = getRGBMPPIndex(mCurrentRGBMPPIndex); | |
1616 | if (gscIndex != FIMD_GSC_IDX && gscIndex != FIMD_GSC_SEC_IDX) | |
1617 | mCurrentRGBMPPIndex++; | |
1618 | } | |
1619 | ALOGV("\tusing gscaler %u in M2M", AVAILABLE_GSC_UNITS[gscIndex]); | |
1620 | mPostData.gsc_map[nextWindow].mode = exynos5_gsc_map_t::GSC_M2M; | |
1621 | mMPPs[gscIndex]->setMode(exynos5_gsc_map_t::GSC_M2M); | |
1622 | mPostData.gsc_map[nextWindow].idx = gscIndex; | |
1623 | if ((gscIndex == FIMD_GSC_IDX || (mMPPs[gscIndex]->isUsingMSC() && mCurrentGscIndex == 0)) && mOtfMode == OTF_RUNNING) { | |
1624 | ALOGV("change from OTF to M2M"); | |
1625 | mOtfMode = OTF_TO_M2M; | |
1626 | if (mMPPs[gscIndex]->isUsingMSC()) { | |
1627 | mMPPs[0]->setMode(exynos5_gsc_map_t::GSC_LOCAL); | |
1628 | } else { | |
1629 | mMPPs[gscIndex]->setMode(exynos5_gsc_map_t::GSC_LOCAL); | |
1630 | mMPPs[FIMD_GSC_SEC_IDX]->setMode(exynos5_gsc_map_t::GSC_M2M); | |
1631 | mPostData.gsc_map[nextWindow].idx = FIMD_GSC_SEC_IDX; | |
1632 | } | |
1633 | } | |
1634 | } | |
1635 | ALOGV("\tusing gscaler %u", | |
1636 | AVAILABLE_GSC_UNITS[gscIndex]); | |
1637 | return ret; | |
1638 | } | |
1639 | ||
1640 | int ExynosOverlayDisplay::waitForRenderFinish(buffer_handle_t *handle, int buffers) | |
1641 | { | |
1642 | return 0; | |
1643 | } | |
1644 | ||
1645 | int ExynosOverlayDisplay::postGscM2M(hwc_layer_1_t &layer, struct s3c_fb_win_config *config, int win_map, int index, bool isBottom) | |
1646 | { | |
1647 | exynos5_hwc_post_data_t *pdata = &mPostData; | |
1648 | int gsc_idx = pdata->gsc_map[index].idx; | |
1649 | int dst_format = HAL_PIXEL_FORMAT_RGBX_8888; | |
1650 | private_handle_t *handle = private_handle_t::dynamicCast(layer.handle); | |
1651 | int32_t deconBlending = HWC_BLENDING_NONE; | |
1652 | int32_t originalBlending = HWC_BLENDING_NONE; | |
1653 | ||
1654 | hwc_frect_t sourceCrop = { 0, 0, | |
1655 | (float)WIDTH(layer.displayFrame), (float)HEIGHT(layer.displayFrame) }; | |
1656 | if (mHwc->mS3DMode == S3D_MODE_READY || mHwc->mS3DMode == S3D_MODE_RUNNING) { | |
1657 | int S3DFormat = getS3DFormat(mHwc->mHdmiPreset); | |
1658 | if (S3DFormat == S3D_SBS) | |
1659 | mMPPs[gsc_idx]->mS3DMode = S3D_SBS; | |
1660 | else if (S3DFormat == S3D_TB) | |
1661 | mMPPs[gsc_idx]->mS3DMode = S3D_TB; | |
1662 | } else { | |
1663 | mMPPs[gsc_idx]->mS3DMode = S3D_NONE; | |
1664 | } | |
1665 | ||
1666 | if (isFormatRgb(handle->format)) | |
1667 | waitForRenderFinish(&layer.handle, 1); | |
1668 | /* OFF_Screen to ON_Screen changes */ | |
1669 | if (getDrmMode(handle->flags) == SECURE_DRM) | |
1670 | recalculateDisplayFrame(layer, mXres, mYres); | |
1671 | ||
1672 | if (handle->format == HAL_PIXEL_FORMAT_RGB_565) | |
1673 | dst_format = HAL_PIXEL_FORMAT_RGB_565; | |
1674 | ||
1675 | if (isBottom) { | |
1676 | originalBlending = layer.blending; | |
1677 | layer.blending = HWC_BLENDING_NONE; | |
1678 | } | |
1679 | ||
1680 | int err = mMPPs[gsc_idx]->processM2M(layer, dst_format, &sourceCrop); | |
1681 | ||
1682 | if (isBottom) | |
1683 | layer.blending = originalBlending; | |
1684 | ||
1685 | if (err < 0) { | |
1686 | ALOGE("failed to configure gscaler %u for layer %u", | |
1687 | gsc_idx, index); | |
1688 | pdata->gsc_map[index].mode = exynos5_gsc_map_t::GSC_NONE; | |
1689 | return -1; | |
1690 | } | |
1691 | ||
1692 | buffer_handle_t dst_buf = mMPPs[gsc_idx]->mDstBuffers[mMPPs[gsc_idx]->mCurrentBuf]; | |
1693 | private_handle_t *dst_handle = | |
1694 | private_handle_t::dynamicCast(dst_buf); | |
1695 | int prevFormat = -1; | |
1696 | if (((handle->format == HAL_PIXEL_FORMAT_RGBA_8888) || (handle->format == HAL_PIXEL_FORMAT_RGBX_8888) || (handle->format == HAL_PIXEL_FORMAT_RGB_565)) | |
1697 | && dst_handle->format == HAL_PIXEL_FORMAT_BGRA_8888) { | |
1698 | prevFormat = dst_handle->format; | |
1699 | dst_handle->format = handle->format; | |
1700 | } | |
1701 | int fence = mMPPs[gsc_idx]->mDstConfig.releaseFenceFd; | |
1702 | ||
1703 | if (layer.blending == HWC_BLENDING_PREMULT) | |
1704 | deconBlending = HWC_BLENDING_COVERAGE; | |
1705 | else | |
1706 | deconBlending = layer.blending; | |
1707 | ||
1708 | configureHandle(dst_handle, sourceCrop, | |
1709 | layer.displayFrame, deconBlending, layer.planeAlpha, fence, | |
1710 | config[win_map]); | |
1711 | ||
1712 | #ifdef USES_DRM_SETTING_BY_DECON | |
1713 | if (getDrmMode(handle->flags) != NO_DRM) | |
1714 | config[win_map].protection = 1; | |
1715 | else | |
1716 | config[win_map].protection = 0; | |
1717 | #endif | |
1718 | ||
1719 | if (prevFormat >= 0) | |
1720 | dst_handle->format = prevFormat; | |
1721 | return 0; | |
1722 | } | |
1723 | ||
1724 | void ExynosOverlayDisplay::postGscOtf(hwc_layer_1_t &layer, struct s3c_fb_win_config *config, int win_map, int index) | |
1725 | { | |
1726 | #ifdef USES_DRM_SETTING_BY_DECON | |
1727 | private_handle_t *handle = private_handle_t::dynamicCast(layer.handle); | |
1728 | #endif | |
1729 | exynos5_hwc_post_data_t *pdata = &mPostData; | |
1730 | int gsc_idx = pdata->gsc_map[index].idx; | |
1731 | if (mHwc->mS3DMode == S3D_MODE_READY || mHwc->mS3DMode == S3D_MODE_RUNNING) { | |
1732 | int S3DFormat = getS3DFormat(mHwc->mHdmiPreset); | |
1733 | if (S3DFormat == S3D_SBS) | |
1734 | mMPPs[gsc_idx]->mS3DMode = S3D_SBS; | |
1735 | else if (S3DFormat == S3D_TB) | |
1736 | mMPPs[gsc_idx]->mS3DMode = S3D_TB; | |
1737 | } else { | |
1738 | mMPPs[gsc_idx]->mS3DMode = S3D_NONE; | |
1739 | } | |
1740 | ||
1741 | int err = mMPPs[gsc_idx]->processOTF(layer); | |
1742 | ||
1743 | if (err < 0) { | |
1744 | ALOGE("failed to config_gsc_localout %u input for layer %u", gsc_idx, index); | |
1745 | mOtfMode = OTF_TO_M2M; | |
1746 | configureDummyOverlay(&layer, config[win_map]); | |
1747 | } else { | |
1748 | configureOtfWindow(layer.displayFrame, layer.blending, layer.planeAlpha, | |
1749 | layer.acquireFenceFd, HAL_PIXEL_FORMAT_RGBX_8888, config[win_map]); | |
1750 | } | |
1751 | #ifdef USES_DRM_SETTING_BY_DECON | |
1752 | if (getDrmMode(handle->flags) != NO_DRM) | |
1753 | config[win_map].protection = 1; | |
1754 | else | |
1755 | config[win_map].protection = 0; | |
1756 | #endif | |
1757 | return; | |
1758 | } | |
1759 | ||
1760 | void ExynosOverlayDisplay::handleStaticLayers(hwc_display_contents_1_t *contents, struct s3c_fb_win_config_data &win_data, int tot_ovly_wins) | |
1761 | { | |
1762 | int win_map = 0; | |
1763 | if (mLastFbWindow >= NUM_HW_WINDOWS) { | |
1764 | ALOGE("handleStaticLayers:: invalid mLastFbWindow(%d)", mLastFbWindow); | |
1765 | return; | |
1766 | } | |
1767 | win_map = getDeconWinMap(mLastFbWindow, tot_ovly_wins); | |
1768 | ALOGV("[USE] SKIP_STATIC_LAYER_COMP, mLastFbWindow(%d), win_map(%d)\n", mLastFbWindow, win_map); | |
1769 | ||
1770 | memcpy(&win_data.config[win_map], | |
1771 | &mLastConfigData.config[win_map], sizeof(struct s3c_fb_win_config)); | |
1772 | win_data.config[win_map].fence_fd = -1; | |
1773 | ||
1774 | for (size_t i = mFirstFb; i <= mLastFb; i++) { | |
1775 | hwc_layer_1_t &layer = contents->hwLayers[i]; | |
1776 | if (layer.compositionType == HWC_OVERLAY) { | |
1777 | ALOGV("[SKIP_STATIC_LAYER_COMP] layer.handle: 0x%p, layer.acquireFenceFd: %d\n", layer.handle, layer.acquireFenceFd); | |
1778 | layer.releaseFenceFd = layer.acquireFenceFd; | |
1779 | } | |
1780 | } | |
1781 | } | |
1782 | ||
1783 | int ExynosOverlayDisplay::getMPPForUHD(hwc_layer_1_t &layer) | |
1784 | { | |
1785 | return FIMD_GSC_IDX; | |
1786 | } | |
1787 | ||
1788 | void ExynosOverlayDisplay::cleanupGscs() | |
1789 | { | |
1790 | if (mMPPs[FIMD_GSC_IDX]->isM2M()) { | |
1791 | mMPPs[FIMD_GSC_IDX]->cleanupM2M(); | |
1792 | mMPPs[FIMD_GSC_IDX]->setMode(exynos5_gsc_map_t::GSC_NONE); | |
1793 | } else if (mMPPs[FIMD_GSC_IDX]->isOTF()) { | |
1794 | mMPPs[FIMD_GSC_IDX]->cleanupOTF(); | |
1795 | } else if (mMPPs[FIMD_GSC_SEC_IDX]->isM2M()) { | |
1796 | mMPPs[FIMD_GSC_SEC_IDX]->cleanupM2M(); | |
1797 | mMPPs[FIMD_GSC_SEC_IDX]->setMode(exynos5_gsc_map_t::GSC_NONE); | |
1798 | } | |
1799 | for (int i = FIMD_GSC_SEC_IDX + 1; i < mNumMPPs; i++) { | |
1800 | if (mMPPs[i]->isM2M()) { | |
1801 | mMPPs[i]->cleanupM2M(); | |
1802 | mMPPs[i]->setMode(exynos5_gsc_map_t::GSC_NONE); | |
1803 | } | |
1804 | } | |
1805 | } | |
1806 | ||
1807 | void ExynosOverlayDisplay::freeMPP() | |
1808 | { | |
1809 | bool invalidate = false; | |
1810 | for (int i = 0; i < mNumMPPs; i++) { | |
1811 | if (mMPPs[i]->needsReqbufs()) { | |
1812 | mMPPs[i]->free(); | |
1813 | invalidate = true; | |
1814 | } | |
1815 | } | |
1816 | if (invalidate) | |
1817 | mHwc->procs->invalidate(mHwc->procs); | |
1818 | } | |
1819 | ||
1820 | void ExynosOverlayDisplay::refreshGscUsage(hwc_layer_1_t &layer) | |
1821 | { | |
1822 | private_handle_t *handle = private_handle_t::dynamicCast(layer.handle); | |
1823 | int gsc_index = getMPPForUHD(layer); | |
1824 | bool gsc_required = mMPPs[gsc_index]->isProcessingRequired(layer, handle->format); | |
1825 | if (gsc_required) { | |
1826 | if (mGscLayers >= 1) | |
1827 | mGscLayers--; | |
1828 | else | |
1829 | ALOGW("refreshGscUsage: GSC layer count is invalid"); | |
1830 | if (!mGscLayers) | |
1831 | mGscUsed = false; | |
1832 | } | |
1833 | } | |
1834 | ||
1835 | void ExynosOverlayDisplay::handleTotalBandwidthOverload(hwc_display_contents_1_t *contents) | |
1836 | { | |
1837 | if (mHwc->totPixels >= FIMD_TOTAL_BW_LIMIT) { | |
1838 | if (mFbNeeded) { | |
1839 | for (int i = mFirstFb - 1; i >= 0; i--) { | |
1840 | if (mForceOverlayLayerIndex == 0 && i == 0) | |
1841 | break; | |
1842 | hwc_layer_1_t &layer = contents->hwLayers[i]; | |
1843 | refreshGscUsage(layer); | |
1844 | layer.compositionType = HWC_FRAMEBUFFER; | |
1845 | mLayerInfos[i]->compositionType = layer.compositionType; | |
1846 | mLayerInfos[i]->mCheckOverlayFlag |= eInsufficientBandwidth; | |
1847 | mFirstFb = i; | |
1848 | mHwc->totPixels -= WIDTH(layer.displayFrame) * HEIGHT(layer.displayFrame); | |
1849 | if (mHwc->totPixels < FIMD_TOTAL_BW_LIMIT) | |
1850 | break; | |
1851 | } | |
1852 | if (mHwc->totPixels >= FIMD_TOTAL_BW_LIMIT) { | |
1853 | for (int i = mLastFb + 1; i < contents->numHwLayers - 1; i++) { | |
1854 | hwc_layer_1_t &layer = contents->hwLayers[i]; | |
1855 | refreshGscUsage(layer); | |
1856 | layer.compositionType = HWC_FRAMEBUFFER; | |
1857 | mLayerInfos[i]->compositionType = layer.compositionType; | |
1858 | mLayerInfos[i]->mCheckOverlayFlag |= eInsufficientBandwidth; | |
1859 | mLastFb = i; | |
1860 | mHwc->totPixels -= WIDTH(layer.displayFrame) * HEIGHT(layer.displayFrame); | |
1861 | if (mHwc->totPixels < FIMD_TOTAL_BW_LIMIT) | |
1862 | break; | |
1863 | } | |
1864 | } | |
1865 | } else { | |
1866 | bool fbAdded = false; | |
1867 | for (size_t i = 0; i < contents->numHwLayers; i++) { | |
1868 | hwc_layer_1_t &layer = contents->hwLayers[i]; | |
1869 | if (layer.compositionType == HWC_OVERLAY && | |
1870 | mForceOverlayLayerIndex != i) { | |
1871 | refreshGscUsage(layer); | |
1872 | layer.compositionType = HWC_FRAMEBUFFER; | |
1873 | mLastFb = max(mLastFb, i); | |
1874 | mLayerInfos[i]->compositionType = layer.compositionType; | |
1875 | mLayerInfos[i]->mCheckOverlayFlag |= eInsufficientBandwidth; | |
1876 | ||
1877 | if (!fbAdded) { | |
1878 | fbAdded = true; | |
1879 | mHwc->totPixels += mXres * mYres; | |
1880 | } | |
1881 | if (mHwc->totPixels < FIMD_TOTAL_BW_LIMIT) | |
1882 | break; | |
1883 | } | |
1884 | } | |
1885 | if (mPopupPlayYuvContents || mForceOverlayLayerIndex == 0) | |
1886 | mFirstFb = 1; | |
1887 | else | |
1888 | mFirstFb = 0; | |
1889 | } | |
1890 | mFbNeeded = true; | |
1891 | } | |
1892 | } | |
1893 | ||
1894 | bool ExynosOverlayDisplay::switchOTF(bool enable) | |
1895 | { | |
1896 | bool ret; | |
1897 | if (mGscLayers > 1) | |
1898 | return false; | |
1899 | ret = mHwc->allowOTF != enable; | |
1900 | mHwc->allowOTF = enable; | |
1901 | return ret; | |
1902 | } | |
1903 | ||
1904 | int ExynosOverlayDisplay::getRGBMPPIndex(int index) | |
1905 | { | |
1906 | return index; | |
1907 | } | |
1908 | ||
1909 | bool ExynosOverlayDisplay::multipleRGBScaling(int format) | |
1910 | { | |
1911 | return isFormatRgb(format) && | |
1912 | mGscLayers >= 1; | |
1913 | } | |
1914 | ||
1915 | void ExynosOverlayDisplay::checkTVBandwidth() | |
1916 | { | |
1917 | } | |
1918 | ||
1919 | void ExynosOverlayDisplay::dump(android::String8& result) | |
1920 | { | |
1921 | result.append( | |
1922 | " type | handle | color | blend | pa | format | position | size | gsc \n" | |
1923 | "----------+----------|----------+-------+----|----------+---------------+---------------------\n"); | |
1924 | // 8_______ | 8_______ | 8_______ | 5____ | 2_ | 8_______ | [5____,5____] | [5____,5____] | 3__ \n" | |
1925 | ||
1926 | int windowsUsed = 0; | |
1927 | for (size_t i = 0; i < NUM_HW_WINDOWS; i++) { | |
1928 | struct s3c_fb_win_config &config = mLastConfigData.config[i]; | |
1929 | if (config.state != config.S3C_FB_WIN_STATE_DISABLED) | |
1930 | windowsUsed++; | |
1931 | } | |
1932 | ||
1933 | for (size_t i = 0; i < NUM_HW_WINDOWS; i++) { | |
1934 | struct s3c_fb_win_config &config = mLastConfigData.config[i]; | |
1935 | size_t inverse = inverseWinMap(i, windowsUsed); | |
1936 | if ((config.state == config.S3C_FB_WIN_STATE_DISABLED) && | |
1937 | (mLastGscMap[inverse].mode == exynos5_gsc_map_t::GSC_NONE)){ | |
1938 | result.appendFormat(" %8s | %8s | %8s | %5s | %2s | %8s | %13s | %13s", | |
1939 | "OVERLAY", "-", "-", "-", "-", "-", "-", "-"); | |
1940 | } | |
1941 | else { | |
1942 | if (config.state == config.S3C_FB_WIN_STATE_COLOR) | |
1943 | result.appendFormat(" %8s | %8s | %8x | %5s | %2s | %8s", "COLOR", | |
1944 | "-", config.color, "-", "-", "-"); | |
1945 | else | |
1946 | result.appendFormat(" %8s | %8x | %8s | %5x | %2x | %8s", | |
1947 | mLastFbWindow == inverse ? "FB" : "OVERLAY", | |
1948 | intptr_t(mLastHandles[i]), | |
1949 | "-", config.blending, config.plane_alpha, s3cFormat2str(config.format)); | |
1950 | ||
1951 | result.appendFormat(" | [%5d,%5d] | [%5u,%5u]", config.x, config.y, | |
1952 | config.w, config.h); | |
1953 | } | |
1954 | if (mLastGscMap[inverse].mode == exynos5_gsc_map_t::GSC_NONE) { | |
1955 | result.appendFormat(" | %3s", "-"); | |
1956 | } else { | |
1957 | result.appendFormat(" | %3d", | |
1958 | AVAILABLE_GSC_UNITS[mLastGscMap[inverse].idx]); | |
1959 | if (mLastGscMap[inverse].mode == exynos5_gsc_map_t::GSC_M2M) | |
1960 | result.appendFormat(" | %10s","GSC_M2M"); | |
1961 | else | |
1962 | result.appendFormat(" | %10s","GSC_LOCAL"); | |
1963 | } | |
1964 | result.append("\n"); | |
1965 | } | |
1966 | } | |
1967 | ||
1968 | unsigned int ExynosOverlayDisplay::getLayerRegion(hwc_layer_1_t &layer, hwc_rect &rect_area, uint32_t regionType) { | |
1969 | hwc_rect_t const *hwcRects = NULL; | |
1970 | unsigned int numRects = 0; | |
1971 | ||
1972 | switch (regionType) { | |
1973 | case eDamageRegion: | |
1974 | hwcRects = layer.surfaceDamage.rects; | |
1975 | numRects = layer.surfaceDamage.numRects; | |
1976 | break; | |
1977 | default: | |
1978 | ALOGE("%s:: Invalid regionType (%d)", __func__, regionType); | |
1979 | return eDamageRegionError; | |
1980 | } | |
1981 | if ((numRects == 0) || (hwcRects == NULL)) | |
1982 | return eDamageRegionFull; | |
1983 | ||
1984 | if ((numRects == 1) && (hwcRects[0].left == 0) && (hwcRects[0].top == 0) && | |
1985 | (hwcRects[0].right == 0) && (hwcRects[0].bottom == 0)) | |
1986 | return eDamageRegionSkip; | |
1987 | ||
1988 | rect_area.left = INT_MAX; | |
1989 | rect_area.top = INT_MAX; | |
1990 | rect_area.right = rect_area.bottom = 0; | |
1991 | if (hwcRects != NULL) { | |
1992 | for (size_t j = 0; j < numRects; j++) { | |
1993 | hwc_rect_t rect; | |
1994 | rect.left = hwcRects[j].left; | |
1995 | rect.top = hwcRects[j].top; | |
1996 | rect.right = hwcRects[j].right; | |
1997 | rect.bottom = hwcRects[j].bottom; | |
1998 | adjustRect(rect, INT_MAX, INT_MAX); | |
1999 | /* Get sums of rects */ | |
2000 | rect_area = expand(rect_area, rect); | |
2001 | } | |
2002 | } | |
2003 | ||
2004 | return eDamageRegionPartial; | |
2005 | } |