b2bb97b4a3cd6f9380e6d51834a0cea31ec0ab3e
[GitHub/LineageOS/android_hardware_samsung_slsi_exynos7580.git] / libdisplaymodule / ExynosPrimaryDisplay.cpp
1 #include "ExynosPrimaryDisplay.h"
2 #include "ExynosHWCModule.h"
3 #include "ExynosHWCUtils.h"
4 #include "ExynosMPPModule.h"
5
6 #define DISPLAY_LOGD(msg, ...) ALOGD("[%s] " msg, mDisplayName.string(), ##__VA_ARGS__)
7 #define DISPLAY_LOGV(msg, ...) ALOGV("[%s] " msg, mDisplayName.string(), ##__VA_ARGS__)
8 #define DISPLAY_LOGI(msg, ...) ALOGI("[%s] " msg, mDisplayName.string(), ##__VA_ARGS__)
9 #define DISPLAY_LOGW(msg, ...) ALOGW("[%s] " msg, mDisplayName.string(), ##__VA_ARGS__)
10 #define DISPLAY_LOGE(msg, ...) ALOGE("[%s] " msg, mDisplayName.string(), ##__VA_ARGS__)
11
12 ExynosPrimaryDisplay::ExynosPrimaryDisplay(int numGSCs, struct exynos5_hwc_composer_device_1_t *pdev) :
13 ExynosOverlayDisplay(numGSCs, pdev)
14 {
15 }
16
17 ExynosPrimaryDisplay::~ExynosPrimaryDisplay()
18 {
19 }
20
21 int ExynosPrimaryDisplay::getDeconWinMap(int overlayIndex, int totalOverlays)
22 {
23 return 0;
24 }
25
26 void ExynosPrimaryDisplay::forceYuvLayersToFb(hwc_display_contents_1_t __unused *contents)
27 {
28 }
29
30 int ExynosPrimaryDisplay::getMPPForUHD(hwc_layer_1_t __unused &layer)
31 {
32 return 0;
33 }
34
35 int ExynosPrimaryDisplay::getRGBMPPIndex(int index)
36 {
37 return index;
38 }
39
40 bool ExynosPrimaryDisplay::isOverlaySupported(hwc_layer_1_t &layer, size_t index, bool useVPPOverlay,
41 ExynosMPPModule** supportedInternalMPP, ExynosMPPModule** supportedExternalMPP)
42 {
43 // Exynos755555oesn't have any VPP Overlays
44 return ExynosDisplay::isOverlaySupported(layer, index, false, supportedInternalMPP, supportedExternalMPP);
45 }
46 bool ExynosPrimaryDisplay::isYuvDmaAvailable(int format, uint32_t dma)
47 {
48 return (format == HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M_FULL &&
49 dma == IDMA_G2);
50 }
51
52 void ExynosPrimaryDisplay::assignWindows(hwc_display_contents_1_t *contents)
53 {
54 // call the ExynosDisplay default implementation of assignWindows()
55 ExynosDisplay::assignWindows(contents);
56
57 // allocate the max bandwidth non-rgb layer to IDMA_G2
58 // consider only non-secure dma case - secure dma is already allocated to IDMA_G2
59
60 bool videoLayerFound = 0, curDmaYuvFound = 0, hasDRMlayer = 0;
61 uint32_t videoLayerIndex = 0, curDmaYuvIndex = 0;
62 uint32_t mTemp = 0, bandWidth = 0;
63 int fbLayerIndex = -1;
64
65 for (size_t i = 0; i < contents->numHwLayers; i++) {
66 hwc_layer_1_t &layer = contents->hwLayers[i];
67
68 if (!layer.handle)
69 continue;
70
71 private_handle_t *handle = private_handle_t::dynamicCast(layer.handle);
72
73 if (layer.compositionType == HWC_FRAMEBUFFER_TARGET)
74 fbLayerIndex = i;
75
76 // If there is DRM layer available, it has to go to IDMA_G2 channel.
77 if (layer.compositionType == HWC_OVERLAY &&
78 getDrmMode(handle->flags) == SECURE_DRM &&
79 !(layer.flags & HWC_SKIP_RENDERING)) {
80 hasDRMlayer = 1;
81 videoLayerFound = 1;
82 videoLayerIndex = i;
83 }
84
85 // If no DRM layer, find non-rgb overlay layer which can be supported by IDMA_G2.
86 if ((layer.compositionType == HWC_OVERLAY) &&
87 isYuvDmaAvailable(handle->format, IDMA_G2) &&
88 !(layer.flags & HWC_SKIP_RENDERING) &&
89 !hasDRMlayer) {
90
91 mTemp = (layer.sourceCropf.right - layer.sourceCropf.left) *
92 (layer.sourceCropf.bottom - layer.sourceCropf.top);
93 if (mTemp > bandWidth) {
94 bandWidth = mTemp;
95 videoLayerFound = 1;
96 videoLayerIndex = i;
97 }
98 }
99
100 if (((layer.compositionType == HWC_OVERLAY) ||
101 (layer.compositionType == HWC_FRAMEBUFFER_TARGET)) &&
102 (!curDmaYuvFound) &&
103 (mLayerInfos[i]->mDmaType == IDMA_G2)) {
104 curDmaYuvFound = 1;
105 curDmaYuvIndex = i;
106 }
107 }
108
109 if (curDmaYuvFound && videoLayerFound) {
110 mTemp = mLayerInfos[videoLayerIndex]->mDmaType;
111 mLayerInfos[videoLayerIndex]->mDmaType = mLayerInfos[curDmaYuvIndex]->mDmaType;
112 mLayerInfos[curDmaYuvIndex]->mDmaType = mTemp;
113 }
114
115 if (videoLayerFound && !curDmaYuvFound) {
116 if (prevfbTargetIdma == IDMA_G2) {
117 prevfbTargetIdma = (enum decon_idma_type) mLayerInfos[videoLayerIndex]->mDmaType;
118 mLayerInfos[videoLayerIndex]->mDmaType = IDMA_G2;
119 return;
120 }
121 mLayerInfos[videoLayerIndex]->mDmaType = IDMA_G2;
122 }
123
124 if (mFbNeeded && mFbWindow < NUM_HW_WINDOWS && fbLayerIndex >= 0)
125 prevfbTargetIdma = (enum decon_idma_type) mLayerInfos[fbLayerIndex]->mDmaType;
126 }
127
128 int ExynosPrimaryDisplay::postMPPM2M(hwc_layer_1_t &layer, struct decon_win_config *config, int win_map, int index)
129 {
130 int dst_format = mExternalMPPDstFormat;
131 private_handle_t *handle = private_handle_t::dynamicCast(layer.handle);
132 ExynosMPPModule *exynosMPP = mLayerInfos[index]->mExternalMPP;
133
134 if (exynosMPP == NULL) {
135 DISPLAY_LOGE("postMPPM2M is called but externMPP is NULL");
136 if (layer.acquireFenceFd >= 0)
137 close(layer.acquireFenceFd);
138 layer.acquireFenceFd = -1;
139 layer.releaseFenceFd = -1;
140 return -1;
141 }
142
143 hwc_frect_t sourceCrop = { 0, 0,
144 (float)WIDTH(layer.displayFrame), (float)HEIGHT(layer.displayFrame) };
145 int originalTransform = layer.transform;
146 hwc_rect_t originalDisplayFrame = layer.displayFrame;
147
148 /* OFF_Screen to ON_Screen changes */
149 if (getDrmMode(handle->flags) == SECURE_DRM)
150 recalculateDisplayFrame(layer, mXres, mYres);
151
152 if (mType != EXYNOS_VIRTUAL_DISPLAY &&
153 (isFormatRgb(handle->format) ||
154 (isYuvDmaAvailable(handle->format, mLayerInfos[index]->mDmaType) &&
155 WIDTH(layer.displayFrame) % getIDMAWidthAlign(handle->format) == 0 &&
156 HEIGHT(layer.displayFrame) % getIDMAHeightAlign(handle->format) == 0)))
157 dst_format = handle->format;
158
159 int err = exynosMPP->processM2M(layer, dst_format, &sourceCrop);
160
161 /* Restore displayFrame*/
162 layer.displayFrame = originalDisplayFrame;
163
164 if (err < 0) {
165 DISPLAY_LOGE("failed to configure MPP (type:%u, index:%u) for layer %u",
166 exynosMPP->mType, exynosMPP->mIndex, index);
167 return -1;
168 }
169
170 buffer_handle_t dst_buf = exynosMPP->mDstBuffers[exynosMPP->mCurrentBuf];
171 private_handle_t *dst_handle =
172 private_handle_t::dynamicCast(dst_buf);
173 int fence = exynosMPP->mDstConfig.releaseFenceFd;
174 hwc_frect originalCrop = layer.sourceCropf;
175
176 /* ExtMPP out is the input of Decon
177 * and Trsform was processed by ExtMPP
178 */
179 layer.sourceCropf = sourceCrop;
180 layer.transform = 0;
181 configureHandle(dst_handle, index, layer, fence, config[win_map]);
182
183 /* Restore sourceCropf and transform */
184 layer.sourceCropf = originalCrop;
185 layer.transform = originalTransform;
186 return 0;
187 }
188
189 void ExynosPrimaryDisplay::handleStaticLayers(hwc_display_contents_1_t *contents,
190 struct decon_win_config_data &win_data, int __unused tot_ovly_wins)
191 {
192 unsigned int bitmap = 0;
193 bool incorrect_mapping = false;
194
195 ExynosDisplay::handleStaticLayers(contents, win_data, tot_ovly_wins);
196
197 if (mLastFbWindow >= NUM_HW_WINDOWS) {
198 DISPLAY_LOGE("handleStaticLayers:: invalid mLastFbWindow(%d)", mLastFbWindow);
199 return;
200 }
201
202 win_data.config[mLastFbWindow].idma_type = prevfbTargetIdma;
203
204 for (size_t i = 0; i < NUM_HW_WINDOWS; i++) {
205 if (win_data.config[i].state == win_data.config[i].DECON_WIN_STATE_BUFFER) {
206 if (bitmap & (1 << win_data.config[i].idma_type)) {
207 ALOGE("handleStaticLayers: Channel-%d is mapped to multiple windows\n", win_data.config[i].idma_type);
208 incorrect_mapping = true;
209 }
210
211 bitmap |= 1 << win_data.config[i].idma_type;
212 }
213 }
214
215 if (incorrect_mapping) {
216 android::String8 result;
217 result.clear();
218 dump(result);
219 ALOGE("%s", result.string());
220 result.clear();
221 dumpLayerInfo(result);
222 ALOGE("%s", result.string());
223 ALOGE("Display Config:");
224 dump_win_config(&win_data.config[0]);
225 }
226 }
227
228 void ExynosPrimaryDisplay::dump_win_config(struct decon_win_config *config)
229 {
230 int win;
231 struct decon_win_config *cfg;
232 const char *state[] = { "DSBL", "COLR", "BUFF", "UPDT" };
233 const char *blending[] = { "NOBL", "PMUL", "COVR" };
234 const char *idma[] = { "G0", "G1", "V0", "V1", "VR0", "VR1", "G2" };
235
236 for (win = 0; win < MAX_DECON_WIN; win++) {
237 cfg = &config[win];
238
239 if (cfg->state == cfg->DECON_WIN_STATE_DISABLED)
240 continue;
241
242 if (cfg->state == cfg->DECON_WIN_STATE_COLOR) {
243 ALOGE("Win[%d]: %s, C(%d), Dst(%d,%d,%d,%d) "
244 "P(%d)\n",
245 win, state[cfg->state], cfg->color,
246 cfg->dst.x, cfg->dst.y,
247 cfg->dst.x + cfg->dst.w,
248 cfg->dst.y + cfg->dst.h,
249 cfg->protection);
250 } else {
251 ALOGE("Win[%d]: %s,(%d,%d,%d), F(%d) P(%d)"
252 " A(%d), %s, %s, fmt(%d) Src(%d,%d,%d,%d,f_w=%d,f_h=%d) ->"
253 " Dst(%d,%d,%d,%d,f_w=%d,f_h=%d) T(%d,%d,%d,%d) B(%d,%d,%d,%d)\n",
254 win, state[cfg->state], cfg->fd_idma[0],
255 cfg->fd_idma[1], cfg->fd_idma[2],
256 cfg->fence_fd, cfg->protection,
257 cfg->plane_alpha, blending[cfg->blending],
258 idma[cfg->idma_type], cfg->format,
259 cfg->src.x, cfg->src.y, cfg->src.x + cfg->src.w, cfg->src.y + cfg->src.h,
260 cfg->src.f_w, cfg->src.f_h,
261 cfg->dst.x, cfg->dst.y, cfg->dst.x + cfg->dst.w, cfg->dst.y + cfg->dst.h,
262 cfg->dst.f_w, cfg->dst.f_h,
263 cfg->transparent_area.x, cfg->transparent_area.y,
264 cfg->transparent_area.w, cfg->transparent_area.h,
265 cfg->covered_opaque_area.x, cfg->covered_opaque_area.y,
266 cfg->covered_opaque_area.w, cfg->covered_opaque_area.h);
267 }
268 }
269 }
270
271 int ExynosPrimaryDisplay::handleWindowUpdate(hwc_display_contents_1_t __unused *contents,
272 struct decon_win_config __unused *config)
273 {
274 int layerIdx = -1;
275 int updatedWinCnt = 0;
276 int totalWinCnt = 0;
277 int bitsPerPixel = 0;
278 size_t winUpdateInfoIdx;
279 hwc_rect updateRect = {this->mXres, this->mYres, 0, 0};
280 hwc_rect currentRect = {0, 0, 0, 0};
281 bool burstLengthCheckDone = false;
282 int alignAdjustment = 0;
283 int intersectionWidth = 0;
284
285 char value[PROPERTY_VALUE_MAX];
286 property_get("debug.hwc.winupdate", value, NULL);
287
288 if (!(!strcmp(value, "1") || !strcmp(value, "true")))
289 return -eWindowUpdateDisabled;
290
291 if (DECON_WIN_UPDATE_IDX < 0)
292 return -eWindowUpdateInvalidIndex;
293 winUpdateInfoIdx = DECON_WIN_UPDATE_IDX;
294
295 if (contents->flags & HWC_GEOMETRY_CHANGED)
296 return -eWindowUpdateGeometryChanged;
297
298 for (size_t i = 0; i < contents->numHwLayers; i++) {
299 if (contents->hwLayers[i].compositionType == HWC_FRAMEBUFFER)
300 continue;
301
302 if (!mFbNeeded && contents->hwLayers[i].compositionType == HWC_FRAMEBUFFER_TARGET)
303 continue;
304 int32_t windowIndex = mLayerInfos[i]->mWindowIndex;
305 if (config[windowIndex].state != config[windowIndex].DECON_WIN_STATE_DISABLED) {
306 totalWinCnt++;
307
308 if (winConfigChanged(&config[windowIndex], &this->mLastConfigData.config[windowIndex])) {
309 updatedWinCnt++;
310
311 currentRect.left = config[windowIndex].dst.x;
312 currentRect.right = config[windowIndex].dst.x + config[windowIndex].dst.w;
313 currentRect.top = config[windowIndex].dst.y;
314 currentRect.bottom = config[windowIndex].dst.y + config[windowIndex].dst.h;
315
316 if (hwcHasApiVersion((hwc_composer_device_1_t*)mHwc, HWC_DEVICE_API_VERSION_1_5))
317 {
318 private_handle_t *handle = NULL;
319 hwc_rect damageRect = {0, 0, 0, 0};
320 hwc_layer_1_t &layer = contents->hwLayers[i];
321 if (layer.handle)
322 handle = private_handle_t::dynamicCast(layer.handle);
323 getLayerRegion(layer, damageRect, eDamageRegion);
324
325 if (handle && !isScaled(layer) && !isRotated(layer)
326 && !(!(damageRect.left) && !(damageRect.top) && !(damageRect.right) && !(damageRect.bottom))) {
327 HLOGD("[WIN_UPDATE][surfaceDamage] layer w(%4d) h(%4d), dirty (%4d, %4d) - (%4d, %4d)",
328 handle->width, handle->height, damageRect.left, damageRect.top, damageRect.right, damageRect.bottom);
329
330 currentRect.left = config[windowIndex].dst.x - (int32_t)layer.sourceCropf.left + damageRect.left;
331 currentRect.right = config[windowIndex].dst.x - (int32_t)layer.sourceCropf.left + damageRect.right;
332 currentRect.top = config[windowIndex].dst.y - (int32_t)layer.sourceCropf.top + damageRect.top;
333 currentRect.bottom = config[windowIndex].dst.y - (int32_t)layer.sourceCropf.top + damageRect.bottom;
334
335 }
336 }
337
338 if ((currentRect.left > currentRect.right) || (currentRect.top > currentRect.bottom)) {
339 HLOGD("[WIN_UPDATE] window(%d) layer(%d) invalid region (%4d, %4d) - (%4d, %4d)",
340 i, layerIdx, currentRect.left, currentRect.top, currentRect.right, currentRect.bottom);
341 return -eWindowUpdateInvalidRegion;
342 }
343 HLOGD("[WIN_UPDATE] Updated Window(%d) Layer(%d) (%4d, %4d) - (%4d, %4d)",
344 windowIndex, i, currentRect.left, currentRect.top, currentRect.right, currentRect.bottom);
345 updateRect = expand(updateRect, currentRect);
346 }
347 }
348 }
349 if (updatedWinCnt == 0)
350 return -eWindowUpdateNotUpdated;
351
352 updateRect.left = ALIGN_DOWN(updateRect.left, WINUPDATE_X_ALIGNMENT);
353 updateRect.right = updateRect.left + ALIGN_UP(WIDTH(updateRect), WINUPDATE_W_ALIGNMENT);
354
355 if (HEIGHT(updateRect) < WINUPDATE_MIN_HEIGHT) {
356 if (updateRect.top + WINUPDATE_MIN_HEIGHT <= mYres)
357 updateRect.bottom = updateRect.top + WINUPDATE_MIN_HEIGHT;
358 else
359 updateRect.top = updateRect.bottom - WINUPDATE_MIN_HEIGHT;
360 }
361
362 if ((100 * (WIDTH(updateRect) * HEIGHT(updateRect)) / (this->mXres * this->mYres)) > WINUPDATE_THRESHOLD)
363 return -eWindowUpdateOverThreshold;
364
365 alignAdjustment = max(WINUPDATE_X_ALIGNMENT, WINUPDATE_W_ALIGNMENT);
366
367 while (1) {
368 burstLengthCheckDone = true;
369
370 for (size_t i = 0; i < contents->numHwLayers; i++) {
371 if (contents->hwLayers[i].compositionType == HWC_FRAMEBUFFER)
372 continue;
373 if (!mFbNeeded && contents->hwLayers[i].compositionType == HWC_FRAMEBUFFER_TARGET)
374 continue;
375 int32_t windowIndex = mLayerInfos[i]->mWindowIndex;
376 if (config[windowIndex].state != config[windowIndex].DECON_WIN_STATE_DISABLED) {
377 enum decon_pixel_format fmt = config[windowIndex].format;
378
379 if (fmt == DECON_PIXEL_FORMAT_RGBA_5551 || fmt == DECON_PIXEL_FORMAT_RGB_565 )
380 bitsPerPixel = 16;
381 else if (fmt == DECON_PIXEL_FORMAT_NV12 || fmt == DECON_PIXEL_FORMAT_NV21 ||
382 fmt == DECON_PIXEL_FORMAT_NV12M || fmt == DECON_PIXEL_FORMAT_NV21M)
383 bitsPerPixel = 12;
384 else
385 bitsPerPixel = 32;
386
387 currentRect.left = config[windowIndex].dst.x;
388 currentRect.right = config[windowIndex].dst.x + config[windowIndex].dst.w;
389 currentRect.top = config[windowIndex].dst.y;
390 currentRect.bottom = config[windowIndex].dst.y + config[windowIndex].dst.h;
391
392 intersectionWidth = WIDTH(intersection(currentRect, updateRect));
393
394 HLOGV("[WIN_UPDATE] win[%d] left(%d) right(%d) intersection(%d)", windowIndex, currentRect.left, currentRect.right, intersectionWidth);
395
396 if (intersectionWidth != 0 && (size_t)((intersectionWidth * bitsPerPixel) / 8) < BURSTLEN_BYTES) {
397 HLOGV("[WIN_UPDATE] win[%d] insufficient burst length ((%d)*(%d)/8) < %d", windowIndex, intersectionWidth, bitsPerPixel, BURSTLEN_BYTES);
398 burstLengthCheckDone = false;
399 break;
400 }
401 }
402 }
403
404 if (burstLengthCheckDone)
405 break;
406 HLOGD("[WIN_UPDATE] Adjusting update width. current left(%d) right(%d)", updateRect.left, updateRect.right);
407 if (updateRect.left >= alignAdjustment) {
408 updateRect.left -= alignAdjustment;
409 } else if (updateRect.right + alignAdjustment <= this->mXres) {
410 updateRect.right += alignAdjustment;
411 } else {
412 DISPLAY_LOGD("[WIN_UPDATE] Error during update width adjustment");
413 return -eWindowUpdateAdjustmentFail;
414 }
415 }
416
417 config[winUpdateInfoIdx].state = config[winUpdateInfoIdx].DECON_WIN_STATE_UPDATE;
418 config[winUpdateInfoIdx].dst.x = updateRect.left;
419 config[winUpdateInfoIdx].dst.y = updateRect.top;
420 config[winUpdateInfoIdx].dst.w = ALIGN_UP(WIDTH(updateRect), WINUPDATE_W_ALIGNMENT);
421 config[winUpdateInfoIdx].dst.h = HEIGHT(updateRect);
422
423 HLOGD("[WIN_UPDATE] UpdateRegion cfg (%4d, %4d) w(%4d) h(%4d) updatedWindowCnt(%d)",
424 config[winUpdateInfoIdx].dst.x, config[winUpdateInfoIdx].dst.y, config[winUpdateInfoIdx].dst.w, config[winUpdateInfoIdx].dst.h, updatedWinCnt);
425
426 /* Disable block mode if window update region is not full screen */
427 if ((config[winUpdateInfoIdx].dst.x != 0) || (config[winUpdateInfoIdx].dst.y != 0) ||
428 (config[winUpdateInfoIdx].dst.w != (uint32_t)mXres) || (config[winUpdateInfoIdx].dst.h != (uint32_t)mXres)) {
429 for (size_t i = 0; i < NUM_HW_WINDOWS; i++) {
430 memset(&config[i].transparent_area, 0, sizeof(config[i].transparent_area));
431 memset(&config[i].covered_opaque_area, 0, sizeof(config[i].covered_opaque_area));
432 }
433 }
434
435 return 1;
436 }
437
438 int ExynosPrimaryDisplay::getIDMAWidthAlign(int format)
439 {
440 if (isFormatRgb(format))
441 return 1;
442 else
443 return 2;
444 }
445
446 int ExynosPrimaryDisplay::getIDMAHeightAlign(int format)
447 {
448 if (isFormatRgb(format))
449 return 1;
450 else
451 return 2;
452 }