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