• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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