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