1 /*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 #include "ExynosHWCHelper.h"
17
18 #include <android-base/properties.h>
19 #include <linux/videodev2.h>
20 #include <linux/videodev2_exynos_media.h>
21 #include <png.h>
22 #include <sync/sync.h>
23 #include <sys/mman.h>
24 #include <utils/CallStack.h>
25 #include <utils/Errors.h>
26
27 #include <iomanip>
28
29 #include "ExynosHWC.h"
30 #include "ExynosHWCDebug.h"
31 #include "ExynosLayer.h"
32 #include "ExynosResourceRestriction.h"
33 #include "VendorVideoAPI.h"
34 #include "exynos_sync.h"
35
36 using vendor::graphics::BufferUsage;
37 using vendor::graphics::VendorGraphicBufferUsage;
38 using vendor::graphics::VendorGraphicBufferMeta;
39
40 #define AFBC_MAGIC 0xafbc
41
42 #define FT_LOGD(msg, ...) \
43 {\
44 if (exynosHWCControl.fenceTracer >= 2) \
45 ALOGD("[FenceTracer]::" msg, ##__VA_ARGS__); \
46 }
47 #define FT_LOGE(msg, ...) \
48 {\
49 if (exynosHWCControl.fenceTracer > 0) \
50 ALOGE("[FenceTracer]::" msg, ##__VA_ARGS__); \
51 }
52 #define FT_LOGW(msg, ...) \
53 {\
54 if (exynosHWCControl.fenceTracer >= 1) \
55 ALOGD("[FenceTracer]::" msg, ##__VA_ARGS__); \
56 }
57
58 extern struct exynos_hwc_control exynosHWCControl;
59 extern char fence_names[FENCE_MAX][32];
60
getHWC1CompType(int32_t type)61 uint32_t getHWC1CompType(int32_t type) {
62
63 uint32_t cType = HWC_FRAMEBUFFER;
64
65 switch(type) {
66 case HWC2_COMPOSITION_DEVICE:
67 case HWC2_COMPOSITION_EXYNOS:
68 cType = HWC_OVERLAY;
69 break;
70 case HWC2_COMPOSITION_SOLID_COLOR:
71 cType = HWC_BACKGROUND;
72 break;
73 case HWC2_COMPOSITION_CURSOR:
74 cType = HWC_CURSOR_OVERLAY;
75 break;
76 case HWC2_COMPOSITION_SIDEBAND:
77 cType = HWC_SIDEBAND;
78 break;
79 case HWC2_COMPOSITION_CLIENT:
80 case HWC2_COMPOSITION_INVALID:
81 default:
82 cType = HWC_FRAMEBUFFER;
83 break;
84 }
85
86 return cType;
87 }
88
getDrmMode(uint64_t flags)89 uint32_t getDrmMode(uint64_t flags)
90 {
91 if (flags & BufferUsage::PROTECTED) {
92 if (flags & VendorGraphicBufferUsage::PRIVATE_NONSECURE)
93 return NORMAL_DRM;
94 else
95 return SECURE_DRM;
96 }
97 return NO_DRM;
98 }
99
getDrmMode(const buffer_handle_t handle)100 uint32_t getDrmMode(const buffer_handle_t handle)
101 {
102 uint64_t usage = VendorGraphicBufferMeta::get_usage(handle);
103 if (usage & BufferUsage::PROTECTED) {
104 if (usage & VendorGraphicBufferUsage::PRIVATE_NONSECURE)
105 return NORMAL_DRM;
106 else
107 return SECURE_DRM;
108 }
109
110 return NO_DRM;
111 }
112
isNarrowRgb(int format,android_dataspace data_space)113 unsigned int isNarrowRgb(int format, android_dataspace data_space)
114 {
115 if (format == HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M_FULL)
116 return 0;
117 else {
118 if (isFormatRgb(format))
119 return 0;
120 else {
121 uint32_t data_space_range = (data_space & HAL_DATASPACE_RANGE_MASK);
122 if (data_space_range == HAL_DATASPACE_RANGE_UNSPECIFIED) {
123 return 1;
124 } else if (data_space_range == HAL_DATASPACE_RANGE_FULL) {
125 return 0;
126 } else {
127 return 1;
128 }
129 }
130 }
131 }
132
halFormatToExynosFormat(int inHalFormat,uint32_t inCompressType)133 const format_description_t* halFormatToExynosFormat(int inHalFormat, uint32_t inCompressType) {
134 for (unsigned int i = 0; i < FORMAT_MAX_CNT; i++) {
135 const int descHalFormat = exynos_format_desc[i].halFormat;
136 uint32_t descCompressType = exynos_format_desc[i].getCompression();
137
138 // TODO: b/175381083, Skip checking SBWC compression type
139 if (descCompressType == SBWC || descCompressType == SBWC_LOSSY) {
140 descCompressType = COMP_ANY;
141 }
142
143 if ((inHalFormat == descHalFormat) &&
144 ((inCompressType == COMP_ANY) || (descCompressType == COMP_ANY) ||
145 (inCompressType == descCompressType))) {
146 return &exynos_format_desc[i];
147 }
148 }
149 return nullptr;
150 }
151
formatToBpp(int format)152 uint8_t formatToBpp(int format)
153 {
154 for (unsigned int i = 0; i < FORMAT_MAX_CNT; i++){
155 if (exynos_format_desc[i].halFormat == format)
156 return exynos_format_desc[i].bpp;
157 }
158
159 ALOGW("unrecognized pixel format %u", format);
160 return 0;
161 }
162
DpuFormatToBpp(decon_pixel_format format)163 uint8_t DpuFormatToBpp(decon_pixel_format format)
164 {
165 for (unsigned int i = 0; i < FORMAT_MAX_CNT; i++){
166 if (exynos_format_desc[i].s3cFormat == format)
167 return exynos_format_desc[i].bpp;
168 }
169 ALOGW("unrecognized decon format %u", format);
170 return 0;
171 }
172
isFormatRgb(int format)173 bool isFormatRgb(int format)
174 {
175 for (unsigned int i = 0; i < FORMAT_MAX_CNT; i++){
176 if (exynos_format_desc[i].halFormat == format) {
177 if (exynos_format_desc[i].type & RGB)
178 return true;
179 else
180 return false;
181 }
182 }
183 return false;
184 }
185
isFormatYUV(int format)186 bool isFormatYUV(int format)
187 {
188 if (isFormatRgb(format))
189 return false;
190 return true;
191 }
192
isFormatSBWC(int format)193 bool isFormatSBWC(int format)
194 {
195 for (unsigned int i = 0; i < FORMAT_MAX_CNT; i++){
196 if (exynos_format_desc[i].halFormat == format) {
197 if ((exynos_format_desc[i].type & SBWC) ||
198 (exynos_format_desc[i].type & SBWC_LOSSY))
199 return true;
200 else
201 return false;
202 }
203 }
204 return false;
205 }
206
isFormatYUV420(int format)207 bool isFormatYUV420(int format)
208 {
209 for (unsigned int i = 0; i < FORMAT_MAX_CNT; i++){
210 if (exynos_format_desc[i].halFormat == format) {
211 if (exynos_format_desc[i].type & YUV420)
212 return true;
213 else
214 return false;
215 }
216 }
217 return false;
218 }
219
isFormatYUV8_2(int format)220 bool isFormatYUV8_2(int format)
221 {
222 for (unsigned int i = 0; i < FORMAT_MAX_CNT; i++){
223 if (exynos_format_desc[i].halFormat == format) {
224 if ((exynos_format_desc[i].type & YUV420) &&
225 (exynos_format_desc[i].type & BIT8_2))
226 return true;
227 else
228 return false;
229 }
230 }
231 return false;
232 }
233
isFormat10BitYUV420(int format)234 bool isFormat10BitYUV420(int format)
235 {
236 for (unsigned int i = 0; i < FORMAT_MAX_CNT; i++){
237 if (exynos_format_desc[i].halFormat == format) {
238 if ((exynos_format_desc[i].type & YUV420) &&
239 (exynos_format_desc[i].type & BIT10))
240 return true;
241 else
242 return false;
243 }
244 }
245 return false;
246 }
247
isFormatYUV422(int format)248 bool isFormatYUV422(int format)
249 {
250 for (unsigned int i = 0; i < FORMAT_MAX_CNT; i++){
251 if (exynos_format_desc[i].halFormat == format) {
252 if (exynos_format_desc[i].type & YUV422)
253 return true;
254 else
255 return false;
256 }
257 }
258 return false;
259 }
260
isFormatP010(int format)261 bool isFormatP010(int format)
262 {
263 for (unsigned int i = 0; i < FORMAT_MAX_CNT; i++){
264 if (exynos_format_desc[i].halFormat == format) {
265 if (exynos_format_desc[i].type & P010)
266 return true;
267 else
268 return false;
269 }
270 }
271 return false;
272 }
273
isFormatYCrCb(int format)274 bool isFormatYCrCb(int format)
275 {
276 return format == HAL_PIXEL_FORMAT_EXYNOS_YV12_M;
277 }
278
isFormatLossy(int format)279 bool isFormatLossy(int format)
280 {
281 for (unsigned int i = 0; i < FORMAT_MAX_CNT; i++){
282 if (exynos_format_desc[i].halFormat == format) {
283 if (exynos_format_desc[i].type & SBWC_LOSSY)
284 return true;
285 else
286 return false;
287 }
288 }
289 return false;
290 }
291
formatHasAlphaChannel(int format)292 bool formatHasAlphaChannel(int format)
293 {
294 for (unsigned int i = 0; i < FORMAT_MAX_CNT; i++){
295 if (exynos_format_desc[i].halFormat == format) {
296 return exynos_format_desc[i].hasAlpha;
297 }
298 }
299 return false;
300 }
301
isAFBCCompressed(const buffer_handle_t handle)302 bool isAFBCCompressed(const buffer_handle_t handle) {
303 if (handle != NULL) {
304 return VendorGraphicBufferMeta::is_afbc(handle);
305 }
306
307 return false;
308 }
309
getCompressionType(const buffer_handle_t handle)310 uint32_t getCompressionType(const buffer_handle_t handle) {
311 if (isAFBCCompressed(handle)) {
312 return AFBC;
313 }
314
315 // TODO: b/175381083, Add SBWC check here or make a function in gralloc
316 return 0;
317 }
318
halDataSpaceToV4L2ColorSpace(android_dataspace data_space)319 uint32_t halDataSpaceToV4L2ColorSpace(android_dataspace data_space)
320 {
321 uint32_t standard_data_space = (data_space & HAL_DATASPACE_STANDARD_MASK);
322 switch (standard_data_space) {
323 case HAL_DATASPACE_STANDARD_BT2020:
324 case HAL_DATASPACE_STANDARD_BT2020_CONSTANT_LUMINANCE:
325 return V4L2_COLORSPACE_BT2020;
326 case HAL_DATASPACE_STANDARD_DCI_P3:
327 return V4L2_COLORSPACE_DCI_P3;
328 case HAL_DATASPACE_STANDARD_BT709:
329 return V4L2_COLORSPACE_REC709;
330 default:
331 return V4L2_COLORSPACE_DEFAULT;
332 }
333 return V4L2_COLORSPACE_DEFAULT;
334 }
335
halFormatToDpuFormat(int format,uint32_t compressType)336 enum decon_pixel_format halFormatToDpuFormat(int format, uint32_t compressType) {
337 auto exynosFormat = halFormatToExynosFormat(format, compressType);
338 return (exynosFormat != nullptr) ? exynosFormat->s3cFormat : DECON_PIXEL_FORMAT_MAX;
339 }
340
DpuFormatToHalFormat(int format,uint32_t)341 uint32_t DpuFormatToHalFormat(int format, uint32_t /*compressType*/) {
342 for (unsigned int i = 0; i < FORMAT_MAX_CNT; i++){
343 if (exynos_format_desc[i].s3cFormat == static_cast<decon_pixel_format>(format))
344 return exynos_format_desc[i].halFormat;
345 }
346 return HAL_PIXEL_FORMAT_EXYNOS_UNDEFINED;
347 }
348
halFormatToDrmFormat(int format,uint32_t compressType)349 int halFormatToDrmFormat(int format, uint32_t compressType)
350 {
351 auto exynosFormat = halFormatToExynosFormat(format, compressType);
352 return (exynosFormat != nullptr) ? exynosFormat->drmFormat : DRM_FORMAT_UNDEFINED;
353 }
354
drmFormatToHalFormats(int format,std::vector<uint32_t> * halFormats)355 int32_t drmFormatToHalFormats(int format, std::vector<uint32_t> *halFormats)
356 {
357 if (halFormats == NULL)
358 return -EINVAL;
359
360 halFormats->clear();
361 for (unsigned int i = 0; i < FORMAT_MAX_CNT; i++){
362 if (exynos_format_desc[i].drmFormat == format) {
363 halFormats->push_back(exynos_format_desc[i].halFormat);
364 }
365 }
366 return NO_ERROR;
367 }
368
drmFormatToHalFormat(int format)369 int drmFormatToHalFormat(int format)
370 {
371 for (unsigned int i = 0; i < FORMAT_MAX_CNT; i++){
372 if (exynos_format_desc[i].drmFormat == format)
373 return exynos_format_desc[i].halFormat;
374 }
375 return HAL_PIXEL_FORMAT_EXYNOS_UNDEFINED;
376 }
377
colorModeToDataspace(android_color_mode_t mode)378 android_dataspace colorModeToDataspace(android_color_mode_t mode)
379 {
380 android_dataspace dataSpace = HAL_DATASPACE_UNKNOWN;
381 switch (mode) {
382 case HAL_COLOR_MODE_STANDARD_BT601_625:
383 dataSpace = HAL_DATASPACE_STANDARD_BT601_625;
384 break;
385 case HAL_COLOR_MODE_STANDARD_BT601_625_UNADJUSTED:
386 dataSpace = HAL_DATASPACE_STANDARD_BT601_625_UNADJUSTED;
387 break;
388 case HAL_COLOR_MODE_STANDARD_BT601_525:
389 dataSpace = HAL_DATASPACE_STANDARD_BT601_525;
390 break;
391 case HAL_COLOR_MODE_STANDARD_BT601_525_UNADJUSTED:
392 dataSpace = HAL_DATASPACE_STANDARD_BT601_525_UNADJUSTED;
393 break;
394 case HAL_COLOR_MODE_STANDARD_BT709:
395 dataSpace = HAL_DATASPACE_STANDARD_BT709;
396 break;
397 case HAL_COLOR_MODE_DCI_P3:
398 dataSpace = HAL_DATASPACE_DCI_P3;
399 break;
400 case HAL_COLOR_MODE_ADOBE_RGB:
401 dataSpace = HAL_DATASPACE_ADOBE_RGB;
402 break;
403 case HAL_COLOR_MODE_DISPLAY_P3:
404 dataSpace = HAL_DATASPACE_DISPLAY_P3;
405 break;
406 case HAL_COLOR_MODE_SRGB:
407 dataSpace = HAL_DATASPACE_V0_SRGB;
408 break;
409 case HAL_COLOR_MODE_NATIVE:
410 dataSpace = HAL_DATASPACE_UNKNOWN;
411 break;
412 default:
413 break;
414 }
415 return dataSpace;
416 }
417
halTransformToDrmRot(uint32_t halTransform)418 uint64_t halTransformToDrmRot(uint32_t halTransform)
419 {
420 switch (halTransform) {
421 case HAL_TRANSFORM_FLIP_H:
422 return DRM_MODE_REFLECT_Y|DRM_MODE_ROTATE_0;
423 case HAL_TRANSFORM_FLIP_V:
424 return DRM_MODE_REFLECT_X|DRM_MODE_ROTATE_0;
425 case HAL_TRANSFORM_ROT_180:
426 return DRM_MODE_ROTATE_180;
427 case HAL_TRANSFORM_ROT_90:
428 return DRM_MODE_ROTATE_90;
429 case (HAL_TRANSFORM_ROT_90|HAL_TRANSFORM_FLIP_H):
430 /*
431 * HAL: HAL_TRANSFORM_FLIP_H -> HAL_TRANSFORM_ROT_90
432 * DPP: ROT_90 -> XFLIP
433 */
434 return (DRM_MODE_ROTATE_90|DRM_MODE_REFLECT_X);
435 case (HAL_TRANSFORM_ROT_90|HAL_TRANSFORM_FLIP_V):
436 /*
437 * HAL: HAL_TRANSFORM_FLIP_V -> HAL_TRANSFORM_ROT_90
438 * DPP: ROT_90 -> YFLIP
439 */
440 return (DRM_MODE_ROTATE_90|DRM_MODE_REFLECT_Y);
441 case HAL_TRANSFORM_ROT_270:
442 return DRM_MODE_ROTATE_270;
443 default:
444 return DRM_MODE_ROTATE_0;
445 }
446 }
447
dumpHandle(uint32_t type,buffer_handle_t h)448 void dumpHandle(uint32_t type, buffer_handle_t h)
449 {
450 if (h == NULL)
451 return;
452
453 VendorGraphicBufferMeta gmeta(h);
454
455 HDEBUGLOGD(type, "\t\tformat = %d, width = %u, height = %u, stride = %u, vstride = %u",
456 gmeta.format, gmeta.width, gmeta.height, gmeta.stride, gmeta.vstride);
457 }
458
dumpExynosImage(uint32_t type,exynos_image & img)459 void dumpExynosImage(uint32_t type, exynos_image &img)
460 {
461 if (!hwcCheckDebugMessages(type))
462 return;
463
464 String8 result;
465 dumpExynosImage(result, img);
466
467 ALOGD("%s", result.string());
468 }
469
dumpExynosImage(String8 & result,exynos_image & img)470 void dumpExynosImage(String8& result, exynos_image &img)
471 {
472 result.appendFormat("\tbufferHandle: %p, fullWidth: %d, fullHeight: %d, x: %d, y: %d, w: %d, "
473 "h: %d, format: %s\n",
474 img.bufferHandle, img.fullWidth, img.fullHeight, img.x, img.y, img.w, img.h,
475 getFormatStr(img.format, img.compressed ? AFBC : 0).string());
476 result.appendFormat("\tusageFlags: 0x%" PRIx64 ", layerFlags: 0x%8x, acquireFenceFd: %d, releaseFenceFd: %d\n",
477 img.usageFlags, img.layerFlags, img.acquireFenceFd, img.releaseFenceFd);
478 result.appendFormat("\tdataSpace(%d), blending(%d), transform(0x%2x), afbc(%d)\n",
479 img.dataSpace, img.blending, img.transform, img.compressed);
480 if (img.bufferHandle != NULL) {
481 VendorGraphicBufferMeta gmeta(img.bufferHandle);
482 result.appendFormat("\tbuffer's stride: %d, %d\n", gmeta.stride, gmeta.vstride);
483 }
484 }
485
printExynosLayer(const ExynosLayer * layer)486 void printExynosLayer(const ExynosLayer* layer) {
487 if (layer == nullptr) {
488 return;
489 }
490
491 const_cast<ExynosLayer*>(layer)->printLayer();
492 }
493
isSrcCropFloat(hwc_frect & frect)494 bool isSrcCropFloat(hwc_frect &frect)
495 {
496 return (frect.left != (int)frect.left) ||
497 (frect.top != (int)frect.top) ||
498 (frect.right != (int)frect.right) ||
499 (frect.bottom != (int)frect.bottom);
500 }
501
isScaled(exynos_image & src,exynos_image & dst)502 bool isScaled(exynos_image &src, exynos_image &dst)
503 {
504 uint32_t srcW = src.w;
505 uint32_t srcH = src.h;
506 uint32_t dstW = dst.w;
507 uint32_t dstH = dst.h;
508
509 if (!!(src.transform & HAL_TRANSFORM_ROT_90)) {
510 dstW = dst.h;
511 dstH = dst.w;
512 }
513
514 return ((srcW != dstW) || (srcH != dstH));
515 }
516
isScaledDown(exynos_image & src,exynos_image & dst)517 bool isScaledDown(exynos_image &src, exynos_image &dst)
518 {
519 uint32_t srcW = src.w;
520 uint32_t srcH = src.h;
521 uint32_t dstW = dst.w;
522 uint32_t dstH = dst.h;
523
524 if (!!(src.transform & HAL_TRANSFORM_ROT_90)) {
525 dstW = dst.h;
526 dstH = dst.w;
527 }
528
529 return ((srcW > dstW) || (srcH > dstH));
530 }
531
hasHdrInfo(const exynos_image & img)532 bool hasHdrInfo(const exynos_image& img) {
533 uint32_t dataSpace = img.dataSpace;
534
535 /* By reference Layer's dataspace */
536 uint32_t standard = (dataSpace & HAL_DATASPACE_STANDARD_MASK);
537 uint32_t transfer = (dataSpace & HAL_DATASPACE_TRANSFER_MASK);
538
539 if ((standard == HAL_DATASPACE_STANDARD_BT2020) ||
540 (standard == HAL_DATASPACE_STANDARD_BT2020_CONSTANT_LUMINANCE) ||
541 (standard == HAL_DATASPACE_STANDARD_DCI_P3)) {
542 if ((transfer == HAL_DATASPACE_TRANSFER_ST2084) ||
543 (transfer == HAL_DATASPACE_TRANSFER_HLG))
544 return true;
545 else
546 return false;
547 }
548
549 return false;
550 }
551
hasHdrInfo(android_dataspace dataSpace)552 bool hasHdrInfo(android_dataspace dataSpace) {
553 exynos_image img;
554 img.dataSpace = dataSpace;
555 return hasHdrInfo(img);
556 }
557
hasHdr10Plus(exynos_image & img)558 bool hasHdr10Plus(exynos_image &img) {
559 /* TODO Check layer has hdr10 and dynamic metadata here */
560 return (img.metaType & VIDEO_INFO_TYPE_HDR_DYNAMIC) ? true : false;
561 }
562
getFormatStr(int format,uint32_t compressType)563 String8 getFormatStr(int format, uint32_t compressType) {
564 auto exynosFormat = halFormatToExynosFormat(format, compressType);
565
566 if (exynosFormat != nullptr) {
567 return exynosFormat->name;
568 }
569
570 String8 result;
571 result.appendFormat("? %08x", format);
572 return result;
573 }
574
adjustRect(hwc_rect_t & rect,int32_t width,int32_t height)575 void adjustRect(hwc_rect_t &rect, int32_t width, int32_t height)
576 {
577 if (rect.left < 0)
578 rect.left = 0;
579 if (rect.left > width)
580 rect.left = width;
581 if (rect.top < 0)
582 rect.top = 0;
583 if (rect.top > height)
584 rect.top = height;
585 if (rect.right < rect.left)
586 rect.right = rect.left;
587 if (rect.right > width)
588 rect.right = width;
589 if (rect.bottom < rect.top)
590 rect.bottom = rect.top;
591 if (rect.bottom > height)
592 rect.bottom = height;
593 }
594
getBufferNumOfFormat(int format,uint32_t compressType)595 uint32_t getBufferNumOfFormat(int format, uint32_t compressType) {
596 auto exynosFormat = halFormatToExynosFormat(format, compressType);
597 return (exynosFormat != nullptr) ? exynosFormat->bufferNum : 0;
598 }
599
getPlaneNumOfFormat(int format,uint32_t compressType)600 uint32_t getPlaneNumOfFormat(int format, uint32_t compressType) {
601 auto exynosFormat = halFormatToExynosFormat(format, compressType);
602 return (exynosFormat != nullptr) ? exynosFormat->planeNum : 0;
603 }
604
getBytePerPixelOfPrimaryPlane(int format)605 uint32_t getBytePerPixelOfPrimaryPlane(int format) {
606 if (isFormatRgb(format))
607 return (formatToBpp(format) / 8);
608 else if (isFormat10BitYUV420(format))
609 return 2;
610 else if (isFormatYUV420(format))
611 return 1;
612 else
613 return 0;
614 }
615
setFenceName(int fenceFd,HwcFenceType fenceType)616 void setFenceName(int fenceFd, HwcFenceType fenceType) {
617 if (fenceFd >= 3)
618 ioctl(fenceFd, SYNC_IOC_FENCE_NAME, fence_names[fenceType]);
619 else if (fenceFd == -1) {
620 HDEBUGLOGD(eDebugFence, "%s : fence (type %d) is -1", __func__, (int)fenceType);
621 }
622 else {
623 ALOGW("%s : fence (type %d) is less than 3", __func__, (int)fenceType);
624 hwc_print_stack();
625 }
626 }
627
getExynosBufferYLength(uint32_t width,uint32_t height,int format)628 uint32_t getExynosBufferYLength(uint32_t width, uint32_t height, int format)
629 {
630 switch (format) {
631 case HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M:
632 case HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M_FULL:
633 case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_PRIV:
634 case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M:
635 case HAL_PIXEL_FORMAT_EXYNOS_YV12_M:
636 case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_P_M:
637 return NV12M_Y_SIZE(width, height);
638 case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_S10B:
639 HDEBUGLOGD(eDebugMPP, "8bit size(Y) : %d, extra size : %d", NV12M_Y_SIZE(width, height), NV12M_Y_2B_SIZE(width, height));
640 return NV12M_Y_SIZE(width, height) + NV12M_Y_2B_SIZE(width, height);
641 case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_S10B:
642 return NV12N_10B_Y_8B_SIZE(width, height) + NV12N_10B_Y_2B_SIZE(width, height);
643 case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_P010_M:
644 HDEBUGLOGD(eDebugMPP, "size(Y) : %d", P010M_Y_SIZE(width, height));
645 return P010M_Y_SIZE(width, height);
646 case HAL_PIXEL_FORMAT_YCBCR_P010:
647 HDEBUGLOGD(eDebugMPP, "size(Y) : %d", P010_Y_SIZE(width, height));
648 return P010_Y_SIZE(width, height);
649 case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN:
650 return YUV420N_Y_SIZE(width, height);
651 case HAL_PIXEL_FORMAT_GOOGLE_NV12_SP_10B:
652 return 2 * __ALIGN_UP(width, 64) * __ALIGN_UP(height, 8);
653 case HAL_PIXEL_FORMAT_GOOGLE_NV12_SP:
654 return __ALIGN_UP(width, 64) * __ALIGN_UP(height, 8);
655 case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_SBWC:
656 case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_SBWC_L50:
657 case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_SBWC_L75:
658 case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_SBWC:
659 case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_SBWC_L50:
660 case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_SBWC_L75:
661 case HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M_SBWC:
662 return SBWC_8B_Y_SIZE(width, height) +
663 SBWC_8B_Y_HEADER_SIZE(width, height);
664 case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_10B_SBWC:
665 case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_10B_SBWC_L40:
666 case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_10B_SBWC_L60:
667 case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_10B_SBWC_L80:
668 case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_10B_SBWC:
669 case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_10B_SBWC_L40:
670 case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_10B_SBWC_L60:
671 case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_10B_SBWC_L80:
672 case HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M_10B_SBWC:
673 return SBWC_10B_Y_SIZE(width, height) +
674 SBWC_10B_Y_HEADER_SIZE(width, height);
675 }
676
677 return NV12M_Y_SIZE(width, height) + ((width % 128) == 0 ? 0 : 256);
678 }
679
getExynosBufferCbCrLength(uint32_t width,uint32_t height,int format)680 uint32_t getExynosBufferCbCrLength(uint32_t width, uint32_t height, int format)
681 {
682 switch (format) {
683 case HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M:
684 case HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M_FULL:
685 case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_PRIV:
686 case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M:
687 case HAL_PIXEL_FORMAT_EXYNOS_YV12_M:
688 case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_P_M:
689 return NV12M_CBCR_SIZE(width, height);
690 case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_S10B:
691 HDEBUGLOGD(eDebugMPP, "8bit size(CbCr) : %d, extra size : %d",NV12M_CBCR_SIZE(width, height), NV12M_CBCR_2B_SIZE(width, height));
692 return NV12M_CBCR_SIZE(width, height) + NV12M_CBCR_2B_SIZE(width, height);
693 case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_P010_M:
694 HDEBUGLOGD(eDebugMPP, "size(CbCr) : %d", P010M_CBCR_SIZE(width, height));
695 return P010M_CBCR_SIZE(width, height);
696 case HAL_PIXEL_FORMAT_YCBCR_P010:
697 HDEBUGLOGD(eDebugMPP, "size(CbCr) : %d", P010_CBCR_SIZE(width, height));
698 return P010_CBCR_SIZE(width, height);
699 case HAL_PIXEL_FORMAT_GOOGLE_NV12_SP_10B:
700 return __ALIGN_UP(width, 64) * __ALIGN_UP(height, 8);
701 case HAL_PIXEL_FORMAT_GOOGLE_NV12_SP:
702 return __ALIGN_UP(width, 64) * __ALIGN_UP(height, 8) / 2;
703 case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_SBWC:
704 case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_SBWC_L50:
705 case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_SBWC_L75:
706 case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_SBWC:
707 case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_SBWC_L50:
708 case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_SBWC_L75:
709 case HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M_SBWC:
710 return SBWC_8B_CBCR_SIZE(width, height) +
711 SBWC_8B_CBCR_HEADER_SIZE(width, height);
712 case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_10B_SBWC:
713 case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_10B_SBWC_L40:
714 case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_10B_SBWC_L60:
715 case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_10B_SBWC_L80:
716 case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_10B_SBWC:
717 case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_10B_SBWC_L40:
718 case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_10B_SBWC_L60:
719 case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_10B_SBWC_L80:
720 case HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M_10B_SBWC:
721 return SBWC_10B_CBCR_SIZE(width, height) +
722 SBWC_10B_CBCR_HEADER_SIZE(width, height);
723 }
724
725 return NV12M_CBCR_SIZE(width, height);
726 }
727
getBufLength(buffer_handle_t handle,uint32_t planerNum,size_t * length,int format,uint32_t width,uint32_t height)728 int getBufLength(buffer_handle_t handle, uint32_t planerNum, size_t *length, int format, uint32_t width, uint32_t height)
729 {
730 uint32_t bufferNumber = getBufferNumOfFormat(format, getCompressionType(handle));
731 if ((bufferNumber == 0) || (bufferNumber > planerNum))
732 return -EINVAL;
733
734 VendorGraphicBufferMeta gmeta(handle);
735
736 switch (bufferNumber) {
737 case 1:
738 length[0] = gmeta.size;
739 break;
740 case 2:
741 HDEBUGLOGD(eDebugMPP, "-- %s x : %d y : %d format : %d",__func__, width, height, format);
742 length[0] = gmeta.size;
743 length[1] = gmeta.size1;
744 HDEBUGLOGD(eDebugMPP, "Y size : %zu CbCr size : %zu", length[0], length[1]);
745 break;
746 case 3:
747 length[0] = width * height;
748 length[1]= (length[0]/4);
749 length[2]= (length[0]/4);
750 break;
751 }
752 return NO_ERROR;
753 }
754
fence_close(int fence,ExynosDisplay * display,HwcFdebugFenceType type,HwcFdebugIpType ip)755 int fence_close(int fence, ExynosDisplay* display, HwcFdebugFenceType type, HwcFdebugIpType ip) {
756 if (display != NULL) setFenceInfo(fence, display, type, ip, HwcFenceDirection::CLOSE);
757 return hwcFdClose(fence);
758 }
759
fence_valid(int fence)760 bool fence_valid(int fence) {
761 if (fence == -1){
762 HDEBUGLOGD(eDebugFence, "%s : fence is -1", __func__);
763 return false;
764 } else if (fence < 3) {
765 ALOGW("%s : fence (fd:%d) is less than 3", __func__, fence);
766 hwc_print_stack();
767 return true;
768 }
769 return true;
770 }
771
hwcFdClose(int fd)772 int hwcFdClose(int fd) {
773 if (fd>= 3)
774 close(fd);
775 else if (fd == -1){
776 HDEBUGLOGD(eDebugFence, "%s : Fd is -1", __func__);
777 } else {
778 ALOGW("%s : Fd:%d is less than 3", __func__, fd);
779 hwc_print_stack();
780 }
781 return -1;
782 }
783
hwc_dup(int fd,ExynosDisplay * display,HwcFdebugFenceType type,HwcFdebugIpType ip,bool pendingAllowed)784 int hwc_dup(int fd, ExynosDisplay* display, HwcFdebugFenceType type, HwcFdebugIpType ip,
785 bool pendingAllowed) {
786 int dup_fd = -1;
787
788 if (fd>= 3)
789 dup_fd = dup(fd);
790 else if (fd == -1){
791 HDEBUGLOGD(eDebugFence, "%s : Fd is -1", __func__);
792 } else {
793 ALOGW("%s : Fd:%d is less than 3", __func__, fd);
794 hwc_print_stack();
795 }
796
797 if ((dup_fd < 3) && (dup_fd != -1)) {
798 ALOGW("%s : Dupulicated Fd:%d is less than 3 : %d", __func__, fd, dup_fd);
799 hwc_print_stack();
800 }
801
802 setFenceInfo(dup_fd, display, type, ip, HwcFenceDirection::DUP, pendingAllowed, fd);
803 FT_LOGD("duplicated %d from %d", dup_fd, fd);
804
805 return dup_fd;
806 }
807
hwc_print_stack()808 int hwc_print_stack() {
809 /* CallStack stack; */
810 /* stack.update(); */
811 /* stack.log("HWCException", ANDROID_LOG_ERROR, "HWCException"); */
812 return 0;
813 }
814
getLocalTimeStr(struct timeval tv)815 String8 getLocalTimeStr(struct timeval tv) {
816 struct tm* localTime = (struct tm*)localtime((time_t*)&tv.tv_sec);
817 return String8::format("%02d-%02d %02d:%02d:%02d.%03lu(%lu)", localTime->tm_mon + 1,
818 localTime->tm_mday, localTime->tm_hour, localTime->tm_min,
819 localTime->tm_sec, tv.tv_usec / 1000,
820 ((tv.tv_sec * 1000) + (tv.tv_usec / 1000)));
821 }
822
setFenceInfo(uint32_t fd,ExynosDisplay * display,HwcFdebugFenceType type,HwcFdebugIpType ip,HwcFenceDirection direction,bool pendingAllowed,int32_t dupFrom)823 void setFenceInfo(uint32_t fd, ExynosDisplay* display, HwcFdebugFenceType type, HwcFdebugIpType ip,
824 HwcFenceDirection direction, bool pendingAllowed, int32_t dupFrom) {
825 if (!fence_valid(fd) || display == NULL) return;
826
827 ExynosDevice* device = display->mDevice;
828
829 std::scoped_lock lock(device->mFenceMutex);
830 HwcFenceInfo& info = device->mFenceInfos[fd];
831 info.displayId = display->mDisplayId;
832
833 if (info.leaking) {
834 return;
835 }
836
837 switch (direction) {
838 case HwcFenceDirection::FROM:
839 info.usage++;
840 break;
841 case HwcFenceDirection::TO:
842 info.usage--;
843 break;
844 case HwcFenceDirection::DUP:
845 info.usage++;
846 info.dupFrom = dupFrom;
847 break;
848 case HwcFenceDirection::CLOSE:
849 info.usage--;
850 if (info.usage < 0) info.usage = 0;
851 break;
852 case HwcFenceDirection::UPDATE:
853 break;
854 default:
855 ALOGE("Fence trace : Undefined direction!");
856 break;
857 }
858
859 if (info.usage == 0) {
860 device->mFenceInfos.erase(fd);
861 return;
862 } else if (info.usage < 0) {
863 ALOGE("%s : Invalid negative usage (%d) for Fence FD:%d", __func__, info.usage, fd);
864 printLastFenceInfo(fd, display);
865 }
866
867 HwcFenceTrace trace = {.direction = direction, .type = type, .ip = ip, .time = {0, 0}};
868
869 gettimeofday(&trace.time, NULL);
870
871 info.traces.push_back(trace);
872
873 FT_LOGW("FD : %d, direction : %d, type : %d, ip : %d", fd, direction, type, ip);
874
875 // Fence's usage count shuld be zero at end of frame(present done).
876 // This flag means usage count of the fence can be pended over frame.
877 info.pendingAllowed = pendingAllowed;
878 }
879
printLastFenceInfo(uint32_t fd,ExynosDisplay * display)880 void printLastFenceInfo(uint32_t fd, ExynosDisplay* display) {
881 if (!fence_valid(fd)) return;
882
883 ExynosDevice* device = display->mDevice;
884
885 auto it = device->mFenceInfos.find(fd);
886 if (it == device->mFenceInfos.end()) return;
887 HwcFenceInfo& info = it->second;
888 FT_LOGD("---- Fence FD : %d, Display(%d) ----", fd, info.displayId);
889 FT_LOGD("usage: %d, dupFrom: %d, pendingAllowed: %d, leaking: %d", info.usage, info.dupFrom,
890 info.pendingAllowed, info.leaking);
891
892 for (const auto& trace : info.traces) {
893 FT_LOGD("> dir: %d, type: %d, ip: %d, time:%s", trace.direction, trace.type, trace.ip,
894 getLocalTimeStr(trace.time).string());
895 }
896 }
897
dumpFenceInfo(ExynosDisplay * display,int32_t count)898 void dumpFenceInfo(ExynosDisplay* display, int32_t count) {
899 ExynosDevice* device = display->mDevice;
900
901 FT_LOGD("Dump fence (up to %d fences) ++", count);
902 for (const auto& [fd, info] : device->mFenceInfos) {
903 if (info.pendingAllowed) continue;
904 if (count-- <= 0) break;
905 printLastFenceInfo(fd, display);
906 }
907 FT_LOGD("Dump fence --");
908 }
909
printLeakFds(ExynosDisplay * display)910 void printLeakFds(ExynosDisplay* display) {
911 ExynosDevice* device = display->mDevice;
912
913 auto reportLeakFds = [&fenceInfos = device->mFenceInfos](int sign) {
914 String8 errString;
915 errString.appendFormat("Leak Fds (%d) :\n", sign);
916
917 int cnt = 0;
918 for (const auto& [fd, info] : fenceInfos) {
919 if (!info.leaking) continue;
920 if (info.usage * sign > 0) {
921 errString.appendFormat("%d,", fd);
922 if ((++cnt % 10) == 0) {
923 errString.append("\n");
924 }
925 }
926 }
927
928 FT_LOGW("%s", errString.string());
929 };
930
931 reportLeakFds(+1);
932 reportLeakFds(-1);
933 }
934
dumpNCheckLeak(ExynosDisplay * display,int32_t __unused depth)935 void dumpNCheckLeak(ExynosDisplay* display, int32_t __unused depth) {
936 ExynosDevice* device = display->mDevice;
937
938 FT_LOGD("Dump leaking fence ++");
939 for (auto& [fd, info] : device->mFenceInfos) {
940 if (!info.pendingAllowed) {
941 // leak is occured in this frame first
942 if (!info.leaking) {
943 info.leaking = true;
944 printLastFenceInfo(fd, display);
945 }
946 }
947 }
948
949 int priv = exynosHWCControl.fenceTracer;
950 exynosHWCControl.fenceTracer = 3;
951 printLeakFds(display);
952 exynosHWCControl.fenceTracer = priv;
953
954 FT_LOGD("Dump leaking fence --");
955 }
956
fenceWarn(ExynosDisplay * display,uint32_t threshold)957 bool fenceWarn(ExynosDisplay* display, uint32_t threshold) {
958 ExynosDevice* device = display->mDevice;
959 uint32_t cnt = device->mFenceInfos.size();
960
961 if (cnt > threshold) {
962 ALOGE("Fence leak! -- the number of fences(%d) exceeds threshold(%d)", cnt, threshold);
963 int priv = exynosHWCControl.fenceTracer;
964 exynosHWCControl.fenceTracer = 3;
965 dumpFenceInfo(display, 10);
966 exynosHWCControl.fenceTracer = priv;
967 }
968
969 return (cnt > threshold);
970 }
971
validateFencePerFrame(ExynosDisplay * display)972 bool validateFencePerFrame(ExynosDisplay* display) {
973 ExynosDevice* device = display->mDevice;
974 bool ret = true;
975
976 for (const auto& [fd, info] : device->mFenceInfos) {
977 if (info.displayId != display->mDisplayId) continue;
978 if ((!info.pendingAllowed) && (!info.leaking)) {
979 ret = false;
980 break;
981 }
982 }
983
984 if (!ret) {
985 int priv = exynosHWCControl.fenceTracer;
986 exynosHWCControl.fenceTracer = 3;
987 dumpNCheckLeak(display, 0);
988 exynosHWCControl.fenceTracer = priv;
989 }
990
991 return ret;
992 }
993
getMPPStr(int typeId)994 String8 getMPPStr(int typeId) {
995 if (typeId < MPP_DPP_NUM){
996 int cnt = sizeof(AVAILABLE_OTF_MPP_UNITS)/sizeof(exynos_mpp_t);
997 for (int i = 0; i < cnt; i++){
998 if (AVAILABLE_OTF_MPP_UNITS[i].physicalType == typeId)
999 return String8(AVAILABLE_OTF_MPP_UNITS[i].name);
1000 }
1001 } else {
1002 int cnt = sizeof(AVAILABLE_M2M_MPP_UNITS)/sizeof(exynos_mpp_t);
1003 for (int i = 0; i < cnt; i++){
1004 if (AVAILABLE_M2M_MPP_UNITS[i].physicalType == typeId)
1005 return String8(AVAILABLE_M2M_MPP_UNITS[i].name);
1006 }
1007 }
1008 String8 result;
1009 result.appendFormat("? %08x", typeId);
1010 return result;
1011 }
1012
hasPPC(uint32_t physicalType,uint32_t formatIndex,uint32_t rotIndex)1013 bool hasPPC(uint32_t physicalType, uint32_t formatIndex, uint32_t rotIndex) {
1014 if (ppc_table_map.find(PPC_IDX(physicalType, formatIndex, rotIndex)) !=
1015 ppc_table_map.end()) {
1016 return true;
1017 }
1018 return false;
1019 }
1020
add(const std::string & key,const uint64_t & value,bool toHex)1021 TableBuilder& TableBuilder::add(const std::string& key, const uint64_t& value, bool toHex) {
1022 std::stringstream v;
1023 if (toHex)
1024 v << "0x" << std::hex << value;
1025 else
1026 v << value;
1027 data.emplace_back(std::make_pair(key, v.str()));
1028 return *this;
1029 }
1030
add(const std::string & key,const std::vector<uint64_t> & values,bool toHex)1031 TableBuilder& TableBuilder::add(const std::string& key, const std::vector<uint64_t>& values,
1032 bool toHex) {
1033 std::stringstream value;
1034 for (int i = 0; i < values.size(); i++) {
1035 if (i) value << ", ";
1036
1037 if (toHex)
1038 value << "0x" << std::hex << values[i];
1039 else
1040 value << values[i];
1041 }
1042
1043 data.emplace_back(std::make_pair(key, value.str()));
1044 return *this;
1045 }
1046
build()1047 std::string TableBuilder::build() {
1048 std::stringstream splitter, header, content;
1049 splitter << "+";
1050 header << "|";
1051 content << "|";
1052 for (const auto& [key, value] : data) {
1053 int size = std::max(key.size(), value.size()) + 2 /* for spaces around the string */;
1054 splitter << std::string(size, '-') << "+";
1055 header << buildPaddedString(key, size) << "|";
1056 content << buildPaddedString(value, size) << "|";
1057 }
1058
1059 std::string output = splitter.str() + "\n" +
1060 header.str() + "\n" +
1061 splitter.str() + "\n" +
1062 content.str() + "\n" +
1063 splitter.str() + "\n";
1064 return output;
1065 }
1066
buildPaddedString(const std::string & str,int size)1067 std::string TableBuilder::buildPaddedString(const std::string& str, int size) {
1068 int totalPadding = size - str.size();
1069 int leftPadding = totalPadding / 2.0;
1070 int rightPadding = (totalPadding / 2.0) + 0.6; // Poor person's ceil
1071
1072 return std::string(leftPadding, ' ') + str + std::string(rightPadding, ' ');
1073 }
1074
writeFileNode(FILE * fd,int value)1075 void writeFileNode(FILE* fd, int value) {
1076 constexpr uint32_t kMaxWriteFileLen = 16;
1077 char val[kMaxWriteFileLen] = {0};
1078
1079 if (fd == nullptr) {
1080 ALOGE("invalid fd pass to %s!", __func__);
1081 return;
1082 }
1083
1084 if (int32_t ret = snprintf(val, kMaxWriteFileLen, "%d", value) <= 0) {
1085 ALOGE("failed to write file node, ret =%d", ret);
1086 } else {
1087 fwrite(val, sizeof(val), 1, fd);
1088 if (ferror(fd)) {
1089 ALOGE("write failed: %s", strerror(errno));
1090 clearerr(fd);
1091 }
1092 rewind(fd);
1093 }
1094 }
1095
writeIntToFile(const char * file,uint32_t value)1096 int32_t writeIntToFile(const char* file, uint32_t value) {
1097 FILE* fd = fopen(file, "w+");
1098 if (fd == nullptr) {
1099 ALOGE("%s open failed! %s", file, strerror(errno));
1100 return -EINVAL;
1101 }
1102 writeFileNode(fd, value);
1103 fclose(fd);
1104 return 0;
1105 }
1106
load_png_image(const char * filepath,buffer_handle_t buffer)1107 int32_t load_png_image(const char* filepath, buffer_handle_t buffer) {
1108 png_structp png_ptr;
1109 png_infop info_ptr;
1110 int width, height, bpp, color_type;
1111
1112 VendorGraphicBufferMeta gmeta(buffer);
1113
1114 FILE* fp = fopen(filepath, "rb");
1115 if (fp == NULL) {
1116 ALOGE("%s open failed ", filepath);
1117 return -ENOENT;
1118 }
1119
1120 png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
1121 if (png_ptr == NULL) {
1122 fclose(fp);
1123 return -ENOMEM;
1124 }
1125
1126 info_ptr = png_create_info_struct(png_ptr);
1127 if (info_ptr == NULL) {
1128 fclose(fp);
1129 png_destroy_read_struct(&png_ptr, NULL, NULL);
1130 return -ENOMEM;
1131 }
1132
1133 if (setjmp(png_jmpbuf(png_ptr))) {
1134 fclose(fp);
1135 png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
1136 return -EIO;
1137 }
1138
1139 png_init_io(png_ptr, fp);
1140
1141 png_set_sig_bytes(png_ptr, 0);
1142 png_read_info(png_ptr, info_ptr);
1143
1144 width = png_get_image_width(png_ptr, info_ptr);
1145 height = png_get_image_height(png_ptr, info_ptr);
1146 if (width != gmeta.width || height != gmeta.height) {
1147 fclose(fp);
1148 png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
1149 return -EINVAL;
1150 }
1151
1152 bpp = png_get_bit_depth(png_ptr, info_ptr) * png_get_channels(png_ptr, info_ptr);
1153 color_type = png_get_color_type(png_ptr, info_ptr);
1154 if (color_type != PNG_COLOR_TYPE_RGB_ALPHA || bpp != formatToBpp(gmeta.format)) {
1155 fclose(fp);
1156 png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
1157 return -EINVAL;
1158 }
1159
1160 size_t bufferHandleSize = gmeta.stride * gmeta.vstride * formatToBpp(gmeta.format) / 8;
1161 size_t png_size = png_get_rowbytes(png_ptr, info_ptr) * height;
1162 if (bufferHandleSize > gmeta.size || (bufferHandleSize < png_size)) {
1163 fclose(fp);
1164 png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
1165 return -EINVAL;
1166 }
1167 void* bufferHandleData =
1168 mmap(0, bufferHandleSize, PROT_READ | PROT_WRITE, MAP_SHARED, gmeta.fd, 0);
1169
1170 if (bufferHandleData != MAP_FAILED && bufferHandleData != NULL) {
1171 int strideBytes = gmeta.stride * (formatToBpp(gmeta.format) / 8);
1172 png_bytep row_ptr = (png_bytep)bufferHandleData;
1173 for (int y = 0; y < height; ++y) {
1174 png_read_row(png_ptr, row_ptr, NULL);
1175 row_ptr += strideBytes;
1176 }
1177 munmap(bufferHandleData, bufferHandleSize);
1178 }
1179
1180 fclose(fp);
1181 png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
1182
1183 return 0;
1184 }
1185
readLineFromFile(const std::string & filename,std::string & out,char delim)1186 int readLineFromFile(const std::string &filename, std::string &out, char delim) {
1187 std::ifstream in(filename);
1188
1189 if (!in) {
1190 return -ENOENT;
1191 }
1192 std::getline(in, out, delim);
1193 if (!in) {
1194 return -EIO;
1195 }
1196
1197 return android::OK;
1198 }
1199
waitForPropertyValue(const std::string & property,int64_t timeoutMs)1200 std::optional<std::string> waitForPropertyValue(const std::string& property, int64_t timeoutMs) {
1201 if (!android::base::WaitForPropertyCreation(property, std::chrono::milliseconds(timeoutMs))) {
1202 return std::nullopt;
1203 }
1204 std::string out = android::base::GetProperty(property, "unknown");
1205 if (out == "unknown") {
1206 return std::nullopt;
1207 }
1208 return std::make_optional(out);
1209 }
1210
rectSize(const hwc_rect_t & rect)1211 uint32_t rectSize(const hwc_rect_t& rect) {
1212 auto width = rect.right - rect.left;
1213 auto height = rect.bottom - rect.top;
1214
1215 if (width <= 0 || height <= 0) return 0;
1216
1217 return width * height;
1218 }
1219
assign(decon_win_rect & win_rect,uint32_t left,uint32_t right,uint32_t width,uint32_t height)1220 void assign(decon_win_rect& win_rect, uint32_t left, uint32_t right, uint32_t width,
1221 uint32_t height) {
1222 win_rect.x = left;
1223 win_rect.y = right;
1224 win_rect.w = std::max(0U, width);
1225 win_rect.h = std::max(0U, height);
1226 }
1227