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 
17 /**
18  * Project HWC 2.0 Design
19  */
20 #define ATRACE_TAG (ATRACE_TAG_GRAPHICS | ATRACE_TAG_HAL)
21 #include <utils/Errors.h>
22 #include <sync/sync.h>
23 #include <sys/mman.h>
24 #include <cutils/properties.h>
25 #include "ExynosMPP.h"
26 #include "ExynosResourceRestriction.h"
27 #include <hardware/hwcomposer_defs.h>
28 #include <math.h>
29 #include "VendorGraphicBuffer.h"
30 #include "ExynosHWCDebug.h"
31 #include "ExynosDisplay.h"
32 #include "ExynosVirtualDisplay.h"
33 #include "ExynosLayer.h"
34 #include "ExynosHWCHelper.h"
35 #include "exynos_sync.h"
36 #include "ExynosResourceManager.h"
37 
38 /**
39  * ExynosMPP implementation
40  *
41  * Abstraction class for HW Resource
42  */
43 
44 using namespace android;
45 using namespace vendor::graphics;
46 
47 int ExynosMPP::mainDisplayWidth = 0;
48 int ExynosMPP::mainDisplayHeight = 0;
49 extern struct exynos_hwc_control exynosHWCControl;
50 #ifndef USE_MODULE_ATTR
51 extern feature_support_t feature_table[];
52 #endif
53 
dumpExynosMPPImgInfo(uint32_t type,exynos_mpp_img_info & imgInfo)54 void dumpExynosMPPImgInfo(uint32_t type, exynos_mpp_img_info &imgInfo)
55 {
56     HDEBUGLOGD(type, "\tbuffer: %p, bufferType: %d",
57             imgInfo.bufferHandle, imgInfo.bufferType);
58 }
59 
exynosMPPSourceComp(const ExynosMPPSource * l,const ExynosMPPSource * r)60 bool exynosMPPSourceComp(const ExynosMPPSource* l, const ExynosMPPSource* r)
61 {
62     if (l == NULL || r == NULL) {
63         HWC_LOGE(NULL,"exynosMPP compare error");
64         return 0;
65     }
66     return (l->mSrcImg.zOrder < r->mSrcImg.zOrder);
67 }
68 
dump(const restriction_size_t & restrictionSize,String8 & result)69 void dump(const restriction_size_t &restrictionSize, String8 &result) {
70     result.appendFormat("    maxDownScale = %u, maxUpscale = %u\n", restrictionSize.maxDownScale,
71                         restrictionSize.maxUpScale);
72     result.appendFormat("    maxFullWidth = %u, maxFullHeight = %u\n", restrictionSize.maxFullWidth,
73                         restrictionSize.maxFullHeight);
74     result.appendFormat("    minFullWidth = %u, minFullHeight = %u\n", restrictionSize.minFullWidth,
75                         restrictionSize.minFullHeight);
76     result.appendFormat("    fullWidthAlign = %u, fullHeightAlign = %u\n",
77                         restrictionSize.fullWidthAlign, restrictionSize.fullHeightAlign);
78     result.appendFormat("    maxCropWidth = %u, maxCropHeight = %u\n", restrictionSize.maxCropWidth,
79                         restrictionSize.maxCropHeight);
80     result.appendFormat("    minCropWidth = %u, minCropHeight = %u\n", restrictionSize.minCropWidth,
81                         restrictionSize.minCropHeight);
82     result.appendFormat("    cropXAlign = %u, cropYAlign = %u\n", restrictionSize.cropXAlign,
83                         restrictionSize.cropYAlign);
84     result.appendFormat("    cropWidthAlign = %u, cropHeightAlign = %u\n",
85                         restrictionSize.cropWidthAlign, restrictionSize.cropHeightAlign);
86 }
87 
ExynosMPPSource()88 ExynosMPPSource::ExynosMPPSource()
89     : mSourceType(MPP_SOURCE_MAX),
90     mSource(NULL),
91     mOtfMPP(NULL),
92     mM2mMPP(NULL)
93 {
94     memset(&mSrcImg, 0, sizeof(mSrcImg));
95     mSrcImg.acquireFenceFd = -1;
96     mSrcImg.releaseFenceFd = -1;
97     memset(&mDstImg, 0, sizeof(mDstImg));
98     mDstImg.acquireFenceFd = -1;
99     mDstImg.releaseFenceFd = -1;
100     memset(&mMidImg, 0, sizeof(mMidImg));
101     mMidImg.acquireFenceFd = -1;
102     mMidImg.releaseFenceFd = -1;
103 }
104 
ExynosMPPSource(uint32_t sourceType,void * source)105 ExynosMPPSource::ExynosMPPSource(uint32_t sourceType, void *source)
106     : mSourceType(sourceType),
107     mSource(source),
108     mOtfMPP(NULL),
109     mM2mMPP(NULL)
110 {
111     memset(&mSrcImg, 0, sizeof(mSrcImg));
112     mSrcImg.acquireFenceFd = -1;
113     mSrcImg.releaseFenceFd = -1;
114     memset(&mDstImg, 0, sizeof(mDstImg));
115     mDstImg.acquireFenceFd = -1;
116     mDstImg.releaseFenceFd = -1;
117     memset(&mMidImg, 0, sizeof(mMidImg));
118     mMidImg.acquireFenceFd = -1;
119     mMidImg.releaseFenceFd = -1;
120 }
121 
setExynosImage(exynos_image src_img,exynos_image dst_img)122 void ExynosMPPSource::setExynosImage(exynos_image src_img, exynos_image dst_img)
123 {
124     mSrcImg = src_img;
125     mDstImg = dst_img;
126 }
127 
setExynosMidImage(exynos_image mid_img)128 void ExynosMPPSource::setExynosMidImage(exynos_image mid_img)
129 {
130     mMidImg = mid_img;
131 }
132 
ExynosMPP(ExynosResourceManager * resourceManager,uint32_t physicalType,uint32_t logicalType,const char * name,uint32_t physicalIndex,uint32_t logicalIndex,uint32_t preAssignInfo)133 ExynosMPP::ExynosMPP(ExynosResourceManager* resourceManager,
134         uint32_t physicalType, uint32_t logicalType, const char *name,
135         uint32_t physicalIndex, uint32_t logicalIndex, uint32_t preAssignInfo)
136 : mResourceManager(resourceManager),
137     mMPPType(MPP_TYPE_NONE),
138     mPhysicalType(physicalType),
139     mLogicalType(logicalType),
140     mName(name),
141     mPhysicalIndex(physicalIndex),
142     mLogicalIndex(logicalIndex),
143     mPreAssignDisplayInfo(preAssignInfo),
144     mHWState(MPP_HW_STATE_IDLE),
145     mLastStateFenceFd(-1),
146     mAssignedState(MPP_ASSIGN_STATE_FREE),
147     mEnable(true),
148     mAssignedDisplay(NULL),
149     mMaxSrcLayerNum(1),
150     mPrevAssignedState(MPP_ASSIGN_STATE_FREE),
151     mPrevAssignedDisplayType(-1),
152     mReservedDisplay(-1),
153     mResourceManageThread(android::sp<ResourceManageThread>::make(this)),
154     mCapacity(-1),
155     mUsedCapacity(0),
156     mAllocOutBufFlag(true),
157     mFreeOutBufFlag(true),
158     mHWBusyFlag(false),
159     mCurrentDstBuf(0),
160     mPrivDstBuf(-1),
161     mNeedCompressedTarget(false),
162     mDstAllocatedSize(DST_SIZE_UNKNOWN),
163     mUseM2MSrcFence(false),
164     mAttr(0),
165     mNeedSolidColorLayer(false)
166 {
167     if (mPhysicalType < MPP_DPP_NUM) {
168         mClockKhz = VPP_CLOCK;
169         mPPC = VPP_PIXEL_PER_CLOCK;
170     }
171 
172     if (mPhysicalType == MPP_G2D) {
173         mClockKhz = G2D_CLOCK;
174         if (mLogicalType == MPP_LOGICAL_G2D_RGB) {
175 
176             char value[256];
177             int afbc_prop;
178             property_get("ro.vendor.ddk.set.afbc", value, "0");
179             afbc_prop = atoi(value);
180             if (afbc_prop == 0)
181                 mNeedCompressedTarget = false;
182             else
183                 mNeedCompressedTarget = true;
184 
185             mMaxSrcLayerNum = G2D_MAX_SRC_NUM;
186         } else if (mLogicalType == MPP_LOGICAL_G2D_COMBO &&
187                 (mPreAssignDisplayInfo & HWC_DISPLAY_VIRTUAL_BIT)) {
188             mMaxSrcLayerNum = G2D_MAX_SRC_NUM - 1;
189             mAllocOutBufFlag = false;
190             mNeedCompressedTarget = false;
191             mUseM2MSrcFence = true;
192         }
193         /* Capacity means time(ms) that can be used for operation */
194         mCapacity = MPP_G2D_CAPACITY;
195         mAcrylicHandle = AcrylicFactory::createAcrylic("default_compositor");
196         if (mAcrylicHandle == NULL) {
197             MPP_LOGE("Fail to allocate acrylic handle");
198             abort();
199         } else {
200             MPP_LOGI("mAcrylicHandle is created: %p", mAcrylicHandle);
201         }
202     }
203 
204     /* Basic feature supported flags */
205     for (const auto &feature: feature_table) {
206         if (feature.hwType == mPhysicalType)
207             mAttr = feature.attr;
208     }
209 
210     if (mPhysicalType == MPP_MSC) {
211         mClockKhz = MSC_CLOCK;
212         /* To do
213         * Capacity should be set
214         */
215         mCapacity = MPP_MSC_CAPACITY;
216         mAcrylicHandle = AcrylicFactory::createAcrylic("default_scaler");
217         if (mAcrylicHandle == NULL) {
218             MPP_LOGE("Fail to allocate acrylic handle");
219             abort();
220         } else {
221             MPP_LOGI("mAcrylicHandle is created: %p", mAcrylicHandle);
222         }
223     }
224 
225     if (mMaxSrcLayerNum > 1) {
226         mNeedSolidColorLayer = true;
227         mAcrylicHandle->setDefaultColor(0, 0, 0, 0);
228     }
229 
230     mAssignedSources.clear();
231     resetUsedCapacity();
232 
233     mResourceManageThread->mRunning = true;
234     mResourceManageThread->run("MPPThread");
235 
236     memset(&mPrevFrameInfo, 0, sizeof(mPrevFrameInfo));
237     for (int i = 0; i < NUM_MPP_SRC_BUFS; i++) {
238         mPrevFrameInfo.srcInfo[i].acquireFenceFd = -1;
239         mPrevFrameInfo.srcInfo[i].releaseFenceFd = -1;
240         mPrevFrameInfo.dstInfo[i].acquireFenceFd = -1;
241         mPrevFrameInfo.dstInfo[i].releaseFenceFd = -1;
242     }
243 
244     for (uint32_t i = 0; i < NUM_MPP_SRC_BUFS; i++) {
245         memset(&mSrcImgs[i], 0, sizeof(mSrcImgs[i]));
246         mSrcImgs[i].acrylicAcquireFenceFd = -1;
247         mSrcImgs[i].acrylicReleaseFenceFd = -1;
248     }
249     for (uint32_t i = 0; i < NUM_MPP_DST_BUFS(mLogicalType); i++) {
250         memset(&mDstImgs[i], 0, sizeof(mDstImgs[i]));
251         mDstImgs[i].acrylicAcquireFenceFd = -1;
252         mDstImgs[i].acrylicReleaseFenceFd = -1;
253     }
254 
255     for (uint32_t i = 0; i < DISPLAY_MODE_NUM; i++)
256     {
257         mPreAssignDisplayList[i] = (preAssignInfo >> (DISPLAY_MODE_MASK_LEN * i)) & DISPLAY_MODE_MASK_BIT;
258     }
259 }
260 
~ExynosMPP()261 ExynosMPP::~ExynosMPP()
262 {
263     mResourceManageThread->mRunning = false;
264     mResourceManageThread->requestExitAndWait();
265 }
266 
267 
ResourceManageThread(ExynosMPP * exynosMPP)268 ExynosMPP::ResourceManageThread::ResourceManageThread(ExynosMPP *exynosMPP)
269 : mExynosMPP(exynosMPP),
270     mRunning(false)
271 {
272 }
273 
~ResourceManageThread()274 ExynosMPP::ResourceManageThread::~ResourceManageThread()
275 {
276 }
277 
isDataspaceSupportedByMPP(struct exynos_image & src,struct exynos_image & dst)278 bool ExynosMPP::isDataspaceSupportedByMPP(struct exynos_image &src, struct exynos_image &dst)
279 {
280     uint32_t srcStandard = (src.dataSpace & HAL_DATASPACE_STANDARD_MASK);
281     uint32_t dstStandard = (dst.dataSpace & HAL_DATASPACE_STANDARD_MASK);
282     uint32_t srcTransfer = (src.dataSpace & HAL_DATASPACE_TRANSFER_MASK);
283     uint32_t dstTransfer = (dst.dataSpace & HAL_DATASPACE_TRANSFER_MASK);
284 
285     /* No conversion case */
286     if ((srcStandard == dstStandard) && (srcTransfer == dstTransfer))
287         return true;
288 
289     /* Unspecified conversion case */
290     if (((srcStandard == HAL_DATASPACE_STANDARD_UNSPECIFIED) ||
291          (dstStandard == HAL_DATASPACE_STANDARD_UNSPECIFIED)) &&
292         ((srcTransfer == HAL_DATASPACE_TRANSFER_UNSPECIFIED) ||
293          (dstTransfer == HAL_DATASPACE_TRANSFER_UNSPECIFIED)))
294         return true;
295 
296     /* WCG support check */
297     /* 'Src is not HDR' and 'src,dst has differenct dataspace' means WCG case */
298     /* Some MPPs are only support HDR but WCG */
299     if (!hasHdrInfo(src) && ((mAttr & MPP_ATTR_WCG) == 0))
300         return false;
301 
302     /* Standard support check */
303     auto standard_it = dataspace_standard_map.find(srcStandard);
304     if ((standard_it == dataspace_standard_map.end()) ||
305         ((mAttr & standard_it->second) == 0))
306         return false;
307 
308     /* Transfer support check */
309     auto transfer_it = dataspace_transfer_map.find(srcTransfer);
310     if ((transfer_it == dataspace_transfer_map.end()) ||
311         ((mAttr & transfer_it->second) == 0))
312         return false;
313 
314     return checkCSCRestriction(src, dst);
315 }
316 
isSupportedHDR10Plus(struct exynos_image & src,struct exynos_image & dst)317 bool ExynosMPP::isSupportedHDR10Plus(struct exynos_image &src, struct exynos_image &dst)
318 {
319 
320     uint32_t srcStandard = (src.dataSpace & HAL_DATASPACE_STANDARD_MASK);
321     uint32_t dstStandard = (dst.dataSpace & HAL_DATASPACE_STANDARD_MASK);
322     uint32_t srcTransfer = (src.dataSpace & HAL_DATASPACE_TRANSFER_MASK);
323     uint32_t dstTransfer = (dst.dataSpace & HAL_DATASPACE_TRANSFER_MASK);
324 
325     if (hasHdr10Plus(src)) {
326         if (mAttr & MPP_ATTR_HDR10PLUS)
327             return true;
328         else if ((srcStandard == dstStandard) && (srcTransfer == dstTransfer))
329             return true;
330         else if ((mLogicalType == MPP_LOGICAL_G2D_COMBO) && (mPreAssignDisplayInfo & HWC_DISPLAY_VIRTUAL_BIT))
331             return true;
332         else
333             return false;
334     }
335     return true;
336 }
337 
isSupportedHStrideCrop(struct exynos_image __unused & src)338 bool ExynosMPP::isSupportedHStrideCrop(struct exynos_image __unused &src)
339 {
340     return true;
341 }
342 
isSupportedBlend(struct exynos_image & src)343 bool ExynosMPP::isSupportedBlend(struct exynos_image &src)
344 {
345     switch(src.blending) {
346     case HWC2_BLEND_MODE_NONE:
347     case HWC2_BLEND_MODE_PREMULTIPLIED:
348     case HWC2_BLEND_MODE_COVERAGE:
349         return true;
350     default:
351         return false;
352     }
353 }
354 
checkRotationCondition(struct exynos_image & src)355 bool ExynosMPP::checkRotationCondition(struct exynos_image &src)
356 {
357     /* Check only DPP types */
358     if (mPhysicalType >= MPP_DPP_NUM)
359         return true;
360 
361     /* If DPP has their own restriction, implmemnt module codes */
362     if (mAttr & MPP_ATTR_ROT_90) {
363         if (isFormatYUV420(src.format) == true)
364             return true;
365     }
366 
367     /* Other DPPs */
368     if ((src.transform & HAL_TRANSFORM_ROT_90) == 0)
369     {
370         if ((src.compressed == 1) && (src.transform != 0))
371             return false;
372         return true;
373     } else {
374         return false;
375     }
376 
377     return true;
378 }
379 
isSupportedTransform(struct exynos_image & src)380 bool ExynosMPP::isSupportedTransform(struct exynos_image &src)
381 {
382     if (src.transform == 0) return true;
383 
384     /* If MPP need to check additional condition,
385      * implement checkRotationCondition function to check it */
386     /* For example, DPP need to check custom conditons */
387     if (!checkRotationCondition(src))
388         return false;
389 
390     for(auto transform_map : transform_map_table) {
391         if (src.transform & transform_map.hal_tr) {
392             if (!(mAttr & transform_map.hwc_tr))
393                 return false;
394         }
395     }
396 
397     return true;
398 }
399 
isSupportedCompression(struct exynos_image & src)400 bool ExynosMPP::isSupportedCompression(struct exynos_image &src)
401 {
402     if (src.compressed) {
403         if (mAttr & MPP_ATTR_AFBC)
404             return true;
405         else
406             return false;
407     } else {
408         return true;
409     }
410 }
411 
isSupportedCapability(ExynosDisplay & display,struct exynos_image & src)412 bool ExynosMPP::isSupportedCapability(ExynosDisplay &display, struct exynos_image &src)
413 {
414     if (display.mType != HWC_DISPLAY_EXTERNAL)
415         return true;
416 
417     if (!(mAttr & MPP_ATTR_USE_CAPA))
418         return true;
419 
420     if (mResourceManager->hasHdrLayer || mResourceManager->hasDrmLayer) {
421         if (getDrmMode(src.usageFlags) != NO_DRM)
422             return true;
423         else if (hasHdrInfo(src))
424             return true;
425         else
426             return false;
427     }
428 
429     return true;
430 }
431 
isSupportedDRM(struct exynos_image & src)432 bool ExynosMPP::isSupportedDRM(struct exynos_image &src)
433 {
434     if (getDrmMode(src.usageFlags) == NO_DRM)
435         return true;
436 
437     if (mLogicalType == MPP_LOGICAL_G2D_RGB)
438         return false;
439 
440     return true;
441 }
442 
checkCSCRestriction(struct exynos_image & src,struct exynos_image & dst)443 bool ExynosMPP::checkCSCRestriction(struct exynos_image &src, struct exynos_image &dst)
444 {
445     return true;
446 }
447 
isDimLayerSupported()448 bool ExynosMPP::isDimLayerSupported()
449 {
450     if (mAttr & MPP_ATTR_DIM)
451         return true;
452 
453     return false;
454 }
455 
isSrcFormatSupported(struct exynos_image & src)456 bool ExynosMPP::isSrcFormatSupported(struct exynos_image &src)
457 {
458     if (mLogicalType == MPP_LOGICAL_G2D_YUV) {
459         /* Support YUV layer and HDR RGB layer */
460         if (isFormatRgb(src.format) && (hasHdrInfo(src) == false))
461             return false;
462     }
463     if ((mLogicalType == MPP_LOGICAL_G2D_RGB) &&
464         isFormatYUV(src.format))
465         return false;
466     if ((mLogicalType == MPP_LOGICAL_MSC_YUV) &&
467         isFormatRgb(src.format)) {
468         return false;
469     }
470 
471     if (mResourceManager == NULL) return false;
472 
473     for (uint32_t i = 0 ; i < mResourceManager->mFormatRestrictionCnt; i++) {
474         if ((mResourceManager->mFormatRestrictions[i].hwType == mPhysicalType) &&
475                 ((mResourceManager->mFormatRestrictions[i].nodeType == NODE_NONE) ||
476                  (mResourceManager->mFormatRestrictions[i].nodeType == NODE_SRC)) &&
477                 (mResourceManager->mFormatRestrictions[i].format == src.format))
478             return true;
479     }
480 
481     return false;
482 }
483 
isDstFormatSupported(struct exynos_image & dst)484 bool ExynosMPP::isDstFormatSupported(struct exynos_image &dst)
485 {
486 
487     for (uint32_t i = 0 ; i < mResourceManager->mFormatRestrictionCnt; i++) {
488         if ((mResourceManager->mFormatRestrictions[i].hwType == mPhysicalType) &&
489                 ((mResourceManager->mFormatRestrictions[i].nodeType == NODE_NONE) ||
490                  (mResourceManager->mFormatRestrictions[i].nodeType == NODE_DST)) &&
491                 (mResourceManager->mFormatRestrictions[i].format == dst.format))
492             return true;
493     }
494 
495     return false;
496 }
497 
getMaxUpscale(const struct exynos_image & src,const struct exynos_image __unused & dst) const498 uint32_t ExynosMPP::getMaxUpscale(const struct exynos_image &src,
499                                   const struct exynos_image __unused &dst) const {
500     uint32_t idx = getRestrictionClassification(src);
501     return mSrcSizeRestrictions[idx].maxUpScale;
502 }
503 
checkDownscaleCap(const float resolution,const float displayRatio_V) const504 bool ExynosMPP::checkDownscaleCap(const float resolution, const float displayRatio_V) const {
505     if (mPhysicalType >= MPP_DPP_NUM) return true;
506 
507     return float(mClockKhz) >= ((resolution * VPP_RESOL_MARGIN) / (mPPC * displayRatio_V));
508 }
509 
getDownscaleRestriction(const struct exynos_image & src,const struct exynos_image &) const510 uint32_t ExynosMPP::getDownscaleRestriction(const struct exynos_image &src,
511                                             const struct exynos_image & /*dst*/) const {
512     auto idx = getRestrictionClassification(src);
513     return mDstSizeRestrictions[idx].maxDownScale;
514 }
515 
getMaxDownscale(const ExynosDisplay & display,const struct exynos_image & src,const struct exynos_image & dst) const516 uint32_t ExynosMPP::getMaxDownscale(const ExynosDisplay &display, const struct exynos_image &src,
517                                     const struct exynos_image &dst) const {
518     uint32_t maxDownscale = getDownscaleRestriction(src, dst);
519 
520     if (maxDownscale <= 1) {
521         return maxDownscale;
522     }
523 
524     if (mPhysicalType < MPP_DPP_NUM) {
525         float resolution = float(src.w) * float(src.h) * display.getBtsRefreshRate() / 1000;
526         if (!checkDownscaleCap(resolution, float(dst.h) / float(display.mYres))) {
527             return 1;
528         }
529     }
530 
531     return maxDownscale;
532 }
533 
getSrcXOffsetAlign(struct exynos_image & src)534 uint32_t ExynosMPP::getSrcXOffsetAlign(struct exynos_image &src)
535 {
536     /* Refer module(ExynosMPPModule) for chip specific restrictions */
537     uint32_t idx = getRestrictionClassification(src);
538     if ((mPhysicalType == MPP_MSC) &&
539             ((src.format == HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_S10B) ||
540             (src.format == HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_S10B))) {
541         return 16;
542     }
543     return mSrcSizeRestrictions[idx].cropXAlign;
544 }
getSrcXOffsetAlign(uint32_t idx)545 uint32_t ExynosMPP::getSrcXOffsetAlign(uint32_t idx)
546 {
547     if (idx >= RESTRICTION_MAX)
548     {
549         MPP_LOGE("invalid idx: %d", idx);
550         return 16;
551     }
552     return mSrcSizeRestrictions[idx].cropXAlign;
553 }
getSrcYOffsetAlign(struct exynos_image & src)554 uint32_t ExynosMPP::getSrcYOffsetAlign(struct exynos_image &src)
555 {
556     uint32_t idx = getRestrictionClassification(src);
557     return mSrcSizeRestrictions[idx].cropYAlign;
558 }
getSrcYOffsetAlign(uint32_t idx)559 uint32_t ExynosMPP::getSrcYOffsetAlign(uint32_t idx)
560 {
561     if (idx >= RESTRICTION_MAX)
562     {
563         MPP_LOGE("invalid idx: %d", idx);
564         return 16;
565     }
566     return mSrcSizeRestrictions[idx].cropYAlign;
567 }
getSrcWidthAlign(struct exynos_image & src)568 uint32_t ExynosMPP::getSrcWidthAlign(struct exynos_image &src)
569 {
570     uint32_t idx = getRestrictionClassification(src);
571     return mSrcSizeRestrictions[idx].fullWidthAlign;
572 }
getSrcHeightAlign(struct exynos_image & src)573 uint32_t ExynosMPP::getSrcHeightAlign(struct exynos_image &src)
574 {
575     uint32_t idx = getRestrictionClassification(src);
576     return mSrcSizeRestrictions[idx].fullHeightAlign;
577 }
getSrcMaxWidth(struct exynos_image & src)578 uint32_t ExynosMPP::getSrcMaxWidth(struct exynos_image &src)
579 {
580     if (isFormatYUV(src.format))
581         return 4096;
582 
583     uint32_t idx = getRestrictionClassification(src);
584     return mSrcSizeRestrictions[idx].maxFullWidth;
585 }
getSrcMaxHeight(struct exynos_image & src)586 uint32_t ExynosMPP::getSrcMaxHeight(struct exynos_image &src)
587 {
588     if (isFormatYUV(src.format))
589         return 4096;
590 
591     uint32_t idx = getRestrictionClassification(src);
592     return mSrcSizeRestrictions[idx].maxFullHeight;
593 }
getSrcMinWidth(struct exynos_image & src)594 uint32_t ExynosMPP::getSrcMinWidth(struct exynos_image &src)
595 {
596     uint32_t idx = getRestrictionClassification(src);
597     return mSrcSizeRestrictions[idx].minFullWidth;
598 }
getSrcMinWidth(uint32_t idx)599 uint32_t ExynosMPP::getSrcMinWidth(uint32_t idx)
600 {
601     if (idx >= RESTRICTION_MAX)
602     {
603         MPP_LOGE("invalid idx: %d", idx);
604         return 16;
605     }
606     return mSrcSizeRestrictions[idx].minFullWidth;
607 }
getSrcMinHeight(struct exynos_image & src)608 uint32_t ExynosMPP::getSrcMinHeight(struct exynos_image &src)
609 {
610     uint32_t idx = getRestrictionClassification(src);
611     return mSrcSizeRestrictions[idx].minFullHeight;
612 }
getSrcMinHeight(uint32_t idx)613 uint32_t ExynosMPP::getSrcMinHeight(uint32_t idx)
614 {
615     if (idx >= RESTRICTION_MAX)
616     {
617         MPP_LOGE("invalid idx: %d", idx);
618         return 16;
619     }
620     return mSrcSizeRestrictions[idx].minFullHeight;
621 }
getSrcMaxCropWidth(struct exynos_image & src)622 uint32_t ExynosMPP::getSrcMaxCropWidth(struct exynos_image &src)
623 {
624     uint32_t idx = getRestrictionClassification(src);
625     return mSrcSizeRestrictions[idx].maxCropWidth;
626 }
getSrcMaxCropHeight(struct exynos_image & src)627 uint32_t ExynosMPP::getSrcMaxCropHeight(struct exynos_image &src)
628 {
629     if ((mMPPType == MPP_TYPE_OTF) &&
630         (src.transform & HAL_TRANSFORM_ROT_90))
631         return 2160;
632 
633     uint32_t idx = getRestrictionClassification(src);
634     return mSrcSizeRestrictions[idx].maxCropHeight;
635 }
getSrcMaxCropSize(struct exynos_image & src)636 uint32_t ExynosMPP::getSrcMaxCropSize(struct exynos_image &src)
637 {
638     return (getSrcMaxCropWidth(src) * getSrcMaxCropHeight(src));
639 }
getSrcMinCropWidth(struct exynos_image & src)640 uint32_t ExynosMPP::getSrcMinCropWidth(struct exynos_image &src)
641 {
642     if (((src.format == HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_S10B) ||
643          (src.format == HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_S10B)) &&
644         (mPhysicalType == MPP_G2D))
645         return 2;
646     uint32_t idx = getRestrictionClassification(src);
647     return mSrcSizeRestrictions[idx].minCropWidth;
648 }
getSrcMinCropHeight(struct exynos_image & src)649 uint32_t ExynosMPP::getSrcMinCropHeight(struct exynos_image &src)
650 {
651     if (((src.format == HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_S10B) ||
652          (src.format == HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_S10B)) &&
653         (mPhysicalType == MPP_G2D))
654         return 2;
655     uint32_t idx = getRestrictionClassification(src);
656     return mSrcSizeRestrictions[idx].minCropHeight;
657 }
getSrcCropWidthAlign(const struct exynos_image & src) const658 uint32_t ExynosMPP::getSrcCropWidthAlign(const struct exynos_image &src) const {
659     if (((src.format == HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_S10B) ||
660          (src.format == HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_S10B)) &&
661         (mPhysicalType == MPP_G2D))
662         return 2;
663     uint32_t idx = getRestrictionClassification(src);
664     return mSrcSizeRestrictions[idx].cropWidthAlign;
665 }
666 
667 /* This is used for only otfMPP */
getSrcCropWidthAlign(uint32_t idx) const668 uint32_t ExynosMPP::getSrcCropWidthAlign(uint32_t idx) const {
669     if (idx >= RESTRICTION_MAX)
670     {
671         MPP_LOGE("invalid idx: %d", idx);
672         return 16;
673     }
674     return mSrcSizeRestrictions[idx].cropWidthAlign;
675 }
getSrcCropHeightAlign(const struct exynos_image & src) const676 uint32_t ExynosMPP::getSrcCropHeightAlign(const struct exynos_image &src) const {
677     if (((src.format == HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_S10B) ||
678          (src.format == HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_S10B)) &&
679         (mPhysicalType == MPP_G2D))
680         return 2;
681 
682     uint32_t idx = getRestrictionClassification(src);
683     return mSrcSizeRestrictions[idx].cropHeightAlign;
684 }
685 
686 /* This is used for only otfMPP */
getSrcCropHeightAlign(uint32_t idx) const687 uint32_t ExynosMPP::getSrcCropHeightAlign(uint32_t idx) const {
688     if (idx >= RESTRICTION_MAX)
689     {
690         MPP_LOGE("invalid idx: %d", idx);
691         return 16;
692     }
693     return mSrcSizeRestrictions[idx].cropHeightAlign;
694 }
getDstMaxWidth(struct exynos_image & dst)695 uint32_t ExynosMPP::getDstMaxWidth(struct exynos_image &dst)
696 {
697     uint32_t idx = getRestrictionClassification(dst);
698     return mDstSizeRestrictions[idx].maxCropWidth;
699 }
getDstMaxHeight(struct exynos_image & dst)700 uint32_t ExynosMPP::getDstMaxHeight(struct exynos_image &dst)
701 {
702     uint32_t idx = getRestrictionClassification(dst);
703     return mDstSizeRestrictions[idx].maxCropHeight;
704 }
getDstMinWidth(struct exynos_image & dst)705 uint32_t ExynosMPP::getDstMinWidth(struct exynos_image &dst)
706 {
707     if (((dst.format == HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_S10B) ||
708          (dst.format == HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_S10B)) &&
709         (mPhysicalType == MPP_G2D))
710         return 64;
711 
712     if ((mNeedSolidColorLayer == false) && mNeedCompressedTarget)
713         return 16;
714 
715     if ((mPhysicalType == MPP_G2D) && (mNeedSolidColorLayer == false) &&
716             isFormatSBWC(dst.format))
717         return 32;
718 
719     uint32_t idx = getRestrictionClassification(dst);
720     return mDstSizeRestrictions[idx].minCropWidth;
721 }
getDstMinHeight(struct exynos_image & dst)722 uint32_t ExynosMPP::getDstMinHeight(struct exynos_image &dst)
723 {
724     if ((mNeedSolidColorLayer == false) && mNeedCompressedTarget)
725         return 16;
726 
727     if ((mPhysicalType == MPP_G2D) && (mNeedSolidColorLayer == false) &&
728             isFormatSBWC(dst.format))
729         return 8;
730 
731     uint32_t idx = getRestrictionClassification(dst);
732     return mDstSizeRestrictions[idx].minCropHeight;
733 }
getDstWidthAlign(const struct exynos_image & dst) const734 uint32_t ExynosMPP::getDstWidthAlign(const struct exynos_image &dst) const {
735     if (((dst.format == HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_S10B) ||
736          (dst.format == HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_S10B)) &&
737         (mPhysicalType == MPP_G2D))
738         return 64;
739 
740     if ((mNeedSolidColorLayer == false) && mNeedCompressedTarget)
741         return 16;
742 
743     if ((mPhysicalType == MPP_G2D) && (mNeedSolidColorLayer == false) &&
744             isFormatSBWC(dst.format))
745         return 32;
746 
747     uint32_t idx = getRestrictionClassification(dst);
748     return mDstSizeRestrictions[idx].cropWidthAlign;
749 }
getDstHeightAlign(const struct exynos_image & dst) const750 uint32_t ExynosMPP::getDstHeightAlign(const struct exynos_image &dst) const {
751     if ((mNeedSolidColorLayer == false) && mNeedCompressedTarget)
752         return 16;
753 
754     if ((mPhysicalType == MPP_G2D) && (mNeedSolidColorLayer == false) &&
755             isFormatSBWC(dst.format))
756         return 8;
757 
758     uint32_t idx = getRestrictionClassification(dst);
759     return mDstSizeRestrictions[idx].cropHeightAlign;
760 }
getDstXOffsetAlign(struct exynos_image & dst)761 uint32_t ExynosMPP::getDstXOffsetAlign(struct exynos_image &dst)
762 {
763     if ((mNeedSolidColorLayer == false) && mNeedCompressedTarget)
764         return 16;
765 
766     if ((mPhysicalType == MPP_G2D) && (mNeedSolidColorLayer == false) &&
767             isFormatSBWC(dst.format))
768         return 32;
769 
770     uint32_t idx = getRestrictionClassification(dst);
771     return mDstSizeRestrictions[idx].cropXAlign;
772 }
getDstYOffsetAlign(struct exynos_image & dst)773 uint32_t ExynosMPP::getDstYOffsetAlign(struct exynos_image &dst)
774 {
775     if ((mNeedSolidColorLayer == false) && mNeedCompressedTarget)
776         return 16;
777 
778     if ((mPhysicalType == MPP_G2D) && (mNeedSolidColorLayer == false) &&
779             isFormatSBWC(dst.format))
780         return 8;
781 
782     uint32_t idx = getRestrictionClassification(dst);
783     return mDstSizeRestrictions[idx].cropYAlign;
784 }
getOutBufAlign()785 uint32_t ExynosMPP::getOutBufAlign()
786 {
787     if (mNeedCompressedTarget)
788         return 16;
789     else
790         return 1;
791 }
792 
isSupportLayerColorTransform(struct exynos_image & src,struct exynos_image __unused & dst)793 int32_t ExynosMPP::isSupportLayerColorTransform(
794         struct exynos_image &src, struct exynos_image __unused &dst)
795 {
796     if (src.needColorTransform == false)
797         return true;
798 
799     if (mAttr & MPP_ATTR_LAYER_TRANSFORM)
800         return true;
801 
802     return false;
803 }
804 
threadLoop()805 bool ExynosMPP::ResourceManageThread::threadLoop()
806 {
807     if (mExynosMPP == NULL)
808         return false;
809 
810     ALOGI("%s threadLoop is started", mExynosMPP->mName.string());
811     while(mRunning) {
812         Mutex::Autolock lock(mMutex);
813         while((mFreedBuffers.size() == 0) &&
814                 (mStateFences.size() == 0)) {
815             mCondition.wait(mMutex);
816         }
817 
818         if ((mExynosMPP->mHWState == MPP_HW_STATE_RUNNING) &&
819                 (mStateFences.size() != 0)) {
820             if (checkStateFences()) {
821                 mExynosMPP->mHWState = MPP_HW_STATE_IDLE;
822             }
823         } else {
824             if ((mStateFences.size() != 0) &&
825                     (mExynosMPP->mHWState != MPP_HW_STATE_RUNNING)) {
826                 ALOGW("%s, mHWState(%d) but mStateFences size(%zu)",
827                         mExynosMPP->mName.string(), mExynosMPP->mHWState,
828                         mStateFences.size());
829                 checkStateFences();
830             }
831         }
832 
833         if (mFreedBuffers.size() != 0) {
834             freeBuffers();
835         }
836     }
837     return true;
838 }
839 
freeBuffers()840 void ExynosMPP::ResourceManageThread::freeBuffers()
841 {
842     VendorGraphicBufferAllocator& gAllocator(VendorGraphicBufferAllocator::get());
843     android::List<exynos_mpp_img_info >::iterator it;
844     android::List<exynos_mpp_img_info >::iterator end;
845     it = mFreedBuffers.begin();
846     end = mFreedBuffers.end();
847 
848     uint32_t freebufNum = 0;
849     while (it != end) {
850         exynos_mpp_img_info freeBuffer = (exynos_mpp_img_info)(*it);
851         HDEBUGLOGD(eDebugMPP|eDebugFence|eDebugBuf, "freebufNum: %d, buffer: %p", freebufNum, freeBuffer.bufferHandle);
852         dumpExynosMPPImgInfo(eDebugMPP|eDebugFence|eDebugBuf, freeBuffer);
853         if (fence_valid(freeBuffer.acrylicAcquireFenceFd)) {
854             if (sync_wait(freeBuffer.acrylicAcquireFenceFd, 1000) < 0)
855                 HWC_LOGE(NULL, "%s:: acquire fence sync_wait error", mExynosMPP->mName.string());
856             freeBuffer.acrylicAcquireFenceFd =
857                 fence_close(freeBuffer.acrylicAcquireFenceFd, mExynosMPP->mAssignedDisplay,
858                         FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_ALL);
859         }
860         if (fence_valid(freeBuffer.acrylicReleaseFenceFd)) {
861             if (sync_wait(freeBuffer.acrylicReleaseFenceFd, 1000) < 0)
862                 HWC_LOGE(NULL, "%s:: release fence sync_wait error", mExynosMPP->mName.string());
863             freeBuffer.acrylicReleaseFenceFd =
864                 fence_close(freeBuffer.acrylicReleaseFenceFd, mExynosMPP->mAssignedDisplay,
865                         FENCE_TYPE_SRC_RELEASE, FENCE_IP_ALL);
866         }
867         gAllocator.free(freeBuffer.bufferHandle);
868         it = mFreedBuffers.erase(it);
869     }
870 }
871 
checkStateFences()872 bool ExynosMPP::ResourceManageThread::checkStateFences()
873 {
874     bool ret = true;
875     android::List<int >::iterator it;
876     android::List<int >::iterator end;
877 
878     it = mStateFences.begin();
879     end = mStateFences.end();
880     uint32_t waitFenceNum = 0;
881     while (it != end) {
882         int fence = (int)(*it);
883         HDEBUGLOGD(eDebugMPP|eDebugFence, "%d wait fence: %d", waitFenceNum, fence);
884         waitFenceNum++;
885         if (fence_valid(fence)) {
886             if (sync_wait(fence, 5000) < 0) {
887                 HWC_LOGE(NULL, "%s::[%s][%d] sync_wait(%d) error(%s)", __func__,
888                         mExynosMPP->mName.string(), mExynosMPP->mLogicalIndex, fence, strerror(errno));
889                 ret = false;
890             }
891             fence = fence_close(fence, mExynosMPP->mAssignedDisplay,
892                     FENCE_TYPE_ALL, FENCE_IP_ALL);
893         }
894         it = mStateFences.erase(it);
895     }
896     return ret;
897 }
898 
addFreedBuffer(exynos_mpp_img_info freedBuffer)899 void ExynosMPP::ResourceManageThread::addFreedBuffer(exynos_mpp_img_info freedBuffer)
900 {
901     android::Mutex::Autolock lock(mMutex);
902     mFreedBuffers.push_back(freedBuffer);
903     mCondition.signal();
904 }
905 
addStateFence(int fence)906 void ExynosMPP::ResourceManageThread::addStateFence(int fence)
907 {
908     Mutex::Autolock lock(mMutex);
909     HDEBUGLOGD(eDebugMPP|eDebugFence, "wait fence is added: %d", fence);
910     mStateFences.push_back(fence);
911     mCondition.signal();
912 }
913 
914 /**
915  * @param w
916  * @param h
917  * @param color
918  * @param usage
919  * @return int32_t
920  */
allocOutBuf(uint32_t w,uint32_t h,uint32_t format,uint64_t usage,uint32_t index)921 int32_t ExynosMPP::allocOutBuf(uint32_t w, uint32_t h, uint32_t format, uint64_t usage, uint32_t index) {
922     ATRACE_CALL();
923     uint32_t dstStride = 0;
924 
925     MPP_LOGD(eDebugMPP|eDebugBuf, "index: %d++++++++", index);
926 
927     if (index >= NUM_MPP_DST_BUFS(mLogicalType)) {
928         return -EINVAL;
929     }
930 
931     exynos_mpp_img_info freeDstBuf = mDstImgs[index];
932     MPP_LOGD(eDebugMPP|eDebugBuf, "mDstImg[%d] is reallocated", index);
933     dumpExynosMPPImgInfo(eDebugMPP, mDstImgs[index]);
934 
935     uint64_t allocUsage = getBufferUsage(usage);
936     if (!needCompressDstBuf()) {
937         allocUsage |= VendorGraphicBufferUsage::NO_AFBC;
938     }
939     buffer_handle_t dstBuffer;
940 
941     MPP_LOGD(eDebugMPP|eDebugBuf, "\tw: %d, h: %d, format: 0x%8x, previousBuffer: %p, allocUsage: 0x%" PRIx64 ", usage: 0x%" PRIx64 "",
942             w, h, format, freeDstBuf.bufferHandle, allocUsage, usage);
943 
944     status_t error = NO_ERROR;
945 
946     {
947         ATRACE_CALL();
948 
949         VendorGraphicBufferAllocator& gAllocator(VendorGraphicBufferAllocator::get());
950         error = gAllocator.allocate(w, h, format, 1, allocUsage, &dstBuffer, &dstStride, "HWC");
951     }
952 
953     if ((error != NO_ERROR) || (dstBuffer == NULL)) {
954         MPP_LOGE("failed to allocate destination buffer(%dx%d): %d", w, h, error);
955         return -EINVAL;
956     }
957 
958     memset(&mDstImgs[index], 0, sizeof(mDstImgs[index]));
959 
960     mDstImgs[index].acrylicAcquireFenceFd = -1;
961     mDstImgs[index].acrylicReleaseFenceFd = -1;
962     mDstImgs[index].bufferHandle = dstBuffer;
963     mDstImgs[index].bufferType = getBufferType(usage);
964     mDstImgs[index].format = format;
965 
966     MPP_LOGD(eDebugMPP|eDebugBuf, "free outbuf[%d] %p", index, freeDstBuf.bufferHandle);
967     if (freeDstBuf.bufferHandle != NULL)
968         freeOutBuf(freeDstBuf);
969     else {
970         if (mAssignedDisplay != NULL) {
971             freeDstBuf.acrylicAcquireFenceFd = fence_close(freeDstBuf.acrylicAcquireFenceFd,
972                     mAssignedDisplay, FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_G2D);
973             freeDstBuf.acrylicReleaseFenceFd = fence_close(freeDstBuf.acrylicReleaseFenceFd,
974                     mAssignedDisplay, FENCE_TYPE_SRC_RELEASE, FENCE_IP_G2D);
975         }
976     }
977 
978     MPP_LOGD(eDebugMPP|eDebugBuf, "dstBuffer(%p)-----------", dstBuffer);
979 
980     return NO_ERROR;
981 }
982 
983 /**
984  * @param outbuf
985  * @return int32_t
986  */
setOutBuf(buffer_handle_t outbuf,int32_t fence)987 int32_t ExynosMPP::setOutBuf(buffer_handle_t outbuf, int32_t fence) {
988     mDstImgs[mCurrentDstBuf].bufferHandle = NULL;
989     if (outbuf != NULL) {
990         mDstImgs[mCurrentDstBuf].bufferHandle = outbuf;
991         mDstImgs[mCurrentDstBuf].format =
992             VendorGraphicBufferMeta::get_format(mDstImgs[mCurrentDstBuf].bufferHandle);
993     }
994     setDstAcquireFence(fence);
995     return NO_ERROR;
996 }
997 
998 /**
999  * @param dst
1000  * @return int32_t
1001  */
freeOutBuf(struct exynos_mpp_img_info dst)1002 int32_t ExynosMPP::freeOutBuf(struct exynos_mpp_img_info dst) {
1003     mResourceManageThread->addFreedBuffer(dst);
1004     dst.bufferHandle = NULL;
1005     return NO_ERROR;
1006 }
1007 
getBufferType(uint64_t usage)1008 uint32_t ExynosMPP::getBufferType(uint64_t usage)
1009 {
1010     if (getDrmMode(usage) == SECURE_DRM)
1011         return MPP_BUFFER_SECURE_DRM;
1012     else if (getDrmMode(usage) == NORMAL_DRM)
1013         return MPP_BUFFER_NORMAL_DRM;
1014     else {
1015         if (exynosHWCControl.dumpMidBuf)
1016             return MPP_BUFFER_DUMP;
1017         else
1018             return MPP_BUFFER_NORMAL;
1019     }
1020 }
1021 
getBufferType(const buffer_handle_t handle)1022 uint32_t ExynosMPP::getBufferType(const buffer_handle_t handle)
1023 {
1024     uint64_t usage = VendorGraphicBufferMeta::get_usage(handle);
1025 
1026     return getBufferType(usage);
1027 }
1028 
getBufferUsage(uint64_t usage)1029 uint64_t ExynosMPP::getBufferUsage(uint64_t usage)
1030 {
1031     uint64_t allocUsage = 0;
1032     if (getBufferType(usage) == MPP_BUFFER_DUMP) {
1033         allocUsage = BufferUsage::CPU_READ_OFTEN |
1034             BufferUsage::CPU_WRITE_OFTEN;
1035     } else {
1036         allocUsage = BufferUsage::CPU_READ_NEVER |
1037             BufferUsage::CPU_WRITE_NEVER |
1038             VendorGraphicBufferUsage::NOZEROED |
1039             BufferUsage::COMPOSER_OVERLAY;
1040     }
1041 
1042     if (getDrmMode(usage) == SECURE_DRM) {
1043         allocUsage |= BufferUsage::PROTECTED;
1044         allocUsage &= ~VendorGraphicBufferUsage::PRIVATE_NONSECURE;
1045     } else if (getDrmMode(usage) == NORMAL_DRM) {
1046         allocUsage |= BufferUsage::PROTECTED;
1047         allocUsage |= VendorGraphicBufferUsage::PRIVATE_NONSECURE;
1048     }
1049 
1050     return allocUsage;
1051 }
1052 
needCompressDstBuf() const1053 bool ExynosMPP::needCompressDstBuf() const {
1054     return (mMaxSrcLayerNum > 1) && mNeedCompressedTarget;
1055 }
1056 
needDstBufRealloc(struct exynos_image & dst,uint32_t index)1057 bool ExynosMPP::needDstBufRealloc(struct exynos_image &dst, uint32_t index)
1058 {
1059     MPP_LOGD(eDebugMPP|eDebugBuf, "index: %d++++++++", index);
1060 
1061     if (index >= NUM_MPP_DST_BUFS(mLogicalType)) {
1062         MPP_LOGE("%s:: index(%d) is not valid", __func__, index);
1063         return false;
1064     }
1065     buffer_handle_t dst_handle = NULL;
1066     if (mDstImgs[index].bufferHandle != NULL)
1067         dst_handle = mDstImgs[index].bufferHandle;
1068 
1069     if (dst_handle == NULL) {
1070         MPP_LOGD(eDebugMPP|eDebugBuf, "\tDstImag[%d]  handle is NULL", index);
1071         return true;
1072     }
1073 
1074     int32_t assignedDisplay = -1;
1075     if (mAssignedDisplay != NULL) {
1076         assignedDisplay = mAssignedDisplay->mType;
1077     } else {
1078         MPP_LOGE("%s:: mpp is not assigned", __func__);
1079         return false;
1080     }
1081 
1082     VendorGraphicBufferMeta gmeta(dst_handle);
1083 
1084     MPP_LOGD(eDebugMPP | eDebugBuf, "\tdst_handle(%p) afbc (%u) sbwc (%u) lossy (%u)", dst_handle,
1085              isAFBCCompressed(dst_handle), isFormatSBWC(gmeta.format), isFormatLossy(gmeta.format));
1086     MPP_LOGD(eDebugMPP | eDebugBuf,
1087              "\tAssignedDisplay[%d, %d] format[0x%8x, 0x%8x], bufferType[%d, %d], usageFlags: "
1088              "0x%" PRIx64 ", need afbc %u sbwc %u lossy %u",
1089              mPrevAssignedDisplayType, assignedDisplay, gmeta.format, dst.format,
1090              mDstImgs[index].bufferType, getBufferType(dst.usageFlags), dst.usageFlags,
1091              dst.compressed, isFormatSBWC(dst.format), isFormatLossy(dst.format));
1092 
1093     bool realloc = (mPrevAssignedDisplayType != assignedDisplay) ||
1094             (formatToBpp(gmeta.format) < formatToBpp(dst.format)) ||
1095             ((gmeta.stride * gmeta.vstride) < (int)(dst.fullWidth * dst.fullHeight)) ||
1096             (mDstImgs[index].bufferType != getBufferType(dst.usageFlags)) ||
1097             (isAFBCCompressed(dst_handle) != dst.compressed) ||
1098             (isFormatSBWC(gmeta.format) != isFormatSBWC(dst.format)) ||
1099             (isFormatLossy(gmeta.format) != isFormatLossy(dst.format));
1100 
1101     MPP_LOGD(eDebugMPP|eDebugBuf, "realloc: %d--------", realloc);
1102     return realloc;
1103 }
1104 
canUsePrevFrame()1105 bool ExynosMPP::canUsePrevFrame()
1106 {
1107     if ((mAssignedDisplay && !mAssignedDisplay->mDisplayControl.skipM2mProcessing) ||
1108         !exynosHWCControl.skipM2mProcessing)
1109         return false;
1110 
1111     /* virtual display always require composition */
1112     if (mAllocOutBufFlag == false)
1113         return false;
1114 
1115     if (mPrevFrameInfo.srcNum != mAssignedSources.size())
1116         return false;
1117 
1118     for (uint32_t i = 0; i < mPrevFrameInfo.srcNum; i++) {
1119         if ((mPrevFrameInfo.srcInfo[i].bufferHandle != mAssignedSources[i]->mSrcImg.bufferHandle) ||
1120             (mPrevFrameInfo.srcInfo[i].x !=  mAssignedSources[i]->mSrcImg.x) ||
1121             (mPrevFrameInfo.srcInfo[i].y !=  mAssignedSources[i]->mSrcImg.y) ||
1122             (mPrevFrameInfo.srcInfo[i].w !=  mAssignedSources[i]->mSrcImg.w) ||
1123             (mPrevFrameInfo.srcInfo[i].h !=  mAssignedSources[i]->mSrcImg.h) ||
1124             (mPrevFrameInfo.srcInfo[i].format !=  mAssignedSources[i]->mSrcImg.format) ||
1125             (mPrevFrameInfo.srcInfo[i].usageFlags !=  mAssignedSources[i]->mSrcImg.usageFlags) ||
1126             (mPrevFrameInfo.srcInfo[i].dataSpace !=  mAssignedSources[i]->mSrcImg.dataSpace) ||
1127             (mPrevFrameInfo.srcInfo[i].blending !=  mAssignedSources[i]->mSrcImg.blending) ||
1128             (mPrevFrameInfo.srcInfo[i].transform !=  mAssignedSources[i]->mSrcImg.transform) ||
1129             (mPrevFrameInfo.srcInfo[i].compressed !=  mAssignedSources[i]->mSrcImg.compressed) ||
1130             (mPrevFrameInfo.srcInfo[i].planeAlpha !=  mAssignedSources[i]->mSrcImg.planeAlpha) ||
1131             (mPrevFrameInfo.dstInfo[i].x != mAssignedSources[i]->mMidImg.x) ||
1132             (mPrevFrameInfo.dstInfo[i].y != mAssignedSources[i]->mMidImg.y) ||
1133             (mPrevFrameInfo.dstInfo[i].w != mAssignedSources[i]->mMidImg.w) ||
1134             (mPrevFrameInfo.dstInfo[i].h != mAssignedSources[i]->mMidImg.h) ||
1135             (mPrevFrameInfo.dstInfo[i].format != mAssignedSources[i]->mMidImg.format))
1136             return false;
1137     }
1138 
1139    int32_t prevDstIndex  = (mCurrentDstBuf + NUM_MPP_DST_BUFS(mLogicalType) - 1)% NUM_MPP_DST_BUFS(mLogicalType);
1140    if (mDstImgs[prevDstIndex].bufferHandle == NULL)
1141        return false;
1142 
1143     return true;
1144 }
1145 
setupLayer(exynos_mpp_img_info * srcImgInfo,struct exynos_image & src,struct exynos_image & dst)1146 int32_t ExynosMPP::setupLayer(exynos_mpp_img_info *srcImgInfo, struct exynos_image &src, struct exynos_image &dst)
1147 {
1148     int ret = NO_ERROR;
1149 
1150     if (srcImgInfo->mppLayer == NULL) {
1151         if ((srcImgInfo->mppLayer = mAcrylicHandle->createLayer()) == NULL)
1152         {
1153             MPP_LOGE("%s:: Fail to create layer", __func__);
1154             return -EINVAL;
1155         }
1156     }
1157 
1158     if (src.bufferHandle == NULL) {
1159         MPP_LOGE("%s:: Invalid source handle", __func__);
1160         return -EINVAL;
1161     }
1162 
1163     buffer_handle_t srcHandle = NULL;
1164     if (src.bufferHandle != NULL)
1165         srcHandle = src.bufferHandle;
1166 
1167     VendorGraphicBufferMeta gmeta(srcHandle);
1168     int bufFds[MAX_HW2D_PLANES];
1169     size_t bufLength[MAX_HW2D_PLANES];
1170     uint32_t attribute = 0;
1171     uint32_t bufferNum = getBufferNumOfFormat(gmeta.format, getCompressionType(srcHandle));
1172     android_dataspace_t dataspace = src.dataSpace;
1173     if (dataspace == HAL_DATASPACE_UNKNOWN)
1174     {
1175         if (isFormatRgb(gmeta.format))
1176             dataspace = HAL_DATASPACE_V0_SRGB;
1177         else
1178             dataspace = HAL_DATASPACE_V0_BT601_625;
1179     }
1180 
1181     if (bufferNum == 0)
1182     {
1183         MPP_LOGE("%s:: Fail to get bufferNum(%d), format(0x%8x, afbc %d)", __func__, bufferNum,
1184                  gmeta.format, isAFBCCompressed(srcHandle));
1185         return -EINVAL;
1186     }
1187     bufFds[0] = gmeta.fd;
1188     bufFds[1] = gmeta.fd1;
1189     bufFds[2] = gmeta.fd2;
1190     if (getBufLength(srcHandle, MAX_HW2D_PLANES, bufLength, gmeta.format, src.fullWidth, src.fullHeight) != NO_ERROR) {
1191         MPP_LOGE("%s:: invalid bufferLength(%zu, %zu, %zu), format(0x%8x)", __func__,
1192                 bufLength[0], bufLength[1], bufLength[2], gmeta.format);
1193         return -EINVAL;
1194     }
1195 
1196     /* HDR process */
1197     if (hasHdrInfo(src)) {
1198         unsigned int max = (src.metaParcel.sHdrStaticInfo.sType1.mMaxDisplayLuminance/10000);
1199         unsigned int min = src.metaParcel.sHdrStaticInfo.sType1.mMinDisplayLuminance;
1200 
1201         srcImgInfo->mppLayer->setMasterDisplayLuminance(min,max);
1202         MPP_LOGD(eDebugMPP, "HWC2: G2D luminance min %d, max %d", min, max);
1203         MPP_LOGD(eDebugMPP|eDebugFence, "G2D getting HDR source!");
1204     }
1205 
1206     /* Transfer MetaData */
1207     if (src.hasMetaParcel) {
1208         srcImgInfo->mppLayer->setLayerData(&src.metaParcel, sizeof(src.metaParcel));
1209     }
1210 
1211     srcImgInfo->bufferType = getBufferType(srcHandle);
1212     if (srcImgInfo->bufferType == MPP_BUFFER_SECURE_DRM)
1213         attribute |= AcrylicCanvas::ATTR_PROTECTED;
1214     if (src.compressed)
1215         attribute |= AcrylicCanvas::ATTR_COMPRESSED;
1216 
1217     srcImgInfo->bufferHandle = srcHandle;
1218     srcImgInfo->acrylicAcquireFenceFd =
1219         hwcCheckFenceDebug(mAssignedDisplay, FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_G2D, src.acquireFenceFd);
1220 
1221     MPP_LOGD(eDebugMPP|eDebugFence, "source configuration:");
1222     MPP_LOGD(eDebugMPP, "\tImageDimension[%d, %d], ImageType[0x%8x, 0x%8x]",
1223             src.fullWidth, src.fullHeight,
1224             gmeta.format, dataspace);
1225     MPP_LOGD(eDebugMPP|eDebugFence, "\tImageBuffer handle: %p, fds[%d, %d, %d], bufLength[%zu, %zu, %zu], bufferNum: %d, acquireFence: %d, attribute: %d",
1226             srcHandle, bufFds[0], bufFds[1], bufFds[2], bufLength[0], bufLength[1], bufLength[2],
1227             bufferNum, srcImgInfo->acrylicAcquireFenceFd, attribute);
1228     MPP_LOGD(eDebugMPP, "\tsrc_rect[%d, %d, %d, %d], dst_rect[%d, %d, %d, %d], transform(0x%4x)",
1229             (int)src.x, (int)src.y, (int)(src.x + src.w), (int)(src.y + src.h),
1230             (int)dst.x, (int)dst.y, (int)(dst.x + dst.w), (int)(dst.y + dst.h), src.transform);
1231 
1232     srcImgInfo->mppLayer->setImageDimension(src.fullWidth, src.fullHeight);
1233 
1234     if (gmeta.format == HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_PRIV) {
1235         srcImgInfo->mppLayer->setImageType(HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M, dataspace);
1236     } else {
1237         srcImgInfo->mppLayer->setImageType(gmeta.format, dataspace);
1238     }
1239 
1240     if (mPhysicalType == MPP_G2D) {
1241         setFenceName(srcImgInfo->acrylicAcquireFenceFd, FENCE_G2D_SRC_LAYER);
1242         setFenceInfo(srcImgInfo->acrylicAcquireFenceFd, mAssignedDisplay,
1243                 FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_G2D, FENCE_TO);
1244     } else if (mPhysicalType == MPP_MSC) {
1245         setFenceName(srcImgInfo->acrylicAcquireFenceFd, FENCE_MSC_SRC_LAYER);
1246         setFenceInfo(srcImgInfo->acrylicAcquireFenceFd, mAssignedDisplay,
1247                 FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_MSC, FENCE_TO);
1248     } else {
1249         MPP_LOGE("%s:: invalid mPhysicalType(%d)", __func__, mPhysicalType);
1250     }
1251 
1252     srcImgInfo->mppLayer->setImageBuffer(bufFds, bufLength, bufferNum,
1253             srcImgInfo->acrylicAcquireFenceFd, attribute);
1254 
1255     if (mMaxSrcLayerNum > 1) {
1256         srcImgInfo->mppLayer->setCompositMode(src.blending, (uint8_t)(255 * src.planeAlpha), src.zOrder);
1257     } else {
1258         srcImgInfo->mppLayer->setCompositMode(src.blending, 255, src.zOrder);
1259     }
1260 
1261     hwc_rect_t src_rect = {(int)src.x, (int)src.y, (int)(src.x + src.w), (int)(src.y + src.h)};
1262     hwc_rect_t dst_rect = {(int)dst.x, (int)dst.y, (int)(dst.x + dst.w), (int)(dst.y + dst.h)};
1263 
1264     if ((mAssignedDisplay != NULL) &&
1265         ((mAssignedDisplay->mType == HWC_DISPLAY_VIRTUAL) ||
1266          (mAssignedDisplay->mType == HWC_DISPLAY_EXTERNAL)))
1267         srcImgInfo->mppLayer->setCompositArea(src_rect, dst_rect, src.transform, AcrylicLayer::ATTR_NORESAMPLING);
1268     else {
1269         if(isFormatYUV(src.format))
1270             srcImgInfo->mppLayer->setCompositArea(src_rect, dst_rect, src.transform, AcrylicLayer::ATTR_NORESAMPLING);
1271         else
1272             srcImgInfo->mppLayer->setCompositArea(src_rect, dst_rect, src.transform);
1273     }
1274 
1275     srcImgInfo->acrylicAcquireFenceFd = -1;
1276     srcImgInfo->format = gmeta.format;
1277 
1278     if (gmeta.format == HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_PRIV) {
1279         srcImgInfo->format = HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M;
1280     }
1281 
1282     return ret;
1283 }
1284 
getDstMetaInfo(android_dataspace_t dstDataspace)1285 dstMetaInfo_t ExynosMPP::getDstMetaInfo(android_dataspace_t dstDataspace)
1286 {
1287     dstMetaInfo_t metaInfo;
1288 
1289     if ((mAssignedSources.size() <= 1) &&
1290             (mAssignedSources[0]->mSrcImg.dataSpace == dstDataspace)) {
1291         metaInfo.minLuminance =
1292             (uint16_t)mAssignedSources[0]->mSrcImg.metaParcel.sHdrStaticInfo.sType1.mMinDisplayLuminance;
1293         metaInfo.maxLuminance =
1294             (uint16_t)(mAssignedSources[0]->mSrcImg.metaParcel.sHdrStaticInfo.sType1.mMaxDisplayLuminance/10000);
1295     } else {
1296         // minLuminance: 0.0001nit unit, maxLuminance: 1nit unit
1297         metaInfo.minLuminance = (uint16_t)(mAssignedDisplay->mMinLuminance * 10000);
1298         metaInfo.maxLuminance = (uint16_t)mAssignedDisplay->mMaxLuminance;
1299     }
1300 
1301     return metaInfo;
1302 }
1303 
setupDst(exynos_mpp_img_info * dstImgInfo)1304 int32_t ExynosMPP::setupDst(exynos_mpp_img_info *dstImgInfo)
1305 {
1306     int ret = NO_ERROR;
1307     bool isComposition = (mMaxSrcLayerNum > 1);
1308     buffer_handle_t dstHandle = dstImgInfo->bufferHandle;
1309     int bufFds[MAX_HW2D_PLANES];
1310     size_t bufLength[MAX_HW2D_PLANES];
1311     uint32_t attribute = 0;
1312     uint32_t bufferNum = getBufferNumOfFormat(dstImgInfo->format, getCompressionType(dstHandle));
1313     if (bufferNum == 0)
1314     {
1315         MPP_LOGE("%s:: Fail to get bufferNum(%d), format(0x%8x, afbc %d)", __func__, bufferNum,
1316                  dstImgInfo->format, isAFBCCompressed(dstHandle));
1317         return -EINVAL;
1318     }
1319 
1320     android_dataspace_t dataspace = HAL_DATASPACE_UNKNOWN;
1321     VendorGraphicBufferMeta gmeta(dstHandle);
1322 
1323     if (isComposition) {
1324         if (isFormatRgb(dstImgInfo->format)) {
1325             if ((mAssignedDisplay != NULL) &&
1326                 (mAssignedDisplay->mColorMode != HAL_COLOR_MODE_NATIVE))
1327                 dataspace = colorModeToDataspace(mAssignedDisplay->mColorMode);
1328         } else {
1329             dataspace =
1330                 (android_dataspace)(HAL_DATASPACE_STANDARD_BT709 | HAL_DATASPACE_TRANSFER_GAMMA2_2 | HAL_DATASPACE_RANGE_LIMITED);
1331         }
1332     } else {
1333         dataspace = mAssignedSources[0]->mMidImg.dataSpace;
1334     }
1335 
1336     if (dataspace == HAL_DATASPACE_UNKNOWN)
1337     {
1338         if (isFormatRgb(dstImgInfo->format))
1339             dataspace = HAL_DATASPACE_V0_SRGB;
1340         else
1341             dataspace = HAL_DATASPACE_V0_BT601_625;
1342     }
1343 
1344     bufFds[0] = gmeta.fd;
1345     bufFds[1] = gmeta.fd1;
1346     bufFds[2] = gmeta.fd2;
1347     if (getBufLength(dstHandle, MAX_HW2D_PLANES, bufLength, dstImgInfo->format,
1348                 gmeta.stride, gmeta.vstride) != NO_ERROR) {
1349         MPP_LOGE("%s:: invalid bufferLength(%zu, %zu, %zu), format(0x%8x)", __func__,
1350                 bufLength[0], bufLength[1], bufLength[2], dstImgInfo->format);
1351         return -EINVAL;
1352     }
1353 
1354     dstImgInfo->bufferType = getBufferType(dstHandle);
1355     if (dstImgInfo->bufferType == MPP_BUFFER_SECURE_DRM)
1356         attribute |= AcrylicCanvas::ATTR_PROTECTED;
1357 
1358     if (mAssignedDisplay != NULL)
1359         mAcrylicHandle->setCanvasDimension(pixel_align(mAssignedDisplay->mXres, G2D_JUSTIFIED_DST_ALIGN),
1360                 pixel_align(mAssignedDisplay->mYres, G2D_JUSTIFIED_DST_ALIGN));
1361 
1362     /* setup dst */
1363     if (needCompressDstBuf()) {
1364         attribute |= AcrylicCanvas::ATTR_COMPRESSED;
1365     }
1366 
1367     if (mPhysicalType == MPP_G2D) {
1368         setFenceName(dstImgInfo->acrylicAcquireFenceFd, FENCE_G2D_DST_DPP);
1369         /* Might be closed next frame */
1370         setFenceInfo(dstImgInfo->acrylicAcquireFenceFd, mAssignedDisplay,
1371                 FENCE_TYPE_DST_ACQUIRE, FENCE_IP_G2D, FENCE_TO);
1372     } else if (mPhysicalType == MPP_MSC) {
1373         setFenceName(dstImgInfo->acrylicAcquireFenceFd, FENCE_MSC_DST_DPP);
1374         /* Might be closed next frame */
1375         setFenceInfo(dstImgInfo->acrylicAcquireFenceFd, mAssignedDisplay,
1376                 FENCE_TYPE_DST_ACQUIRE, FENCE_IP_MSC, FENCE_TO);
1377     } else {
1378         MPP_LOGE("%s:: invalid mPhysicalType(%d)", __func__, mPhysicalType);
1379     }
1380 
1381     mAcrylicHandle->setCanvasImageType(dstImgInfo->format, dataspace);
1382 
1383     if ((mLogicalType == MPP_LOGICAL_G2D_COMBO) &&
1384             (mAssignedDisplay != NULL) &&
1385             (mAssignedDisplay->mType == HWC_DISPLAY_VIRTUAL) &&
1386             (((ExynosVirtualDisplay *)mAssignedDisplay)->mIsWFDState == (int)LLWFD)) {
1387         mAcrylicHandle->setCanvasImageType(HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN, dataspace);
1388         dstImgInfo->acrylicAcquireFenceFd = fence_close(dstImgInfo->acrylicAcquireFenceFd,
1389                 mAssignedDisplay, FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_G2D);
1390         mAcrylicHandle->setCanvasBuffer(bufFds, bufLength, bufferNum,
1391                 dstImgInfo->acrylicAcquireFenceFd, attribute);
1392         mAcrylicHandle->setCanvasOTF(attribute);
1393     }
1394     else {
1395         dstImgInfo->acrylicAcquireFenceFd =
1396             hwcCheckFenceDebug(mAssignedDisplay, FENCE_TYPE_DST_ACQUIRE, FENCE_IP_G2D, dstImgInfo->acrylicAcquireFenceFd);
1397         mAcrylicHandle->setCanvasBuffer(bufFds, bufLength, bufferNum,
1398                 dstImgInfo->acrylicAcquireFenceFd, attribute);
1399     }
1400 
1401     dstMetaInfo_t metaInfo = getDstMetaInfo(dataspace);
1402     if ((mAssignedDisplay != NULL) &&
1403         (mAssignedDisplay->mType != HWC_DISPLAY_VIRTUAL)) {
1404         mAcrylicHandle->setTargetDisplayLuminance(metaInfo.minLuminance, metaInfo.maxLuminance);
1405     }
1406 
1407     MPP_LOGD(eDebugMPP|eDebugFence, "destination configuration:");
1408     MPP_LOGD(eDebugMPP, "\tImageDimension[%d, %d], ImageType[0x%8x, %d], target luminance[%d, %d]",
1409             gmeta.stride, gmeta.vstride,
1410             dstImgInfo->format, dataspace, metaInfo.minLuminance, metaInfo.maxLuminance);
1411     MPP_LOGD(eDebugMPP|eDebugFence, "\tImageBuffer handle: %p, fds[%d, %d, %d], bufLength[%zu, %zu, %zu], bufferNum: %d, acquireFence: %d, attribute: %d",
1412             dstHandle, bufFds[0], bufFds[1], bufFds[2], bufLength[0], bufLength[1], bufLength[2],
1413             bufferNum, dstImgInfo->acrylicAcquireFenceFd, attribute);
1414 
1415 
1416     dstImgInfo->acrylicAcquireFenceFd = -1;
1417     dstImgInfo->dataspace = dataspace;
1418 
1419     return ret;
1420 }
1421 
doPostProcessingInternal()1422 int32_t ExynosMPP::doPostProcessingInternal()
1423 {
1424     ATRACE_CALL();
1425     int ret = NO_ERROR;
1426     size_t sourceNum = mAssignedSources.size();
1427 
1428     if (mAcrylicHandle == NULL) {
1429         MPP_LOGE("%s:: mAcrylicHandle is NULL", __func__);
1430         return -EINVAL;
1431     }
1432 
1433     /* setup source layers */
1434     for(size_t i = 0; i < sourceNum; i++) {
1435         MPP_LOGD(eDebugMPP|eDebugFence, "Setup [%zu] source: %p", i, mAssignedSources[i]);
1436         if ((ret = setupLayer(&mSrcImgs[i], mAssignedSources[i]->mSrcImg, mAssignedSources[i]->mMidImg)) != NO_ERROR) {
1437             MPP_LOGE("%s:: fail to setupLayer[%zu], ret %d",
1438                     __func__, i, ret);
1439             return ret;
1440         }
1441     }
1442 
1443     if ((ret = setColorConversionInfo()) != NO_ERROR) {
1444             MPP_LOGE("%s:: fail to setColorConversionInfo ret %d",
1445                     __func__, ret);
1446             return ret;
1447     }
1448 
1449     if (mPrevFrameInfo.srcNum > sourceNum) {
1450         MPP_LOGD(eDebugMPP, "prev sourceNum(%d), current sourceNum(%zu)",
1451                 mPrevFrameInfo.srcNum, sourceNum);
1452         for (size_t i = sourceNum; i < mPrevFrameInfo.srcNum; i++)
1453         {
1454             MPP_LOGD(eDebugMPP, "Remove mSrcImgs[%zu], %p", i, mSrcImgs[i].mppLayer);
1455             if (mSrcImgs[i].mppLayer != NULL) {
1456                 delete mSrcImgs[i].mppLayer;
1457                 mSrcImgs[i].mppLayer = NULL;
1458             }
1459         }
1460     }
1461 
1462     if (mAcrylicHandle->layerCount() != mAssignedSources.size()) {
1463         MPP_LOGE("Different layer number, acrylic layers(%d), assigned size(%zu)",
1464                 mAcrylicHandle->layerCount(), mAssignedSources.size());
1465         return -EINVAL;
1466     }
1467     MPP_LOGD(eDebugFence, "setupDst ++ mDstImgs[%d] acrylicAcquireFenceFd(%d)",
1468             mCurrentDstBuf, mDstImgs[mCurrentDstBuf].acrylicAcquireFenceFd);
1469 
1470     setupDst(&mDstImgs[mCurrentDstBuf]);
1471 
1472     MPP_LOGD(eDebugFence, "setupDst -- mDstImgs[%d] acrylicAcquireFenceFd(%d) closed",
1473             mCurrentDstBuf, mDstImgs[mCurrentDstBuf].acrylicAcquireFenceFd);
1474 
1475 
1476     int usingFenceCnt = 1;
1477     bool acrylicReturn = true;
1478 
1479 #ifndef DISABLE_FENCE
1480     if (mUseM2MSrcFence)
1481         usingFenceCnt = sourceNum + 1; // Get and Use src + dst fence
1482     else
1483         usingFenceCnt = 1;             // Get and Use only dst fence
1484     int *releaseFences = new int[usingFenceCnt];
1485     int dstBufIdx = usingFenceCnt - 1;
1486 #else
1487     usingFenceCnt = 0;                 // Get and Use no fences
1488     int dstBufIdx = 0;
1489     int *releaseFences = NULL;
1490 #endif
1491 
1492     acrylicReturn = mAcrylicHandle->execute(releaseFences, usingFenceCnt);
1493 
1494     if (acrylicReturn == false) {
1495         MPP_LOGE("%s:: fail to excute compositor", __func__);
1496         for(size_t i = 0; i < sourceNum; i++) {
1497             mSrcImgs[i].acrylicReleaseFenceFd = -1;
1498             MPP_LOGE("src[%zu]: ImageDimension[%d, %d], src_rect[%d, %d, %d, %d], dst_rect[%d, %d, %d, %d], transform(0x%4x)",
1499                     i,
1500                     mAssignedSources[i]->mSrcImg.fullWidth, mAssignedSources[i]->mSrcImg.fullHeight,
1501                     mAssignedSources[i]->mSrcImg.x, mAssignedSources[i]->mSrcImg.y,
1502                     mAssignedSources[i]->mSrcImg.x + mAssignedSources[i]->mSrcImg.w,
1503                     mAssignedSources[i]->mSrcImg.y + mAssignedSources[i]->mSrcImg.h,
1504                     mAssignedSources[i]->mMidImg.x, mAssignedSources[i]->mMidImg.y,
1505                     mAssignedSources[i]->mMidImg.x + mAssignedSources[i]->mMidImg.w,
1506                     mAssignedSources[i]->mMidImg.y + mAssignedSources[i]->mMidImg.h,
1507                     mAssignedSources[i]->mSrcImg.transform);
1508         }
1509         mDstImgs[mCurrentDstBuf].acrylicReleaseFenceFd = -1;
1510         ret = -EPERM;
1511     } else {
1512 
1513         // set fence informations from acryl
1514         if (mPhysicalType == MPP_G2D) {
1515             setFenceInfo(releaseFences[dstBufIdx], mAssignedDisplay,
1516                     FENCE_TYPE_DST_ACQUIRE, FENCE_IP_G2D, FENCE_FROM);
1517             if (usingFenceCnt > 1) {
1518                 for(size_t i = 0; i < sourceNum; i++) {
1519                     // TODO DPU release fence is tranferred to m2mMPP's source layer fence
1520                     setFenceInfo(releaseFences[i], mAssignedDisplay,
1521                             FENCE_TYPE_SRC_RELEASE, FENCE_IP_G2D, FENCE_FROM);
1522                 }
1523             }
1524         } else if (mPhysicalType == MPP_MSC) {
1525             setFenceInfo(releaseFences[dstBufIdx], mAssignedDisplay,
1526                     FENCE_TYPE_DST_ACQUIRE, FENCE_IP_MSC, FENCE_FROM);
1527             if (usingFenceCnt > 1) {
1528                 for(size_t i = 0; i < sourceNum; i++) {
1529                     // TODO DPU release fence is tranferred to m2mMPP's source layer fence
1530                     setFenceInfo(releaseFences[i], mAssignedDisplay,
1531                             FENCE_TYPE_SRC_RELEASE, FENCE_IP_MSC, FENCE_FROM);
1532                 }
1533             }
1534         } else {
1535             MPP_LOGE("%s:: invalid mPhysicalType(%d)", __func__, mPhysicalType);
1536         }
1537 
1538         if ((mLogicalType == MPP_LOGICAL_G2D_COMBO) &&
1539                 (mAssignedDisplay != NULL) &&
1540                 (mAssignedDisplay->mType == HWC_DISPLAY_VIRTUAL)) {
1541             if (((ExynosVirtualDisplay *)mAssignedDisplay)->mIsWFDState == (int)LLWFD) {
1542                 if (usingFenceCnt != 0) // Use no fences
1543                     releaseFences[dstBufIdx] = fence_close(releaseFences[dstBufIdx],
1544                             mAssignedDisplay, FENCE_TYPE_SRC_RELEASE, FENCE_IP_G2D); // Close dst buf's fence
1545             }
1546             if (mUseM2MSrcFence) {
1547                 if (((ExynosVirtualDisplay *)mAssignedDisplay)->mIsWFDState != (int)GOOGLEWFD) {
1548                     for (size_t i = 0; i < sourceNum; i++)
1549                         releaseFences[i] = fence_close(releaseFences[i],
1550                                 mAssignedDisplay, FENCE_TYPE_SRC_RELEASE, FENCE_IP_G2D);
1551                 }
1552             }
1553         }
1554 
1555         if (usingFenceCnt == 0) { // Use no fences
1556             for(size_t i = 0; i < sourceNum; i++) {
1557                 mSrcImgs[i].acrylicReleaseFenceFd = -1;
1558             }
1559             mDstImgs[mCurrentDstBuf].acrylicReleaseFenceFd = -1;
1560         } else {
1561             for(size_t i = 0; i < sourceNum; i++) {
1562                 if (mUseM2MSrcFence)
1563                     mSrcImgs[i].acrylicReleaseFenceFd =
1564                         hwcCheckFenceDebug(mAssignedDisplay, FENCE_TYPE_SRC_RELEASE, FENCE_IP_G2D, releaseFences[i]);
1565                 else
1566                     mSrcImgs[i].acrylicReleaseFenceFd = -1;
1567                 MPP_LOGD(eDebugFence, "mSrcImgs[%zu] acrylicReleaseFenceFd: %d",
1568                         i, mSrcImgs[i].acrylicReleaseFenceFd);
1569             }
1570 
1571             if (mDstImgs[mCurrentDstBuf].acrylicReleaseFenceFd >= 0) {
1572                 MPP_LOGE("mDstImgs[%d].acrylicReleaseFenceFd(%d) is not initialized",
1573                         mCurrentDstBuf,
1574                         mDstImgs[mCurrentDstBuf].acrylicReleaseFenceFd);
1575             }
1576 
1577             if (mPhysicalType == MPP_G2D)
1578                 mDstImgs[mCurrentDstBuf].acrylicReleaseFenceFd =
1579                     hwcCheckFenceDebug(mAssignedDisplay, FENCE_TYPE_DST_RELEASE, FENCE_IP_G2D, releaseFences[dstBufIdx]);
1580             else if (mPhysicalType == MPP_MSC)
1581                 mDstImgs[mCurrentDstBuf].acrylicReleaseFenceFd =
1582                     hwcCheckFenceDebug(mAssignedDisplay, FENCE_TYPE_DST_RELEASE, FENCE_IP_MSC, releaseFences[dstBufIdx]);
1583 
1584             MPP_LOGD(eDebugFence, "mDstImgs[%d] acrylicReleaseFenceFd: %d , releaseFences[%d]",
1585                     mCurrentDstBuf, mDstImgs[mCurrentDstBuf].acrylicReleaseFenceFd, dstBufIdx);
1586         }
1587 
1588         if (exynosHWCControl.dumpMidBuf) {
1589             ALOGI("dump image");
1590             exynosHWCControl.dumpMidBuf = false;
1591             if ((mDstImgs[mCurrentDstBuf].acrylicReleaseFenceFd > 0) &&
1592                 (sync_wait(mDstImgs[mCurrentDstBuf].acrylicReleaseFenceFd, 1000) < 0)) {
1593                 ALOGE("%s:: fence sync_wait error to dump image", __func__);
1594             } else {
1595                 buffer_handle_t dstHandle = mDstImgs[mCurrentDstBuf].bufferHandle;
1596                 VendorGraphicBufferMeta gmeta(dstHandle);
1597 
1598                 ALOGI("dump image fw: %d, fh:%d, size: %d", gmeta.stride, gmeta.vstride, gmeta.size);
1599                 FILE *fp;
1600                 fp = fopen(MPP_DUMP_PATH,"ab");
1601 
1602                 if (fp) {
1603                     void *temp = mmap(0, gmeta.size, PROT_READ|PROT_WRITE, MAP_SHARED, gmeta.fd, 0);
1604                     if (temp) {
1605                         ALOGI("write...%p", temp);
1606                         int write_size = fwrite(temp, gmeta.size, 1, fp);
1607                         if (write_size < 0) {
1608                             ALOGI("write error: %s", strerror(errno));
1609                         } else {
1610                             ALOGI("write size: %d", write_size);
1611                         }
1612                         munmap(temp, gmeta.size);
1613                     } else {
1614                         ALOGE("mmap is NULL %s", strerror(errno));
1615                     }
1616                     fclose(fp);
1617                 } else {
1618                     ALOGE("open fail %s", strerror(errno));
1619                 }
1620             }
1621         }
1622     }
1623 
1624 #ifndef DISABLE_FENCE
1625     delete [] releaseFences;
1626 #endif
1627 
1628     return ret;
1629 }
1630 
canSkipProcessing()1631 bool ExynosMPP::canSkipProcessing()
1632 {
1633     if ((mAssignedDisplay == NULL) || (mAssignedSources.size() == 0))
1634         return true;
1635     ExynosMPPSource *source = mAssignedSources[0];
1636     exynos_image dst = source->mMidImg;
1637     if ((mLogicalType == MPP_LOGICAL_G2D_RGB) ||
1638         (mLogicalType == MPP_LOGICAL_G2D_COMBO)) {
1639         dst = mAssignedDisplay->mExynosCompositionInfo.mDstImg;
1640     }
1641     return ((needDstBufRealloc(dst, mCurrentDstBuf) == false) & canUsePrevFrame());
1642 
1643 }
1644 
1645 /**
1646  * @param src
1647  * @param dst
1648  * @return int32_t releaseFenceFd of src buffer
1649  */
doPostProcessing(struct exynos_image & src,struct exynos_image & dst)1650 int32_t ExynosMPP::doPostProcessing(struct exynos_image &src, struct exynos_image &dst)
1651 {
1652     ATRACE_CALL();
1653     MPP_LOGD(eDebugMPP, "total assigned sources (%zu)++++++++", mAssignedSources.size());
1654 
1655     int ret = NO_ERROR;
1656     bool realloc = false;
1657     if (mAssignedSources.size() == 0) {
1658         MPP_LOGE("Assigned source size(%zu) is not valid",
1659                 mAssignedSources.size());
1660         ret = -EINVAL;
1661         goto save_frame_info;
1662     }
1663 
1664     // Check whether destination buffer allocation is required
1665     if (mAllocOutBufFlag) {
1666         if ((realloc = needDstBufRealloc(dst, mCurrentDstBuf)) == true) {
1667             //  allocate mDstImgs[mCurrentDstBuf]
1668             uint32_t bufAlign = getOutBufAlign();
1669             bool isComposition = (mMaxSrcLayerNum > 1);
1670             if (isComposition)
1671                 dst.format = DEFAULT_MPP_DST_FORMAT;
1672 
1673             uint32_t allocFormat = dst.format;
1674             if (mFreeOutBufFlag == false)
1675                 allocFormat = DEFAULT_MPP_DST_FORMAT;
1676 
1677             if ((allocFormat == HAL_PIXEL_FORMAT_RGBA_1010102) ||
1678                 (allocFormat == HAL_PIXEL_FORMAT_GOOGLE_NV12_SP_10B) ||
1679                 (allocFormat == HAL_PIXEL_FORMAT_YCBCR_P010))
1680                 allocFormat = DEFAULT_MPP_DST_FORMAT;
1681 
1682             ret = allocOutBuf(ALIGN_UP(mAssignedDisplay->mXres, bufAlign),
1683                     ALIGN_UP(mAssignedDisplay->mYres, bufAlign),
1684                     allocFormat, dst.usageFlags, mCurrentDstBuf);
1685         }
1686         if (ret < 0) {
1687             MPP_LOGE("%s:: fail to allocate dst buffer[%d]", __func__, mCurrentDstBuf);
1688             goto save_frame_info;
1689         }
1690         if (mDstImgs[mCurrentDstBuf].format != dst.format) {
1691             MPP_LOGD(eDebugMPP, "dst format is changed (%d -> %d)",
1692                     mDstImgs[mCurrentDstBuf].format, dst.format);
1693             mDstImgs[mCurrentDstBuf].format = dst.format;
1694         }
1695     }
1696 
1697     if ((realloc == false) && canUsePrevFrame()) {
1698         mCurrentDstBuf = (mCurrentDstBuf + NUM_MPP_DST_BUFS(mLogicalType) - 1)% NUM_MPP_DST_BUFS(mLogicalType);
1699         MPP_LOGD(eDebugMPP|eDebugFence, "Reuse previous frame, dstImg[%d]", mCurrentDstBuf);
1700         for (uint32_t i = 0; i < mAssignedSources.size(); i++) {
1701             mAssignedSources[i]->mSrcImg.acquireFenceFd =
1702                 fence_close(mAssignedSources[i]->mSrcImg.acquireFenceFd,
1703                         mAssignedDisplay, FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_G2D);
1704         }
1705         goto save_frame_info;
1706     }
1707 
1708     /* G2D or sclaer case */
1709     if ((ret = doPostProcessingInternal()) < 0) {
1710         MPP_LOGE("%s:: fail to post processing, ret %d",
1711                 __func__, ret);
1712         goto save_frame_info;
1713     }
1714 
1715 save_frame_info:
1716     /* Save current frame information for next frame*/
1717     mPrevAssignedDisplayType = mAssignedDisplay->mType;
1718     mPrevFrameInfo.srcNum = (uint32_t)mAssignedSources.size();
1719     for (uint32_t i = 0; i < mPrevFrameInfo.srcNum; i++) {
1720         mPrevFrameInfo.srcInfo[i] = mAssignedSources[i]->mSrcImg;
1721         mPrevFrameInfo.dstInfo[i] = mAssignedSources[i]->mMidImg;
1722     }
1723 
1724     MPP_LOGD(eDebugMPP, "mPrevAssignedState: %d, mPrevAssignedDisplayType: %d--------------",
1725             mAssignedState, mAssignedDisplay->mType);
1726 
1727     return ret;
1728 }
1729 
1730 /*
1731  * This function should be called after doPostProcessing()
1732  * because doPostProcessing() sets
1733  * mSrcImgs[].mppImg.releaseFenceFd
1734  */
getSrcReleaseFence(uint32_t srcIndex)1735 int32_t ExynosMPP::getSrcReleaseFence(uint32_t srcIndex)
1736 {
1737     if (srcIndex >= NUM_MPP_SRC_BUFS)
1738         return -EINVAL;
1739 
1740     return mSrcImgs[srcIndex].acrylicReleaseFenceFd;
1741 
1742     return -EINVAL;
1743 }
1744 
resetSrcReleaseFence()1745 int32_t ExynosMPP::resetSrcReleaseFence()
1746 {
1747     MPP_LOGD(eDebugFence, "");
1748     for (uint32_t i = 0; i < mAssignedSources.size(); i++) {
1749         mSrcImgs[i].acrylicReleaseFenceFd = -1;
1750     }
1751     return NO_ERROR;
1752 }
1753 
getDstImageInfo(exynos_image * img)1754 int32_t ExynosMPP::getDstImageInfo(exynos_image *img)
1755 {
1756     if ((mCurrentDstBuf < 0) || (mCurrentDstBuf >= NUM_MPP_DST_BUFS(mLogicalType)) ||
1757         (mAssignedDisplay == NULL)) {
1758         MPP_LOGE("mCurrentDstBuf(%d), mAssignedDisplay(%p)", mCurrentDstBuf, mAssignedDisplay);
1759         return -EINVAL;
1760     }
1761 
1762     memset(img, 0, sizeof(exynos_image));
1763     img->acquireFenceFd = -1;
1764     img->releaseFenceFd = -1;
1765 
1766     img->compressed = needCompressDstBuf();
1767 
1768     if (mDstImgs[mCurrentDstBuf].bufferHandle == NULL) {
1769         img->acquireFenceFd = -1;
1770         img->releaseFenceFd = -1;
1771         return -EFAULT;
1772     } else {
1773         img->bufferHandle = mDstImgs[mCurrentDstBuf].bufferHandle;
1774         VendorGraphicBufferMeta gmeta(img->bufferHandle);
1775         img->fullWidth = gmeta.stride;
1776         img->fullHeight = gmeta.vstride;
1777         if ((mLogicalType == MPP_LOGICAL_G2D_RGB) ||
1778             (mLogicalType == MPP_LOGICAL_G2D_COMBO)) {
1779             if (mAssignedSources.size() == 1) {
1780                 img->x = mAssignedSources[0]->mDstImg.x;
1781                 img->y = mAssignedSources[0]->mDstImg.y;
1782                 img->w = mAssignedSources[0]->mDstImg.w;
1783                 img->h = mAssignedSources[0]->mDstImg.h;
1784             } else {
1785                 img->x = 0;
1786                 img->y = 0;
1787                 img->w = mAssignedDisplay->mXres;
1788                 img->h = mAssignedDisplay->mXres;
1789             }
1790         } else {
1791             img->x = mAssignedSources[0]->mMidImg.x;
1792             img->y = mAssignedSources[0]->mMidImg.y;
1793             img->w = mAssignedSources[0]->mMidImg.w;
1794             img->h = mAssignedSources[0]->mMidImg.h;
1795             img->needColorTransform =
1796                 mAssignedSources[0]->mMidImg.needColorTransform;
1797         }
1798 
1799         img->format = mDstImgs[mCurrentDstBuf].format;
1800         MPP_LOGD(eDebugFence, "get dstBuf[%d] accquireFence(%d)", mCurrentDstBuf,
1801                 mDstImgs[mCurrentDstBuf].acrylicAcquireFenceFd);
1802         img->acquireFenceFd = mDstImgs[mCurrentDstBuf].acrylicAcquireFenceFd;
1803         img->releaseFenceFd = mDstImgs[mCurrentDstBuf].acrylicReleaseFenceFd;
1804         img->dataSpace = mDstImgs[mCurrentDstBuf].dataspace;
1805     }
1806     return NO_ERROR;
1807 }
1808 
1809 /*
1810  * This function should be called after getDstReleaseFence()
1811  * by ExynosDisplay
1812  */
setDstAcquireFence(int acquireFence)1813 int32_t ExynosMPP::setDstAcquireFence(int acquireFence)
1814 {
1815 
1816     int dstBufIndex = 0;
1817 
1818     dstBufIndex = mPrivDstBuf;
1819 
1820     if (mPrivDstBuf == mCurrentDstBuf)
1821         MPP_LOGD(eDebugFence|eDebugMPP,
1822                 "M2MMPP : same buffer was reused idx %d, %d",mPrivDstBuf, mCurrentDstBuf);
1823 
1824     if (dstBufIndex < 0 || dstBufIndex >= NUM_MPP_DST_BUFS(mLogicalType)) {
1825         // TODO fence_close..
1826         acquireFence = fence_close(acquireFence, mAssignedDisplay, FENCE_TYPE_DST_ACQUIRE, FENCE_IP_ALL);
1827         mPrivDstBuf = mCurrentDstBuf;
1828         return -EINVAL;
1829     }
1830 
1831     if (acquireFence < 0) {
1832         mPrivDstBuf = mCurrentDstBuf;
1833         return -EINVAL;
1834     }
1835 
1836     if (mDstImgs[dstBufIndex].acrylicAcquireFenceFd >= 0) {
1837         MPP_LOGD(eDebugFence,"mDstImgs[%d].acrylicAcquireFenceFd: %d is closed", dstBufIndex,
1838                 mDstImgs[dstBufIndex].acrylicAcquireFenceFd);
1839         fence_close(mDstImgs[dstBufIndex].acrylicAcquireFenceFd, mAssignedDisplay,
1840                 FENCE_TYPE_DST_ACQUIRE, FENCE_IP_ALL);
1841     }
1842     if (mPhysicalType == MPP_MSC)
1843         mDstImgs[dstBufIndex].acrylicAcquireFenceFd =
1844             hwcCheckFenceDebug(mAssignedDisplay, FENCE_TYPE_DST_ACQUIRE, FENCE_IP_MSC, acquireFence);
1845     else
1846         mDstImgs[dstBufIndex].acrylicAcquireFenceFd =
1847             hwcCheckFenceDebug(mAssignedDisplay, FENCE_TYPE_DST_ACQUIRE, FENCE_IP_G2D, acquireFence);
1848 
1849     MPP_LOGD(eDebugFence,"->mDstImgs[%d].acrylicAcquireFenceFd: %d", dstBufIndex,
1850             mDstImgs[dstBufIndex].acrylicAcquireFenceFd);
1851 
1852     mPrivDstBuf = mCurrentDstBuf;
1853 
1854     return NO_ERROR;
1855 }
1856 
resetDstReleaseFence()1857 int32_t ExynosMPP::resetDstReleaseFence()
1858 {
1859     MPP_LOGD(eDebugFence, "");
1860 
1861     if (mCurrentDstBuf < 0 || mCurrentDstBuf >= NUM_MPP_DST_BUFS(mLogicalType))
1862         return -EINVAL;
1863 
1864     mDstImgs[mCurrentDstBuf].acrylicReleaseFenceFd = -1;
1865 
1866     return NO_ERROR;
1867 }
1868 
requestHWStateChange(uint32_t state)1869 int32_t ExynosMPP::requestHWStateChange(uint32_t state)
1870 {
1871     MPP_LOGD(eDebugMPP|eDebugFence|eDebugBuf, "state: %d", state);
1872     /* Set HW state to running */
1873     if (mHWState == state) {
1874         if ((mPhysicalType == MPP_G2D) && (state == MPP_HW_STATE_IDLE) && (mHWBusyFlag == false)) {
1875             int ret = NO_ERROR;
1876             if ((ret = prioritize(-1)) != NO_ERROR)
1877                 MPP_LOGI("prioritize (%d) will be applied on next work", ret);
1878         }
1879         return NO_ERROR;
1880     }
1881 
1882     if (state == MPP_HW_STATE_RUNNING)
1883         mHWState = MPP_HW_STATE_RUNNING;
1884     else if (state == MPP_HW_STATE_IDLE) {
1885         if (mLastStateFenceFd >= 0)
1886             mResourceManageThread->addStateFence(mLastStateFenceFd);
1887         else
1888             mHWState = MPP_HW_STATE_IDLE;
1889         mLastStateFenceFd = -1;
1890 
1891         if ((mPhysicalType == MPP_G2D) && (mHWBusyFlag == false)) {
1892             int ret = NO_ERROR;
1893             if ((ret = prioritize(-1)) != NO_ERROR)
1894                 MPP_LOGI("prioritize (%d) is not applied on next work", ret);
1895         }
1896 
1897         /* Free all of output buffers */
1898         if (mMPPType == MPP_TYPE_M2M) {
1899             for(uint32_t i = 0; i < NUM_MPP_DST_BUFS(mLogicalType); i++) {
1900                 exynos_mpp_img_info freeDstBuf = mDstImgs[i];
1901                 memset(&mDstImgs[i], 0, sizeof(mDstImgs[i]));
1902                 mDstImgs[i].acrylicAcquireFenceFd = freeDstBuf.acrylicAcquireFenceFd;
1903                 mDstImgs[i].acrylicReleaseFenceFd = freeDstBuf.acrylicReleaseFenceFd;
1904                 freeDstBuf.acrylicAcquireFenceFd = -1;
1905                 freeDstBuf.acrylicReleaseFenceFd = -1;
1906 
1907                 if (mFreeOutBufFlag == true) {
1908                     MPP_LOGD(eDebugMPP|eDebugFence|eDebugBuf, "free outbuf[%d] %p",
1909                             i, freeDstBuf.bufferHandle);
1910                     if (freeDstBuf.bufferHandle != NULL && mAllocOutBufFlag) {
1911                         freeOutBuf(freeDstBuf);
1912                     }
1913                 } else {
1914                     mDstImgs[i].bufferHandle = freeDstBuf.bufferHandle;
1915                     mDstImgs[i].bufferType = freeDstBuf.bufferType;
1916                 }
1917             }
1918         }
1919 
1920         for (uint32_t i = 0; i < NUM_MPP_SRC_BUFS; i++)
1921         {
1922             if (mSrcImgs[i].mppLayer != NULL) {
1923                 delete mSrcImgs[i].mppLayer;
1924                 mSrcImgs[i].mppLayer = NULL;
1925             }
1926         }
1927         memset(&mPrevFrameInfo, 0, sizeof(mPrevFrameInfo));
1928         for (int i = 0; i < NUM_MPP_SRC_BUFS; i++) {
1929             mPrevFrameInfo.srcInfo[i].acquireFenceFd = -1;
1930             mPrevFrameInfo.srcInfo[i].releaseFenceFd = -1;
1931             mPrevFrameInfo.dstInfo[i].acquireFenceFd = -1;
1932             mPrevFrameInfo.dstInfo[i].releaseFenceFd = -1;
1933         }
1934     }
1935 
1936     return NO_ERROR;
1937 }
1938 
setHWStateFence(int32_t fence)1939 int32_t ExynosMPP::setHWStateFence(int32_t fence)
1940 {
1941     MPP_LOGD(eDebugFence, "Update HWState fence, Close(%d), set(%d)",
1942             mLastStateFenceFd, fence);
1943     mLastStateFenceFd = fence;
1944 
1945     return NO_ERROR;
1946 }
1947 
1948 /**
1949  * @param ..
1950  * @return int32_t
1951  */
setupRestriction()1952 int32_t ExynosMPP::setupRestriction() {
1953 
1954     MPP_LOGD(eDebugMPP, "mPhysicalType(%d)", mPhysicalType);
1955 
1956     for (uint32_t i = 0; i < RESTRICTION_MAX; i++) {
1957         const restriction_size_element *restriction_size_table = mResourceManager->mSizeRestrictions[i];
1958         for (uint32_t j = 0; j < mResourceManager->mSizeRestrictionCnt[i]; j++) {
1959             if (restriction_size_table[j].key.hwType == mPhysicalType) {
1960                 if ((restriction_size_table[j].key.nodeType == NODE_SRC) ||
1961                         (restriction_size_table[j].key.nodeType == NODE_NONE)) {
1962                     memcpy(&mSrcSizeRestrictions[i], &restriction_size_table[j].sizeRestriction,
1963                             sizeof(mSrcSizeRestrictions[i]));
1964                     MPP_LOGD(eDebugMPP, "\tSet mSrcSizeRestrictions[%d], "
1965                             "[%d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d]",
1966                             i, mSrcSizeRestrictions[i].maxDownScale, mSrcSizeRestrictions[i].maxUpScale,
1967                             mSrcSizeRestrictions[i].maxFullWidth, mSrcSizeRestrictions[i].maxFullHeight,
1968                             mSrcSizeRestrictions[i].minFullWidth, mSrcSizeRestrictions[i].minFullHeight,
1969                             mSrcSizeRestrictions[i].fullWidthAlign, mSrcSizeRestrictions[i].fullHeightAlign,
1970                             mSrcSizeRestrictions[i].maxCropWidth, mSrcSizeRestrictions[i].maxCropHeight,
1971                             mSrcSizeRestrictions[i].minCropWidth, mSrcSizeRestrictions[i].minCropHeight,
1972                             mSrcSizeRestrictions[i].cropXAlign, mSrcSizeRestrictions[i].cropYAlign,
1973                             mSrcSizeRestrictions[i].cropWidthAlign, mSrcSizeRestrictions[i].cropHeightAlign);
1974 
1975                 }
1976                 if ((restriction_size_table[j].key.nodeType == NODE_DST) ||
1977                         (restriction_size_table[j].key.nodeType == NODE_NONE)) {
1978                     memcpy(&mDstSizeRestrictions[i], &restriction_size_table[j].sizeRestriction,
1979                             sizeof(mDstSizeRestrictions[i]));
1980                     MPP_LOGD(eDebugMPP, "\tSet mDstSizeRestrictions[%d], "
1981                             "[%d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d]",
1982                             i, mDstSizeRestrictions[i].maxDownScale, mDstSizeRestrictions[i].maxUpScale,
1983                             mDstSizeRestrictions[i].maxFullWidth, mDstSizeRestrictions[i].maxFullHeight,
1984                             mDstSizeRestrictions[i].minFullWidth, mDstSizeRestrictions[i].minFullHeight,
1985                             mDstSizeRestrictions[i].fullWidthAlign, mDstSizeRestrictions[i].fullHeightAlign,
1986                             mDstSizeRestrictions[i].maxCropWidth, mDstSizeRestrictions[i].maxCropHeight,
1987                             mDstSizeRestrictions[i].minCropWidth, mDstSizeRestrictions[i].minCropHeight,
1988                             mDstSizeRestrictions[i].cropXAlign, mDstSizeRestrictions[i].cropYAlign,
1989                             mDstSizeRestrictions[i].cropWidthAlign, mDstSizeRestrictions[i].cropHeightAlign);
1990                 }
1991             }
1992         }
1993     }
1994 
1995     return NO_ERROR;
1996 }
1997 
isSupported(ExynosDisplay & display,struct exynos_image & src,struct exynos_image & dst)1998 int64_t ExynosMPP::isSupported(ExynosDisplay &display, struct exynos_image &src, struct exynos_image &dst)
1999 {
2000     uint32_t maxSrcWidth = getSrcMaxWidth(src);
2001     uint32_t maxSrcHeight = getSrcMaxHeight(src);
2002     uint32_t minSrcWidth = getSrcMinWidth(src);
2003     uint32_t minSrcHeight = getSrcMinHeight(src);
2004     uint32_t srcWidthAlign = getSrcWidthAlign(src);
2005     uint32_t srcHeightAlign = getSrcHeightAlign(src);
2006 
2007     uint32_t maxSrcCropWidth = getSrcMaxCropWidth(src);
2008     uint32_t maxSrcCropHeight = getSrcMaxCropHeight(src);
2009     uint32_t maxSrcCropSize = getSrcMaxCropSize(src);
2010     uint32_t minSrcCropWidth = getSrcMinCropWidth(src);
2011     uint32_t minSrcCropHeight = getSrcMinCropHeight(src);
2012     uint32_t srcCropWidthAlign = getSrcCropWidthAlign(src);
2013     uint32_t srcCropHeightAlign = getSrcCropHeightAlign(src);
2014     uint32_t srcXOffsetAlign = getSrcXOffsetAlign(src);
2015     uint32_t srcYOffsetAlign = getSrcYOffsetAlign(src);
2016 
2017     uint32_t maxDstWidth = getDstMaxWidth(dst);
2018     uint32_t maxDstHeight = getDstMaxHeight(dst);
2019     uint32_t minDstWidth = getDstMinWidth(dst);
2020     uint32_t minDstHeight = getDstMinHeight(dst);
2021     uint32_t dstWidthAlign = getDstWidthAlign(dst);
2022     uint32_t dstHeightAlign = getDstHeightAlign(dst);
2023     uint32_t dstXOffsetAlign = getDstXOffsetAlign(dst);
2024     uint32_t dstYOffsetAlign = getDstYOffsetAlign(dst);
2025 
2026     uint32_t maxDownscale = getMaxDownscale(display, src, dst);
2027     uint32_t maxUpscale = getMaxUpscale(src, dst);
2028 
2029     exynos_image rot_dst = dst;
2030     bool isPerpendicular = !!(src.transform & HAL_TRANSFORM_ROT_90);
2031     if (isPerpendicular) {
2032         rot_dst.w = dst.h;
2033         rot_dst.h = dst.w;
2034     }
2035 
2036     if (dst.w > maxDstWidth)
2037         return -eMPPExeedMaxDstWidth;
2038     else if (dst.h > maxDstHeight)
2039         return -eMPPExeedMaxDstHeight;
2040     else if (dst.w < minDstWidth)
2041         return -eMPPExeedMinDstWidth;
2042     else if (dst.h < minDstHeight)
2043         return -eMPPExeedMinDstHeight;
2044     else if (src.isDimLayer()) { // Dim layer
2045         if (isDimLayerSupported()) {
2046             return NO_ERROR;
2047         } else {
2048             return -eMPPUnsupportedDIMLayer;
2049         }
2050     }
2051     if (!isSupportedCapability(display, src))
2052         return -eMPPSaveCapability;
2053     else if (!isSrcFormatSupported(src))
2054         return -eMPPUnsupportedFormat;
2055     else if (!isDstFormatSupported(dst))
2056         return -eMPPUnsupportedFormat;
2057     else if (!isDataspaceSupportedByMPP(src, dst))
2058         return -eMPPUnsupportedCSC;
2059     else if (!isSupportedHDR10Plus(src, dst))
2060         return -eMPPUnsupportedDynamicMeta;
2061     else if (!isSupportedBlend(src))
2062         return -eMPPUnsupportedBlending;
2063     else if (!isSupportedTransform(src))
2064         return -eMPPUnsupportedRotation;
2065     else if (src.fullWidth < minSrcWidth)
2066         return -eMPPExeedMinSrcWidth;
2067     else if (src.fullHeight < minSrcHeight)
2068         return -eMPPExeedMinSrcHeight;
2069     else if (src.w < minSrcCropWidth)
2070         return -eMPPExeedSrcWCropMin;
2071     else if (src.h < minSrcCropHeight)
2072         return -eMPPExeedSrcHCropMin;
2073     else if ((dst.w % dstWidthAlign != 0) || (dst.h % dstHeightAlign != 0))
2074         return -eMPPNotAlignedDstSize;
2075     else if (src.w > rot_dst.w * maxDownscale)
2076         return -eMPPExeedMaxDownScale;
2077     else if (rot_dst.w > src.w * maxUpscale)
2078         return -eMPPExeedMaxUpScale;
2079     else if (src.h > rot_dst.h * maxDownscale)
2080         return -eMPPExeedMaxDownScale;
2081     else if (rot_dst.h > src.h * maxUpscale)
2082         return -eMPPExeedMaxUpScale;
2083     else if (!isSupportedDRM(src))
2084         return -eMPPUnsupportedDRM;
2085     else if (!isSupportedHStrideCrop(src))
2086         return -eMPPStrideCrop;
2087     else if (src.fullWidth > maxSrcWidth)
2088         return -eMPPExceedHStrideMaximum;
2089     else if (src.fullWidth % srcWidthAlign != 0)
2090         return -eMPPNotAlignedHStride;
2091 
2092     if ((src.w * src.h) > maxSrcCropSize)
2093         return -eMPPExeedSrcCropMax;
2094 
2095     if (getDrmMode(src.usageFlags) == NO_DRM) {
2096         if (src.fullHeight > maxSrcHeight)
2097             return -eMPPExceedVStrideMaximum;
2098         else if (src.fullHeight % srcHeightAlign != 0)
2099             return -eMPPNotAlignedVStride;
2100         else if (src.w > maxSrcCropWidth)
2101             return -eMPPExeedSrcWCropMax;
2102         else if (src.h > maxSrcCropHeight)
2103             return -eMPPExeedSrcHCropMax;
2104         else if ((src.w % srcCropWidthAlign != 0) || (src.h % srcCropHeightAlign != 0))
2105             return -eMPPNotAlignedCrop;
2106         else if ((src.x % srcXOffsetAlign != 0) || (src.y % srcYOffsetAlign != 0))
2107             return -eMPPNotAlignedOffset;
2108     }
2109 
2110     if ((dst.x % dstXOffsetAlign != 0) || (dst.y % dstYOffsetAlign != 0))
2111         return -eMPPNotAlignedOffset;
2112 
2113     if (!isSupportedCompression(src))
2114         return -eMPPUnsupportedCompression;
2115 
2116     if (!isSupportLayerColorTransform(src,dst))
2117         return -eMPPUnsupportedColorTransform;
2118 
2119     return NO_ERROR;
2120 }
2121 
resetMPP()2122 int32_t ExynosMPP::resetMPP()
2123 {
2124     mAssignedState = MPP_ASSIGN_STATE_FREE;
2125     mAssignedDisplay = NULL;
2126     mAssignedSources.clear();
2127     resetUsedCapacity();
2128     mReservedDisplay = -1;
2129     mHWBusyFlag = false;
2130 
2131     return NO_ERROR;
2132 }
2133 
resetAssignedState()2134 int32_t ExynosMPP::resetAssignedState()
2135 {
2136     for (int i = (int)mAssignedSources.size(); i-- > 0;) {
2137         ExynosMPPSource *mppSource = mAssignedSources[i];
2138         if (mppSource->mOtfMPP == this) {
2139             mppSource->mOtfMPP = NULL;
2140         }
2141         if (mppSource->mM2mMPP == this) {
2142             mppSource->mM2mMPP = NULL;
2143         }
2144         mAssignedSources.removeItemsAt(i);
2145     }
2146 
2147     /* Keep status if mAssignedState is MPP_ASSIGN_STATE_RESERVED */
2148     if ((mAssignedState & MPP_ASSIGN_STATE_ASSIGNED) &&
2149         (mAssignedSources.size() == 0)) {
2150         mAssignedState &= ~MPP_ASSIGN_STATE_ASSIGNED;
2151         mAssignedDisplay = NULL;
2152     }
2153 
2154     /* All mpp source are removed, reset capacity information */
2155     resetUsedCapacity();
2156 
2157     return NO_ERROR;
2158 }
2159 
resetAssignedState(ExynosMPPSource * mppSource)2160 int32_t ExynosMPP::resetAssignedState(ExynosMPPSource *mppSource)
2161 {
2162     bool needUpdateCapacity = false;
2163     for (int i = (int)mAssignedSources.size(); i-- > 0;) {
2164         ExynosMPPSource *source = mAssignedSources[i];
2165         if (source == mppSource) {
2166             if (mppSource->mM2mMPP == this) {
2167                 mppSource->mM2mMPP = NULL;
2168             }
2169             /* Update information for used capacity */
2170             /* This should be called before mAssignedSources.removeItemsAt(mppSource) */
2171             needUpdateCapacity = removeCapacity(mppSource);
2172 
2173             mAssignedSources.removeItemsAt(i);
2174 
2175             if (needUpdateCapacity)
2176                 updateUsedCapacity();
2177 
2178             break;
2179         }
2180     }
2181 
2182     /* Keep status if mAssignedState is MPP_ASSIGN_STATE_RESERVED */
2183     if ((mAssignedState & MPP_ASSIGN_STATE_ASSIGNED) &&
2184         (mAssignedSources.size() == 0)) {
2185         mAssignedState &= ~MPP_ASSIGN_STATE_ASSIGNED;
2186         mAssignedDisplay = NULL;
2187     }
2188 
2189     return NO_ERROR;
2190 }
2191 
reserveMPP(int32_t displayId)2192 int32_t ExynosMPP::reserveMPP(int32_t displayId)
2193 {
2194     mAssignedState |= MPP_ASSIGN_STATE_RESERVED;
2195     mReservedDisplay = displayId;
2196 
2197     return NO_ERROR;
2198 }
2199 
assignMPP(ExynosDisplay * display,ExynosMPPSource * mppSource)2200 int32_t ExynosMPP::assignMPP(ExynosDisplay *display, ExynosMPPSource* mppSource)
2201 {
2202     mAssignedState |= MPP_ASSIGN_STATE_ASSIGNED;
2203 
2204     if (mMPPType == MPP_TYPE_OTF)
2205         mppSource->mOtfMPP = this;
2206     else if (mMPPType == MPP_TYPE_M2M)
2207         mppSource->mM2mMPP = this;
2208     else {
2209         MPP_LOGE("%s:: Invalid mppType(%d)", __func__, mMPPType);
2210         return -EINVAL;
2211     }
2212 
2213     mAssignedDisplay = display;
2214 
2215     /* Update information for used capacity */
2216     /* This should be called before mAssignedSources.add(mppSource) */
2217     bool needUpdateCapacity = addCapacity(mppSource);
2218 
2219     mAssignedSources.add(mppSource);
2220 
2221     MPP_LOGD(eDebugCapacity|eDebugMPP, "\tassigned to source(%p) type(%d), mAssignedSources(%zu)",
2222             mppSource, mppSource->mSourceType,
2223             mAssignedSources.size());
2224 
2225     if (needUpdateCapacity)
2226         updateUsedCapacity();
2227 
2228     if (mMaxSrcLayerNum > 1) {
2229         std::sort(mAssignedSources.begin(), mAssignedSources.end(), exynosMPPSourceComp);
2230     }
2231 
2232     return NO_ERROR;
2233 }
2234 
getSrcMaxBlendingNum(struct exynos_image __unused & src,struct exynos_image __unused & dst)2235 uint32_t ExynosMPP::getSrcMaxBlendingNum(struct exynos_image __unused &src, struct exynos_image __unused &dst)
2236 {
2237     uint32_t maxSrcLayerNum = mMaxSrcLayerNum;
2238     return maxSrcLayerNum;
2239 }
2240 
getAssignedSourceNum()2241 uint32_t ExynosMPP::getAssignedSourceNum()
2242 {
2243     return mAssignedSources.size();
2244 }
2245 
2246 /* Based on multi-resolution support */
setDstAllocSize(uint32_t width,uint32_t height)2247 void ExynosMPP::setDstAllocSize(uint32_t width, uint32_t height)
2248 {
2249     switch(width) {
2250     case 720:
2251         mDstAllocatedSize = ((height >= 1480) ? DST_SIZE_HD_PLUS : DST_SIZE_HD);
2252         break;
2253     case 1080:
2254         mDstAllocatedSize = ((height >= 2220) ? DST_SIZE_FHD_PLUS : DST_SIZE_FHD);
2255         break;
2256     case 1440:
2257         mDstAllocatedSize = ((height >= 2960) ? DST_SIZE_WQHD_PLUS : DST_SIZE_WQHD);
2258         break;
2259     default:
2260         mDstAllocatedSize = DST_SIZE_UNKNOWN;
2261         break;
2262     }
2263 }
2264 
getDstAllocSize()2265 dst_alloc_buf_size_t ExynosMPP::getDstAllocSize()
2266 {
2267     return mDstAllocatedSize;
2268 }
2269 
needPreAllocation()2270 bool ExynosMPP::needPreAllocation()
2271 {
2272     bool ret = false;
2273 
2274     if ((mLogicalType == MPP_LOGICAL_G2D_RGB) &&
2275         (mPreAssignDisplayList[mResourceManager->mDevice->mDisplayMode] == HWC_DISPLAY_PRIMARY_BIT))
2276         ret = true;
2277 
2278     return ret;
2279 }
2280 
isAssignableState(ExynosDisplay * display,struct exynos_image & src,struct exynos_image & dst)2281 bool ExynosMPP::isAssignableState(ExynosDisplay *display, struct exynos_image &src, struct exynos_image &dst)
2282 {
2283     bool isAssignable = false;
2284 
2285     if (mAssignedState == MPP_ASSIGN_STATE_FREE) {
2286         if (mHWState == MPP_HW_STATE_IDLE)
2287             isAssignable = true;
2288         else {
2289             if ((mPrevAssignedDisplayType < 0) ||
2290                 ((uint32_t)mPrevAssignedDisplayType == display->mType))
2291                 isAssignable = true;
2292             else
2293                 isAssignable = false;
2294         }
2295     }
2296 
2297     if ((mAssignedState & MPP_ASSIGN_STATE_ASSIGNED) && (mAssignedState & MPP_ASSIGN_STATE_RESERVED))
2298     {
2299         if (mReservedDisplay == (int32_t)display->getId()) {
2300             if (mAssignedSources.size() < getSrcMaxBlendingNum(src, dst))
2301                 isAssignable = true;
2302             else
2303                 isAssignable = false;
2304         } else {
2305             isAssignable = false;
2306         }
2307     } else if ((mAssignedState & MPP_ASSIGN_STATE_ASSIGNED) && !(mAssignedState & MPP_ASSIGN_STATE_RESERVED)) {
2308         if (mAssignedSources.size() < getSrcMaxBlendingNum(src, dst))
2309             isAssignable = true;
2310         else
2311             isAssignable = false;
2312     } else if (mAssignedState & MPP_ASSIGN_STATE_RESERVED) {
2313         if (mReservedDisplay == (int32_t)display->getId())
2314             isAssignable = true;
2315         else
2316             isAssignable = false;
2317     }
2318 
2319     MPP_LOGD(eDebugMPP, "\tisAssignableState(%d), assigned size(%zu), getSrcMaxBlendingNum(%d)",
2320             isAssignable, mAssignedSources.size(), getSrcMaxBlendingNum(src, dst));
2321     return isAssignable;
2322 }
isAssignable(ExynosDisplay * display,struct exynos_image & src,struct exynos_image & dst)2323 bool ExynosMPP::isAssignable(ExynosDisplay *display,
2324         struct exynos_image &src, struct exynos_image &dst)
2325 {
2326     bool isAssignable = isAssignableState(display, src, dst);
2327     return (isAssignable && hasEnoughCapa(display, src, dst));
2328 }
2329 
hasEnoughCapa(ExynosDisplay * display,struct exynos_image & src,struct exynos_image & dst)2330 bool ExynosMPP::hasEnoughCapa(ExynosDisplay *display, struct exynos_image &src, struct exynos_image &dst)
2331 {
2332     if (mCapacity == -1)
2333         return true;
2334 
2335     float totalUsedCapacity = ExynosResourceManager::getResourceUsedCapa(*this);
2336     MPP_LOGD(eDebugCapacity|eDebugMPP, "totalUsedCapacity(%f), mUsedCapacity(%f)",
2337             totalUsedCapacity, mUsedCapacity);
2338 
2339     /* mUsedCapacity should be re-calculated including src, dst passed as parameters*/
2340     totalUsedCapacity -= mUsedCapacity;
2341 
2342     float requiredCapacity = getRequiredCapacity(display, src, dst);
2343 
2344     MPP_LOGD(eDebugCapacity|eDebugMPP, "mCapacity(%f), usedCapacity(%f), RequiredCapacity(%f)",
2345             mCapacity, totalUsedCapacity, requiredCapacity);
2346 
2347     if (mCapacity >= (totalUsedCapacity + requiredCapacity))
2348         return true;
2349     else if ((hasHdrInfo(src)) &&
2350              (totalUsedCapacity == 0) && (requiredCapacity < (mCapacity * 1.2))) {
2351         /* HDR video will be excepted from G2D capa calculation */
2352         /* if DRM has assigned before, totalUsedCapacity will be non-zero */
2353         return true;
2354     } else
2355         return false;
2356 }
2357 
getPPCIndex(const struct exynos_image & src,const struct exynos_image & dst,uint32_t & formatIndex,uint32_t & rotIndex,uint32_t & scaleIndex,const struct exynos_image & criteria)2358 void ExynosMPP::getPPCIndex(const struct exynos_image &src,
2359         const struct exynos_image &dst,
2360         uint32_t &formatIndex, uint32_t &rotIndex, uint32_t &scaleIndex,
2361         const struct exynos_image &criteria)
2362 {
2363     formatIndex = 0;
2364     rotIndex = 0;
2365     scaleIndex = 0;
2366 
2367     /* Compare SBWC, AFBC and 10bitYUV420 first! because can be overlapped with other format */
2368     if (isFormatSBWC(criteria.format) && hasPPC(mPhysicalType, PPC_FORMAT_SBWC, PPC_ROT_NO))
2369         formatIndex = PPC_FORMAT_SBWC;
2370     else if (src.compressed == 1) {
2371         if ((isFormatRgb(criteria.format)) && hasPPC(mPhysicalType, PPC_FORMAT_AFBC_RGB, PPC_ROT_NO))
2372             formatIndex = PPC_FORMAT_AFBC_RGB;
2373         else if ((isFormatYUV(criteria.format)) && hasPPC(mPhysicalType, PPC_FORMAT_AFBC_YUV, PPC_ROT_NO))
2374             formatIndex = PPC_FORMAT_AFBC_YUV;
2375         else {
2376             formatIndex = PPC_FORMAT_RGB32;
2377             MPP_LOGW("%s:: AFBC PPC is not existed. Use default PPC", __func__);
2378         }
2379     } else if (isFormatP010(criteria.format) && hasPPC(mPhysicalType, PPC_FORMAT_P010, PPC_ROT_NO))
2380         formatIndex = PPC_FORMAT_P010;
2381     else if (isFormatYUV420(criteria.format) && hasPPC(mPhysicalType, PPC_FORMAT_YUV420, PPC_ROT_NO))
2382         formatIndex = PPC_FORMAT_YUV420;
2383     else if (isFormatYUV422(criteria.format) && hasPPC(mPhysicalType, PPC_FORMAT_YUV422, PPC_ROT_NO))
2384         formatIndex = PPC_FORMAT_YUV422;
2385     else
2386         formatIndex = PPC_FORMAT_RGB32;
2387 
2388     if (((criteria.transform & HAL_TRANSFORM_ROT_90) != 0) ||
2389         (mRotatedSrcCropBW > 0))
2390         rotIndex = PPC_ROT;
2391     else
2392         rotIndex = PPC_ROT_NO;
2393 
2394     uint32_t srcResolution = src.w * src.h;
2395     uint32_t dstResolution = dst.w * dst.h;
2396 
2397     if (mPhysicalType == MPP_G2D) {
2398         if (srcResolution == dstResolution) {
2399             scaleIndex = PPC_SCALE_NO;
2400         } else if (dstResolution > srcResolution) {
2401             /* scale up case */
2402             if (dstResolution >= (srcResolution * 4))
2403                 scaleIndex = PPC_SCALE_UP_4_;
2404             else
2405                 scaleIndex = PPC_SCALE_UP_1_4;
2406         } else {
2407             /* scale down case */
2408             if ((dstResolution * 16) <= srcResolution)
2409                 scaleIndex = PPC_SCALE_DOWN_16_;
2410             else if (((dstResolution * 9) <= srcResolution) &&
2411                     (srcResolution < (dstResolution * 16)))
2412                 scaleIndex = PPC_SCALE_DOWN_9_16;
2413             else if (((dstResolution * 4) <= srcResolution) &&
2414                     (srcResolution < (dstResolution * 9)))
2415                 scaleIndex = PPC_SCALE_DOWN_4_9;
2416             else
2417                 scaleIndex = PPC_SCALE_DOWN_1_4;
2418         }
2419     } else scaleIndex = 0; /* MSC doesn't refer scale Index */
2420 }
2421 
getPPC(const struct exynos_image & src,const struct exynos_image & dst,const struct exynos_image & criteria,const struct exynos_image * assignCheckSrc,const struct exynos_image * assignCheckDst)2422 float ExynosMPP::getPPC(const struct exynos_image &src,
2423         const struct exynos_image &dst, const struct exynos_image &criteria,
2424         const struct exynos_image *assignCheckSrc,
2425         const struct exynos_image *assignCheckDst)
2426 {
2427     float PPC = 0;
2428     uint32_t formatIndex = 0;
2429     uint32_t rotIndex = 0;
2430     uint32_t scaleIndex = 0;
2431 
2432     getPPCIndex(src, dst, formatIndex, rotIndex, scaleIndex, criteria);
2433 
2434     if ((rotIndex == PPC_ROT_NO) && (assignCheckSrc != NULL) &&
2435         ((assignCheckSrc->transform & HAL_TRANSFORM_ROT_90) != 0)) {
2436         rotIndex = PPC_ROT;
2437     }
2438 
2439     if (mPhysicalType == MPP_G2D || mPhysicalType == MPP_MSC) {
2440         if (hasPPC(mPhysicalType, formatIndex, rotIndex)) {
2441             PPC = ppc_table_map.at(PPC_IDX(mPhysicalType, formatIndex, rotIndex)).ppcList[scaleIndex];
2442         }
2443     }
2444 
2445     if (PPC == 0) {
2446         MPP_LOGE("%s:: mPhysicalType(%d), formatIndex(%d), rotIndex(%d), scaleIndex(%d), PPC(%f) is not valid",
2447                 __func__, mPhysicalType, formatIndex, rotIndex, scaleIndex, PPC);
2448         PPC = 0.000001;  /* It means can't use mPhysicalType H/W  */
2449     }
2450 
2451     MPP_LOGD(eDebugCapacity, "srcW(%d), srcH(%d), dstW(%d), dstH(%d), rot(%d)"
2452             "formatIndex(%d), rotIndex(%d), scaleIndex(%d), PPC(%f)",
2453             src.w, src.h, dst.w, dst.h, src.transform,
2454             formatIndex, rotIndex, scaleIndex, PPC);
2455     return PPC;
2456 }
2457 
getAssignedCapacity()2458 float ExynosMPP::getAssignedCapacity()
2459 {
2460     float capacity = 0;
2461     float baseCycles = 0;
2462     uint32_t rotIndex = 0;
2463 
2464     if (mPhysicalType != MPP_G2D)
2465         return 0;
2466 
2467     /*
2468      * Client target is assigned to m2mMPP
2469      * even if capacity is not enough
2470      */
2471     if ((mAssignedDisplay != NULL) &&
2472         (mAssignedDisplay->mType == HWC_DISPLAY_VIRTUAL))
2473         return 0;
2474 
2475 
2476     for (uint32_t i = 0; i < mAssignedSources.size(); i++) {
2477         if ((mAssignedSources[i]->mSrcImg.transform & HAL_TRANSFORM_ROT_90) != 0)
2478             rotIndex = PPC_ROT;
2479     }
2480 
2481     MPP_LOGD(eDebugCapacity, "Check all of assigned layers cycles");
2482     /* PPC of layers that were added before should be changed */
2483     /* Check cycles of all assigned layers again */
2484     if ((mAssignedDisplay != NULL) && (mMaxSrcLayerNum > 1)) {
2485         baseCycles += ((mAssignedDisplay->mXres * mAssignedDisplay->mYres) / G2D_BASE_PPC_COLORFILL);
2486         MPP_LOGD(eDebugCapacity, "colorfill cycles: %f, total cycles: %f",
2487                 ((mAssignedDisplay->mXres * mAssignedDisplay->mYres) / G2D_BASE_PPC_COLORFILL), baseCycles);
2488     }
2489 
2490     for (uint32_t i = 0; i < mAssignedSources.size(); i++) {
2491         float srcCycles = 0;
2492         uint32_t srcResolution = mAssignedSources[i]->mSrcImg.w * mAssignedSources[i]->mSrcImg.h;
2493         uint32_t dstResolution = mAssignedSources[i]->mMidImg.w * mAssignedSources[i]->mMidImg.h;
2494         uint32_t maxResolution = max(srcResolution, dstResolution);
2495         float PPC = 0;
2496 
2497         if (mAssignedSources[i]->mSrcImg.layerFlags & EXYNOS_HWC_DIM_LAYER) {
2498             PPC = G2D_BASE_PPC_COLORFILL;
2499         } else {
2500             PPC = getPPC(mAssignedSources[i]->mSrcImg, mAssignedSources[i]->mMidImg, mAssignedSources[i]->mSrcImg,
2501                     &mAssignedSources[i]->mSrcImg, &mAssignedSources[i]->mMidImg);
2502         }
2503         srcCycles = maxResolution/PPC;
2504 
2505         /* Hdr and drm layer is exception */
2506         if ((hasHdrInfo(mAssignedSources[i]->mSrcImg) ||
2507             (getDrmMode(mAssignedSources[i]->mSrcImg.usageFlags) != NO_DRM))) {
2508             MPP_LOGD(eDebugCapacity, "Src[%d] is skipped(drm or hdr), cycles: %f, PPC: %f, srcResolution: %d, dstResolution: %d, rot(%d)",
2509                     i, srcCycles, PPC, srcResolution, dstResolution, mAssignedSources[i]->mSrcImg.transform);
2510             continue;
2511         }
2512 
2513         baseCycles += srcCycles;
2514 
2515         MPP_LOGD(eDebugCapacity, "Src[%d] cycles: %f, total cycles: %f, PPC: %f, srcResolution: %d, dstResolution: %d, rot(%d)",
2516                 i, srcCycles, baseCycles, PPC, srcResolution, dstResolution, mAssignedSources[i]->mSrcImg.transform);
2517     }
2518 
2519     capacity = baseCycles / mClockKhz;
2520 
2521     return capacity;
2522 }
2523 
getRequiredCapacity(ExynosDisplay * display,struct exynos_image & src,struct exynos_image & dst)2524 float ExynosMPP::getRequiredCapacity(ExynosDisplay *display, struct exynos_image &src,
2525         struct exynos_image &dst)
2526 {
2527     float capacity = 0;
2528     float cycles = 0;
2529     if (mPhysicalType == MPP_G2D) {
2530         /* Initialize value with the cycles that were already assigned */
2531         float baseCycles = mUsedBaseCycles;
2532         float srcCycles = 0;
2533         uint32_t srcResolution = src.w * src.h;
2534         uint32_t dstResolution = dst.w * dst.h;
2535         uint32_t maxResolution = max(srcResolution, dstResolution);
2536         float curBaseCycles = 0;
2537         float PPC = 0;
2538 
2539         if ((mAssignedSources.size() == 0) ||
2540             (mRotatedSrcCropBW != 0) ||
2541             ((mRotatedSrcCropBW == 0) &&
2542              ((src.transform & HAL_TRANSFORM_ROT_90) == 0))) {
2543             /* Just add cycles for current layer */
2544             if ((mAssignedSources.size() == 0) &&
2545                 (display != NULL) && (mMaxSrcLayerNum > 1)) {
2546                 curBaseCycles = ((display->mXres * display->mYres) / G2D_BASE_PPC_COLORFILL);
2547                 MPP_LOGD(eDebugCapacity, "There is no assigned layer. Colorfill cycles: %f should be added",
2548                         curBaseCycles);
2549             }
2550             curBaseCycles += getRequiredBaseCycles(src, dst);
2551             baseCycles += curBaseCycles;
2552             MPP_LOGD(eDebugCapacity, "mUsedBaseCycles was %f, Add base cycles %f, totalBaseCycle(%f)",
2553                     mUsedBaseCycles, curBaseCycles, baseCycles);
2554         } else {
2555             /* Recalculate cycles for all of layers */
2556             baseCycles = 0;
2557             MPP_LOGD(eDebugCapacity, "Check all of assigned layers cycles");
2558             /* PPC of layers that were added before should be changed */
2559             /* Check cycles of all assigned layers again */
2560             if ((display != NULL) && (mMaxSrcLayerNum > 1)) {
2561                 baseCycles += ((display->mXres * display->mYres) / G2D_BASE_PPC_COLORFILL);
2562                 MPP_LOGD(eDebugCapacity, "colorfill cycles: %f, total cycles: %f",
2563                         ((display->mXres * display->mYres) / G2D_BASE_PPC_COLORFILL), cycles);
2564             }
2565 
2566             for (uint32_t i = 0; i < mAssignedSources.size(); i++) {
2567                 float assignedSrcCycles = 0;
2568                 uint32_t assignedSrcResolution = mAssignedSources[i]->mSrcImg.w * mAssignedSources[i]->mSrcImg.h;
2569                 uint32_t assignedDstResolution = mAssignedSources[i]->mMidImg.w * mAssignedSources[i]->mMidImg.h;
2570                 uint32_t assignedMaxResolution = max(assignedSrcResolution, assignedDstResolution);
2571                 float assignedPPC = getPPC(mAssignedSources[i]->mSrcImg, mAssignedSources[i]->mMidImg,
2572                         mAssignedSources[i]->mSrcImg, &src, &dst);
2573 
2574                 assignedSrcCycles = assignedMaxResolution/assignedPPC;
2575                 baseCycles += assignedSrcCycles;
2576 
2577                 MPP_LOGD(eDebugCapacity, "Src[%d] cycles: %f, total cycles: %f, PPC: %f, srcResolution: %d, dstResolution: %d, rot(%d)",
2578                         i, assignedSrcCycles, baseCycles, assignedPPC, assignedSrcResolution, assignedDstResolution, mAssignedSources[i]->mSrcImg.transform);
2579             }
2580 
2581             PPC = getPPC(src, dst, src, &src, &dst);
2582 
2583             srcCycles = maxResolution/PPC;
2584             baseCycles += srcCycles;
2585 
2586             MPP_LOGD(eDebugCapacity, "check mppSource cycles: %f, total cycles: %f, PPC: %f, srcResolution: %d, dstResolution: %d, rot(%d)",
2587                     srcCycles, baseCycles, PPC, srcResolution, dstResolution, src.transform);
2588         }
2589 
2590         capacity = baseCycles / mClockKhz;
2591 
2592         MPP_LOGD(eDebugCapacity, "baseCycles: %f, capacity: %f",
2593                 baseCycles, capacity);
2594     } else if (mPhysicalType == MPP_MSC) {
2595         /* Initialize value with the capacity that were already assigned */
2596         capacity = mUsedCapacity;
2597 
2598         /* Just add capacity for current layer */
2599         float srcPPC = getPPC(src, dst, src);
2600         float dstPPC = getPPC(src, dst, dst);
2601         float srcCapacity = (float((src.w * src.h))) / (mClockKhz * srcPPC);
2602         float dstCapacity = (float((dst.w * dst.h))) / (mClockKhz * dstPPC);
2603 
2604         capacity += max(srcCapacity, dstCapacity);
2605 
2606     }
2607 
2608     return capacity;
2609 }
2610 
getRequiredBaseCycles(struct exynos_image & src,struct exynos_image & dst)2611 float ExynosMPP::getRequiredBaseCycles(struct exynos_image &src, struct exynos_image &dst)
2612 {
2613     if (mPhysicalType != MPP_G2D)
2614         return 0;
2615 
2616     uint32_t srcResolution = src.w * src.h;
2617     uint32_t dstResolution = dst.w * dst.h;
2618     uint32_t maxResolution = max(srcResolution, dstResolution);
2619 
2620     return maxResolution/(float)getPPC(src, dst, src);
2621 }
2622 
addCapacity(ExynosMPPSource * mppSource)2623 bool ExynosMPP::addCapacity(ExynosMPPSource* mppSource)
2624 {
2625     if ((mppSource == NULL) || mCapacity == -1)
2626         return false;
2627 
2628     if (mPhysicalType == MPP_G2D) {
2629         bool needUpdateCapacity = true;
2630         if ((mAssignedSources.size() == 0) ||
2631             (mRotatedSrcCropBW != 0) ||
2632             ((mRotatedSrcCropBW == 0) &&
2633              ((mppSource->mSrcImg.transform & HAL_TRANSFORM_ROT_90) == 0))) {
2634             needUpdateCapacity = false;
2635         }
2636 
2637         if (needUpdateCapacity)
2638             return true;
2639 
2640         if ((mMaxSrcLayerNum > 1) &&
2641             (mAssignedSources.size() == 0)) {
2642             if (mAssignedDisplay != NULL) {
2643                 /* This will be the first mppSource that is assigned to the ExynosMPP */
2644                 /* Add capacity for background */
2645                 mUsedBaseCycles += ((mAssignedDisplay->mXres * mAssignedDisplay->mYres) / G2D_BASE_PPC_COLORFILL);
2646                 MPP_LOGD(eDebugCapacity, "\tcolorfill cycles: %f, total cycles: %f",
2647                         ((mAssignedDisplay->mXres * mAssignedDisplay->mYres) / G2D_BASE_PPC_COLORFILL), mUsedBaseCycles);
2648             } else {
2649                 MPP_LOGE("mAssignedDisplay is null");
2650             }
2651         }
2652 
2653         float baseCycles = getRequiredBaseCycles(mppSource->mSrcImg, mppSource->mMidImg);
2654         mUsedBaseCycles += baseCycles;
2655 
2656         uint32_t srcResolution = mppSource->mSrcImg.w * mppSource->mSrcImg.h;
2657         uint32_t dstResolution = mppSource->mMidImg.w * mppSource->mMidImg.h;
2658         if ((mppSource->mSrcImg.transform & HAL_TRANSFORM_ROT_90) == 0)
2659             mNoRotatedSrcCropBW += srcResolution;
2660         else
2661             mRotatedSrcCropBW += srcResolution;
2662 
2663         mUsedCapacity = mUsedBaseCycles / mClockKhz;
2664 
2665         MPP_LOGD(eDebugCapacity, "src num: %zu base cycle is added: %f, mUsedBaseCycles: %f, mUsedCapacity(%f), srcResolution: %d, dstResolution: %d, rot: %d, mNoRotatedSrcCropBW(%d), mRotatedSrcCropBW(%d)",
2666                 mAssignedSources.size(),
2667                 baseCycles, mUsedBaseCycles, mUsedCapacity, srcResolution, dstResolution,
2668                 mppSource->mSrcImg.transform, mNoRotatedSrcCropBW, mRotatedSrcCropBW);
2669     } else if (mPhysicalType == MPP_MSC) {
2670         mUsedCapacity = getRequiredCapacity(NULL, mppSource->mSrcImg, mppSource->mMidImg);
2671     }
2672 
2673     return false;
2674 }
2675 
removeCapacity(ExynosMPPSource * mppSource)2676 bool ExynosMPP::removeCapacity(ExynosMPPSource* mppSource)
2677 {
2678     if ((mppSource == NULL) || (mCapacity == -1))
2679         return false;
2680 
2681     if (mPhysicalType == MPP_G2D) {
2682         uint32_t srcResolution = mppSource->mSrcImg.w * mppSource->mSrcImg.h;
2683         uint32_t dstResolution = mppSource->mDstImg.w * mppSource->mDstImg.h;
2684 
2685         uint32_t prevRotatedSrcCropBW = mRotatedSrcCropBW;
2686 
2687         if (mppSource->mSrcImg.transform == 0)
2688             mNoRotatedSrcCropBW -= srcResolution;
2689         else
2690             mRotatedSrcCropBW -= srcResolution;
2691 
2692         if ((prevRotatedSrcCropBW > 0) && (mRotatedSrcCropBW == 0))
2693             return true;
2694 
2695         float baseCycles = getRequiredBaseCycles(mppSource->mSrcImg, mppSource->mMidImg);
2696         mUsedBaseCycles -= baseCycles;
2697 
2698         mUsedCapacity = mUsedBaseCycles / mClockKhz;
2699 
2700         MPP_LOGD(eDebugCapacity, "src num: %zu, base cycle is removed: %f, mUsedBaseCycles: %f, mUsedCapacity(%f), srcResolution: %d, dstResolution: %d, rot: %d, mNoRotatedSrcCropBW(%d), mRotatedSrcCropBW(%d)",
2701                 mAssignedSources.size(),
2702                 baseCycles, mUsedBaseCycles, mUsedCapacity, srcResolution, dstResolution,
2703                 mppSource->mSrcImg.transform, mNoRotatedSrcCropBW, mRotatedSrcCropBW);
2704     } else if (mPhysicalType == MPP_MSC) {
2705         exynos_image &src = mppSource->mSrcImg;
2706         exynos_image &dst = mppSource->mDstImg;
2707         uint32_t srcResolution = src.w * src.h;
2708         uint32_t dstResolution = dst.w * dst.h;
2709 
2710         float srcCapacity = (float)srcResolution / getPPC(src, dst, src);
2711         float dstCapacity  = (float)dstResolution  / getPPC(src, dst, dst);
2712 
2713         mUsedCapacity -= max(srcCapacity, dstCapacity);
2714     }
2715 
2716     return false;
2717 }
2718 
resetUsedCapacity()2719 void ExynosMPP::resetUsedCapacity()
2720 {
2721     mUsedCapacity = 0;
2722     mUsedBaseCycles = 0;
2723     mRotatedSrcCropBW = 0;
2724     mNoRotatedSrcCropBW = 0;
2725 }
2726 
updateUsedCapacity()2727 int32_t ExynosMPP::updateUsedCapacity()
2728 {
2729     int32_t ret = NO_ERROR;
2730     if (mCapacity == -1)
2731         return ret;
2732 
2733     float capacity = 0;
2734     mUsedCapacity = 0;
2735 
2736     mRotatedSrcCropBW = 0;
2737     mNoRotatedSrcCropBW = 0;
2738 
2739     if ((mPhysicalType == MPP_G2D) &&
2740         (mAssignedDisplay != NULL) &&
2741         (mAssignedSources.size() > 0)) {
2742         float cycles = 0;
2743 
2744         if (mMaxSrcLayerNum > 1) {
2745             cycles += ((mAssignedDisplay->mXres * mAssignedDisplay->mYres) / G2D_BASE_PPC_COLORFILL);
2746             MPP_LOGD(eDebugCapacity, "\tcolorfill cycles: %f, total cycles: %f",
2747                     ((mAssignedDisplay->mXres * mAssignedDisplay->mYres) / G2D_BASE_PPC_COLORFILL), cycles);
2748         }
2749         for (uint32_t i = 0; i < mAssignedSources.size(); i++) {
2750             uint32_t srcResolution = mAssignedSources[i]->mSrcImg.w * mAssignedSources[i]->mSrcImg.h;
2751             if ((mAssignedSources[i]->mSrcImg.transform & HAL_TRANSFORM_ROT_90) == 0)
2752                 mNoRotatedSrcCropBW += srcResolution;
2753             else
2754                 mRotatedSrcCropBW += srcResolution;
2755         }
2756         MPP_LOGD(eDebugCapacity, "mNoRotatedSrcCropBW(%d), mRotatedSrcCropBW(%d)",
2757                 mNoRotatedSrcCropBW, mRotatedSrcCropBW);
2758         for (uint32_t i = 0; i < mAssignedSources.size(); i++) {
2759             float srcCycles = 0;
2760             uint32_t srcResolution = mAssignedSources[i]->mSrcImg.w * mAssignedSources[i]->mSrcImg.h;
2761             uint32_t dstResolution = mAssignedSources[i]->mMidImg.w * mAssignedSources[i]->mMidImg.h;
2762             uint32_t maxResolution = max(srcResolution, dstResolution);
2763             float PPC = getPPC(mAssignedSources[i]->mSrcImg, mAssignedSources[i]->mMidImg, mAssignedSources[i]->mSrcImg);
2764             srcCycles = maxResolution/PPC;
2765             cycles += srcCycles;
2766 
2767             MPP_LOGD(eDebugCapacity, "Src[%d] cycles: %f, total cycles: %f, PPC: %f, srcResolution: %d, dstResolution: %d, rot(%d)",
2768                     i, srcCycles, cycles, PPC, srcResolution, dstResolution, mAssignedSources[i]->mSrcImg.transform);
2769         }
2770 
2771         mUsedBaseCycles = cycles;
2772         capacity = cycles / mClockKhz;
2773 
2774         mUsedCapacity = capacity;
2775 
2776     }
2777     MPP_LOGD(eDebugCapacity, "assigned layer size(%zu), mUsedCapacity: %f", mAssignedSources.size(), mUsedCapacity);
2778 
2779     return mUsedCapacity;
2780 }
2781 
getRestrictionClassification(const struct exynos_image & img) const2782 uint32_t ExynosMPP::getRestrictionClassification(const struct exynos_image &img) const {
2783     return !!(isFormatRgb(img.format) == false);
2784 }
2785 
prioritize(int priority)2786 int ExynosMPP::prioritize(int priority)
2787 {
2788     if ((mPhysicalType != MPP_G2D) ||
2789         (mAcrylicHandle == NULL)) {
2790         MPP_LOGE("invalid function call");
2791         return -1;
2792     }
2793     int ret = NO_ERROR;
2794     ret = mAcrylicHandle->prioritize(priority);
2795 
2796     if ((priority > 0) && (ret == 1))
2797     {
2798         /* G2D Driver returned EBUSY */
2799         mHWBusyFlag = true;
2800     }
2801     MPP_LOGD(eDebugMPP, "set resource prioritize (%d), ret(%d), mHWBusyFlag(%d)", priority, ret, mHWBusyFlag);
2802 
2803     return ret;
2804 }
2805 
increaseDstBuffIndex()2806 uint32_t ExynosMPP::increaseDstBuffIndex()
2807 {
2808     if (mAllocOutBufFlag)
2809         mCurrentDstBuf = (mCurrentDstBuf + 1) % NUM_MPP_DST_BUFS(mLogicalType);
2810     return mCurrentDstBuf;
2811 }
2812 
reloadResourceForHWFC()2813 void ExynosMPP::reloadResourceForHWFC()
2814 {
2815     ALOGI("reloadResourceForHWFC()");
2816     delete mAcrylicHandle;
2817     mAcrylicHandle = AcrylicFactory::createAcrylic("default_compositor");
2818     if (mAcrylicHandle == NULL) {
2819         MPP_LOGE("Fail to allocate compositor");
2820     } else {
2821         mAcrylicHandle->setDefaultColor(0, 0, 0, 0);
2822         MPP_LOGI("The resource is reloaded for HWFC: %p", mAcrylicHandle);
2823     }
2824     for (uint32_t i = 0; i < NUM_MPP_SRC_BUFS; i++)
2825     {
2826         if (mSrcImgs[i].mppLayer != NULL) {
2827             delete mSrcImgs[i].mppLayer;
2828             mSrcImgs[i].mppLayer = NULL;
2829         }
2830     }
2831 }
2832 
setTargetDisplayLuminance(uint16_t min,uint16_t max)2833 void ExynosMPP::setTargetDisplayLuminance(uint16_t min, uint16_t max)
2834 {
2835     MPP_LOGD(eDebugMPP, "%s: min(%d), max(%d)", __func__, min, max);
2836     if (mAcrylicHandle == NULL) {
2837         MPP_LOGE("mAcrylicHandle is NULL");
2838     } else
2839         mAcrylicHandle->setTargetDisplayLuminance(min, max);
2840 }
2841 
setTargetDisplayDevice(int device)2842 void ExynosMPP::setTargetDisplayDevice(int device)
2843 {
2844     ALOGI("%s: device(%d)", __func__, device);
2845     if (mAcrylicHandle == NULL) {
2846         MPP_LOGE("mAcrylicHandle is NULL");
2847     } else
2848         mAcrylicHandle->setTargetDisplayInfo(&device);
2849 }
2850 
dump(String8 & result)2851 void ExynosMPP::dump(String8& result)
2852 {
2853     int32_t assignedDisplayType = -1;
2854     if (mAssignedDisplay != NULL)
2855         assignedDisplayType = mAssignedDisplay->mType;
2856 
2857     result.appendFormat("%s: types mppType(%d), (p:%d, l:0x%2x), indexs(p:%d, l:%d), preAssignDisplay(0x%2x)\n",
2858             mName.string(), mMPPType, mPhysicalType, mLogicalType, mPhysicalIndex, mLogicalIndex, mPreAssignDisplayInfo);
2859     result.appendFormat("\tEnable: %d, HWState: %d, AssignedState: %d, assignedDisplay(%d)\n",
2860             mEnable, mHWState, mAssignedState, assignedDisplayType);
2861     result.appendFormat("\tPrevAssignedState: %d, PrevAssignedDisplayType: %d, ReservedDisplay: %d\n",
2862             mPrevAssignedState, mPrevAssignedDisplayType, mReservedDisplay);
2863     result.appendFormat("\tassinedSourceNum(%zu), Capacity(%f), CapaUsed(%f), mCurrentDstBuf(%d)\n",
2864             mAssignedSources.size(), mCapacity, mUsedCapacity, mCurrentDstBuf);
2865 
2866 }
2867 
closeFences()2868 void ExynosMPP::closeFences()
2869 {
2870     for (uint32_t i = 0; i < mAssignedSources.size(); i++)
2871     {
2872         mSrcImgs[i].acrylicAcquireFenceFd =
2873             fence_close(mSrcImgs[i].acrylicAcquireFenceFd, mAssignedDisplay,
2874                     FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_G2D);
2875         mSrcImgs[i].acrylicReleaseFenceFd =
2876             fence_close(mSrcImgs[i].acrylicReleaseFenceFd, mAssignedDisplay,
2877                     FENCE_TYPE_SRC_RELEASE, FENCE_IP_G2D);
2878     }
2879 
2880     mDstImgs[mCurrentDstBuf].acrylicAcquireFenceFd =
2881         fence_close(mDstImgs[mCurrentDstBuf].acrylicAcquireFenceFd, mAssignedDisplay,
2882                 FENCE_TYPE_DST_ACQUIRE, FENCE_IP_G2D);
2883     mDstImgs[mCurrentDstBuf].acrylicReleaseFenceFd =
2884         fence_close(mDstImgs[mCurrentDstBuf].acrylicReleaseFenceFd, mAssignedDisplay,
2885                 FENCE_TYPE_DST_RELEASE, FENCE_IP_G2D);
2886 }
2887 
updateAttr()2888 void ExynosMPP::updateAttr()
2889 {
2890     MPP_LOGD(eDebugAttrSetting, "updateAttr::mPhysicalType(%d), mAttr(0x%" PRIx64 ")",
2891             mPhysicalType, mAttr);
2892 
2893     if (mResourceManager == NULL) return;
2894 
2895     auto iter = mResourceManager->mMPPAttrs.find(mPhysicalType);
2896     if (iter != mResourceManager->mMPPAttrs.end()) {
2897         mAttr = iter->second;
2898         MPP_LOGD(eDebugAttrSetting, "After mAttr(0x%" PRIx64 ")", mAttr);
2899     }
2900 }
2901 
2902