blob: 794c430a9d236f4d409500d2381543b41828b4e9 [file] [log] [blame]
/*
* Copyright (C) 2012 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Project HWC 2.0 Design
*/
#define ATRACE_TAG (ATRACE_TAG_GRAPHICS | ATRACE_TAG_HAL)
#include <utils/Errors.h>
#include <sync/sync.h>
#include <sys/mman.h>
#include <cutils/properties.h>
#include "ExynosMPP.h"
#include "ExynosResourceRestriction.h"
#include <hardware/hwcomposer_defs.h>
#include <math.h>
#include "VendorGraphicBuffer.h"
#include "ExynosHWCDebug.h"
#include "ExynosDisplay.h"
#include "ExynosVirtualDisplay.h"
#include "ExynosLayer.h"
#include "ExynosHWCHelper.h"
#include "exynos_sync.h"
#include "ExynosResourceManager.h"
/**
* ExynosMPP implementation
*
* Abstraction class for HW Resource
*/
using namespace android;
using namespace vendor::graphics;
int ExynosMPP::mainDisplayWidth = 0;
int ExynosMPP::mainDisplayHeight = 0;
extern struct exynos_hwc_control exynosHWCControl;
#ifndef USE_MODULE_ATTR
extern feature_support_t feature_table[];
#endif
void dumpExynosMPPImgInfo(uint32_t type, exynos_mpp_img_info &imgInfo)
{
HDEBUGLOGD(type, "\tbuffer: %p, bufferType: %d",
imgInfo.bufferHandle, imgInfo.bufferType);
}
bool exynosMPPSourceComp(const ExynosMPPSource* l, const ExynosMPPSource* r)
{
if (l == NULL || r == NULL) {
HWC_LOGE(NULL,"exynosMPP compare error");
return 0;
}
return (l->mSrcImg.zOrder < r->mSrcImg.zOrder);
}
void dump(const restriction_size_t &restrictionSize, String8 &result) {
result.appendFormat(" maxDownScale = %u, maxUpscale = %u\n", restrictionSize.maxDownScale,
restrictionSize.maxUpScale);
result.appendFormat(" maxFullWidth = %u, maxFullHeight = %u\n", restrictionSize.maxFullWidth,
restrictionSize.maxFullHeight);
result.appendFormat(" minFullWidth = %u, minFullHeight = %u\n", restrictionSize.minFullWidth,
restrictionSize.minFullHeight);
result.appendFormat(" fullWidthAlign = %u, fullHeightAlign = %u\n",
restrictionSize.fullWidthAlign, restrictionSize.fullHeightAlign);
result.appendFormat(" maxCropWidth = %u, maxCropHeight = %u\n", restrictionSize.maxCropWidth,
restrictionSize.maxCropHeight);
result.appendFormat(" minCropWidth = %u, minCropHeight = %u\n", restrictionSize.minCropWidth,
restrictionSize.minCropHeight);
result.appendFormat(" cropXAlign = %u, cropYAlign = %u\n", restrictionSize.cropXAlign,
restrictionSize.cropYAlign);
result.appendFormat(" cropWidthAlign = %u, cropHeightAlign = %u\n",
restrictionSize.cropWidthAlign, restrictionSize.cropHeightAlign);
}
ExynosMPPSource::ExynosMPPSource()
: mSourceType(MPP_SOURCE_NO_TYPE),
mSource(NULL),
mOtfMPP(NULL),
mM2mMPP(NULL)
{
memset(&mSrcImg, 0, sizeof(mSrcImg));
mSrcImg.acquireFenceFd = -1;
mSrcImg.releaseFenceFd = -1;
memset(&mDstImg, 0, sizeof(mDstImg));
mDstImg.acquireFenceFd = -1;
mDstImg.releaseFenceFd = -1;
memset(&mMidImg, 0, sizeof(mMidImg));
mMidImg.acquireFenceFd = -1;
mMidImg.releaseFenceFd = -1;
}
ExynosMPPSource::ExynosMPPSource(uint32_t sourceType, void *source)
: mSourceType(sourceType),
mSource(source),
mOtfMPP(NULL),
mM2mMPP(NULL)
{
memset(&mSrcImg, 0, sizeof(mSrcImg));
mSrcImg.acquireFenceFd = -1;
mSrcImg.releaseFenceFd = -1;
memset(&mDstImg, 0, sizeof(mDstImg));
mDstImg.acquireFenceFd = -1;
mDstImg.releaseFenceFd = -1;
memset(&mMidImg, 0, sizeof(mMidImg));
mMidImg.acquireFenceFd = -1;
mMidImg.releaseFenceFd = -1;
}
void ExynosMPPSource::setExynosImage(exynos_image src_img, exynos_image dst_img)
{
mSrcImg = src_img;
mDstImg = dst_img;
}
void ExynosMPPSource::setExynosMidImage(exynos_image mid_img)
{
mMidImg = mid_img;
}
ExynosMPP::ExynosMPP(ExynosResourceManager* resourceManager,
uint32_t physicalType, uint32_t logicalType, const char *name,
uint32_t physicalIndex, uint32_t logicalIndex, uint32_t preAssignInfo)
: mResourceManager(resourceManager),
mMPPType(MPP_TYPE_NONE),
mPhysicalType(physicalType),
mLogicalType(logicalType),
mName(name),
mPhysicalIndex(physicalIndex),
mLogicalIndex(logicalIndex),
mPreAssignDisplayInfo(preAssignInfo),
mHWState(MPP_HW_STATE_IDLE),
mLastStateFenceFd(-1),
mAssignedState(MPP_ASSIGN_STATE_FREE),
mEnable(true),
mAssignedDisplay(NULL),
mMaxSrcLayerNum(1),
mPrevAssignedState(MPP_ASSIGN_STATE_FREE),
mPrevAssignedDisplayType(-1),
mReservedDisplay(-1),
mResourceManageThread(this),
mCapacity(-1),
mUsedCapacity(0),
mAllocOutBufFlag(true),
mFreeOutBufFlag(true),
mHWBusyFlag(false),
mCurrentDstBuf(0),
mPrivDstBuf(-1),
mNeedCompressedTarget(false),
mDstAllocatedSize(DST_SIZE_UNKNOWN),
mUseM2MSrcFence(false),
mAttr(0),
mNeedSolidColorLayer(false)
{
if (mPhysicalType < MPP_DPP_NUM) {
mClockKhz = VPP_CLOCK;
mPPC = VPP_PIXEL_PER_CLOCK;
}
if (mPhysicalType == MPP_G2D) {
mClockKhz = G2D_CLOCK;
if (mLogicalType == MPP_LOGICAL_G2D_RGB) {
char value[256];
int afbc_prop;
property_get("ro.vendor.ddk.set.afbc", value, "0");
afbc_prop = atoi(value);
if (afbc_prop == 0)
mNeedCompressedTarget = false;
else
mNeedCompressedTarget = true;
mMaxSrcLayerNum = G2D_MAX_SRC_NUM;
} else if (mLogicalType == MPP_LOGICAL_G2D_COMBO &&
(mPreAssignDisplayInfo & HWC_DISPLAY_VIRTUAL_BIT)) {
mMaxSrcLayerNum = G2D_MAX_SRC_NUM - 1;
mAllocOutBufFlag = false;
mNeedCompressedTarget = false;
mUseM2MSrcFence = true;
}
/* Capacity means time(ms) that can be used for operation */
mCapacity = MPP_G2D_CAPACITY;
mAcrylicHandle = AcrylicFactory::createAcrylic("default_compositor");
if (mAcrylicHandle == NULL) {
MPP_LOGE("Fail to allocate acrylic handle");
abort();
} else {
MPP_LOGI("mAcrylicHandle is created: %p", mAcrylicHandle);
}
}
/* Basic feature supported flags */
for (const auto &feature: feature_table) {
if (feature.hwType == mPhysicalType)
mAttr = feature.attr;
}
if (mPhysicalType == MPP_MSC) {
mClockKhz = MSC_CLOCK;
/* To do
* Capacity should be set
*/
mCapacity = MPP_MSC_CAPACITY;
mAcrylicHandle = AcrylicFactory::createAcrylic("default_scaler");
if (mAcrylicHandle == NULL) {
MPP_LOGE("Fail to allocate acrylic handle");
abort();
} else {
MPP_LOGI("mAcrylicHandle is created: %p", mAcrylicHandle);
}
}
if (mMaxSrcLayerNum > 1) {
mNeedSolidColorLayer = true;
mAcrylicHandle->setDefaultColor(0, 0, 0, 0);
}
mAssignedSources.clear();
resetUsedCapacity();
mResourceManageThread.mRunning = true;
mResourceManageThread.run("MPPThread");
memset(&mPrevFrameInfo, 0, sizeof(mPrevFrameInfo));
for (int i = 0; i < NUM_MPP_SRC_BUFS; i++) {
mPrevFrameInfo.srcInfo[i].acquireFenceFd = -1;
mPrevFrameInfo.srcInfo[i].releaseFenceFd = -1;
mPrevFrameInfo.dstInfo[i].acquireFenceFd = -1;
mPrevFrameInfo.dstInfo[i].releaseFenceFd = -1;
}
for (uint32_t i = 0; i < NUM_MPP_SRC_BUFS; i++) {
memset(&mSrcImgs[i], 0, sizeof(mSrcImgs[i]));
mSrcImgs[i].acrylicAcquireFenceFd = -1;
mSrcImgs[i].acrylicReleaseFenceFd = -1;
}
for (uint32_t i = 0; i < NUM_MPP_DST_BUFS(mLogicalType); i++) {
memset(&mDstImgs[i], 0, sizeof(mDstImgs[i]));
mDstImgs[i].acrylicAcquireFenceFd = -1;
mDstImgs[i].acrylicReleaseFenceFd = -1;
}
for (uint32_t i = 0; i < DISPLAY_MODE_NUM; i++)
{
mPreAssignDisplayList[i] = (preAssignInfo >> (DISPLAY_MODE_MASK_LEN * i)) & DISPLAY_MODE_MASK_BIT;
}
}
ExynosMPP::~ExynosMPP()
{
mResourceManageThread.mRunning = false;
mResourceManageThread.requestExitAndWait();
}
ExynosMPP::ResourceManageThread::ResourceManageThread(ExynosMPP *exynosMPP)
: mExynosMPP(exynosMPP),
mRunning(false)
{
}
ExynosMPP::ResourceManageThread::~ResourceManageThread()
{
}
bool ExynosMPP::isDataspaceSupportedByMPP(struct exynos_image &src, struct exynos_image &dst)
{
uint32_t srcStandard = (src.dataSpace & HAL_DATASPACE_STANDARD_MASK);
uint32_t dstStandard = (dst.dataSpace & HAL_DATASPACE_STANDARD_MASK);
uint32_t srcTransfer = (src.dataSpace & HAL_DATASPACE_TRANSFER_MASK);
uint32_t dstTransfer = (dst.dataSpace & HAL_DATASPACE_TRANSFER_MASK);
/* No conversion case */
if ((srcStandard == dstStandard) && (srcTransfer == dstTransfer))
return true;
/* Unspecified conversion case */
if (((srcStandard == HAL_DATASPACE_STANDARD_UNSPECIFIED) ||
(dstStandard == HAL_DATASPACE_STANDARD_UNSPECIFIED)) &&
((srcTransfer == HAL_DATASPACE_TRANSFER_UNSPECIFIED) ||
(dstTransfer == HAL_DATASPACE_TRANSFER_UNSPECIFIED)))
return true;
/* WCG support check */
/* 'Src is not HDR' and 'src,dst has differenct dataspace' means WCG case */
/* Some MPPs are only support HDR but WCG */
if (!hasHdrInfo(src) && ((mAttr & MPP_ATTR_WCG) == 0))
return false;
/* Standard support check */
auto standard_it = dataspace_standard_map.find(srcStandard);
if ((standard_it == dataspace_standard_map.end()) ||
((mAttr & standard_it->second) == 0))
return false;
/* Transfer support check */
auto transfer_it = dataspace_transfer_map.find(srcTransfer);
if ((transfer_it == dataspace_transfer_map.end()) ||
((mAttr & transfer_it->second) == 0))
return false;
return checkCSCRestriction(src, dst);
}
bool ExynosMPP::isSupportedHDR10Plus(struct exynos_image &src, struct exynos_image &dst)
{
uint32_t srcStandard = (src.dataSpace & HAL_DATASPACE_STANDARD_MASK);
uint32_t dstStandard = (dst.dataSpace & HAL_DATASPACE_STANDARD_MASK);
uint32_t srcTransfer = (src.dataSpace & HAL_DATASPACE_TRANSFER_MASK);
uint32_t dstTransfer = (dst.dataSpace & HAL_DATASPACE_TRANSFER_MASK);
if (hasHdr10Plus(src)) {
if (mAttr & MPP_ATTR_HDR10PLUS)
return true;
else if ((srcStandard == dstStandard) && (srcTransfer == dstTransfer))
return true;
else if ((mLogicalType == MPP_LOGICAL_G2D_COMBO) && (mPreAssignDisplayInfo & HWC_DISPLAY_VIRTUAL_BIT))
return true;
else
return false;
}
return true;
}
bool ExynosMPP::isSupportedHStrideCrop(struct exynos_image __unused &src)
{
return true;
}
bool ExynosMPP::isSupportedBlend(struct exynos_image &src)
{
switch(src.blending) {
case HWC2_BLEND_MODE_NONE:
case HWC2_BLEND_MODE_PREMULTIPLIED:
case HWC2_BLEND_MODE_COVERAGE:
return true;
default:
return false;
}
}
bool ExynosMPP::checkRotationCondition(struct exynos_image &src)
{
/* Check only DPP types */
if (mPhysicalType >= MPP_DPP_NUM)
return true;
/* If DPP has their own restriction, implmemnt module codes */
if (mAttr & MPP_ATTR_ROT_90) {
if (isFormatYUV420(src.format) == true)
return true;
}
/* Other DPPs */
if ((src.transform & HAL_TRANSFORM_ROT_90) == 0)
{
if ((src.compressed == 1) && (src.transform != 0))
return false;
return true;
} else {
return false;
}
return true;
}
bool ExynosMPP::isSupportedTransform(struct exynos_image &src)
{
if (src.transform == 0) return true;
/* If MPP need to check additional condition,
* implement checkRotationCondition function to check it */
/* For example, DPP need to check custom conditons */
if (!checkRotationCondition(src))
return false;
for(auto transform_map : transform_map_table) {
if (src.transform & transform_map.hal_tr) {
if (!(mAttr & transform_map.hwc_tr))
return false;
}
}
return true;
}
bool ExynosMPP::isSupportedCompression(struct exynos_image &src)
{
if (src.compressed) {
if (mAttr & MPP_ATTR_AFBC)
return true;
else
return false;
} else {
return true;
}
}
bool ExynosMPP::isSupportedCapability(ExynosDisplay &display, struct exynos_image &src)
{
if (display.mType != HWC_DISPLAY_EXTERNAL)
return true;
if (!(mAttr & MPP_ATTR_USE_CAPA))
return true;
if (mResourceManager->hasHdrLayer || mResourceManager->hasDrmLayer) {
if (getDrmMode(src.usageFlags) != NO_DRM)
return true;
else if (hasHdrInfo(src))
return true;
else
return false;
}
return true;
}
bool ExynosMPP::isSupportedDRM(struct exynos_image &src)
{
if (getDrmMode(src.usageFlags) == NO_DRM)
return true;
if (mLogicalType == MPP_LOGICAL_G2D_RGB)
return false;
return true;
}
bool ExynosMPP::checkCSCRestriction(struct exynos_image &src, struct exynos_image &dst)
{
return true;
}
bool ExynosMPP::isDimLayerSupported()
{
if (mAttr & MPP_ATTR_DIM)
return true;
return false;
}
bool ExynosMPP::isSrcFormatSupported(struct exynos_image &src)
{
if (mLogicalType == MPP_LOGICAL_G2D_YUV) {
/* Support YUV layer and HDR RGB layer */
if (isFormatRgb(src.format) && (hasHdrInfo(src) == false))
return false;
}
if ((mLogicalType == MPP_LOGICAL_G2D_RGB) &&
isFormatYUV(src.format))
return false;
if ((mLogicalType == MPP_LOGICAL_MSC_YUV) &&
isFormatRgb(src.format)) {
return false;
}
if (mResourceManager == NULL) return false;
for (uint32_t i = 0 ; i < mResourceManager->mFormatRestrictionCnt; i++) {
if ((mResourceManager->mFormatRestrictions[i].hwType == mPhysicalType) &&
((mResourceManager->mFormatRestrictions[i].nodeType == NODE_NONE) ||
(mResourceManager->mFormatRestrictions[i].nodeType == NODE_SRC)) &&
(mResourceManager->mFormatRestrictions[i].format == src.format))
return true;
}
return false;
}
bool ExynosMPP::isDstFormatSupported(struct exynos_image &dst)
{
for (uint32_t i = 0 ; i < mResourceManager->mFormatRestrictionCnt; i++) {
if ((mResourceManager->mFormatRestrictions[i].hwType == mPhysicalType) &&
((mResourceManager->mFormatRestrictions[i].nodeType == NODE_NONE) ||
(mResourceManager->mFormatRestrictions[i].nodeType == NODE_DST)) &&
(mResourceManager->mFormatRestrictions[i].format == dst.format))
return true;
}
return false;
}
uint32_t ExynosMPP::getMaxUpscale(const struct exynos_image &src,
const struct exynos_image __unused &dst) const {
uint32_t idx = getRestrictionClassification(src);
return mSrcSizeRestrictions[idx].maxUpScale;
}
bool ExynosMPP::checkDownscaleCap(const float resolution, const float scaleRatio_H,
const float scaleRatio_V, const float displayRatio_H) const {
if (mPhysicalType >= MPP_DPP_NUM) return true;
return float(mClockKhz) * 1000.0 >=
((resolution * VPP_RESOL_CLOCK_FACTOR * scaleRatio_H * scaleRatio_V * VPP_DISP_FACTOR) /
mPPC * displayRatio_H);
}
uint32_t ExynosMPP::getDownscaleRestriction(const struct exynos_image &src,
const struct exynos_image & /*dst*/) const {
auto idx = getRestrictionClassification(src);
return mDstSizeRestrictions[idx].maxDownScale;
}
uint32_t ExynosMPP::getMaxDownscale(const ExynosDisplay &display, const struct exynos_image &src,
const struct exynos_image &dst) const {
uint32_t maxDownscale = getDownscaleRestriction(src, dst);
if (maxDownscale <= 1) {
return maxDownscale;
}
if (mPhysicalType < MPP_DPP_NUM) {
const bool isPerpendicular = !!(src.transform & HAL_TRANSFORM_ROT_90);
float scaleRatio_H = 1;
float scaleRatio_V = 1;
if (isPerpendicular) {
scaleRatio_H = float(src.w) / float(dst.h);
scaleRatio_V = float(src.h) / float(dst.w);
} else {
scaleRatio_H = float(src.w) / float(dst.w);
scaleRatio_V = float(src.h) / float(dst.h);
}
float dstW = float(dst.w);
float displayW = float(display.mXres);
float displayH = float(display.mYres);
float resolution = displayW * displayH;
scaleRatio_H = std::min(scaleRatio_H, float(maxDownscale));
scaleRatio_V = std::min(scaleRatio_V, float(maxDownscale));
if (!checkDownscaleCap(resolution, scaleRatio_H, scaleRatio_V, dstW / displayW)) {
return 1;
}
}
return maxDownscale;
}
uint32_t ExynosMPP::getSrcXOffsetAlign(struct exynos_image &src)
{
/* Refer module(ExynosMPPModule) for chip specific restrictions */
uint32_t idx = getRestrictionClassification(src);
if ((mPhysicalType == MPP_MSC) &&
((src.format == HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_S10B) ||
(src.format == HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_S10B))) {
return 16;
}
return mSrcSizeRestrictions[idx].cropXAlign;
}
uint32_t ExynosMPP::getSrcXOffsetAlign(uint32_t idx)
{
if (idx >= RESTRICTION_MAX)
{
MPP_LOGE("invalid idx: %d", idx);
return 16;
}
return mSrcSizeRestrictions[idx].cropXAlign;
}
uint32_t ExynosMPP::getSrcYOffsetAlign(struct exynos_image &src)
{
uint32_t idx = getRestrictionClassification(src);
return mSrcSizeRestrictions[idx].cropYAlign;
}
uint32_t ExynosMPP::getSrcYOffsetAlign(uint32_t idx)
{
if (idx >= RESTRICTION_MAX)
{
MPP_LOGE("invalid idx: %d", idx);
return 16;
}
return mSrcSizeRestrictions[idx].cropYAlign;
}
uint32_t ExynosMPP::getSrcWidthAlign(struct exynos_image &src)
{
uint32_t idx = getRestrictionClassification(src);
return mSrcSizeRestrictions[idx].fullWidthAlign;
}
uint32_t ExynosMPP::getSrcHeightAlign(struct exynos_image &src)
{
uint32_t idx = getRestrictionClassification(src);
return mSrcSizeRestrictions[idx].fullHeightAlign;
}
uint32_t ExynosMPP::getSrcMaxWidth(struct exynos_image &src)
{
if (isFormatYUV(src.format))
return 4096;
uint32_t idx = getRestrictionClassification(src);
return mSrcSizeRestrictions[idx].maxFullWidth;
}
uint32_t ExynosMPP::getSrcMaxHeight(struct exynos_image &src)
{
if (isFormatYUV(src.format))
return 4096;
uint32_t idx = getRestrictionClassification(src);
return mSrcSizeRestrictions[idx].maxFullHeight;
}
uint32_t ExynosMPP::getSrcMinWidth(struct exynos_image &src)
{
uint32_t idx = getRestrictionClassification(src);
return mSrcSizeRestrictions[idx].minFullWidth;
}
uint32_t ExynosMPP::getSrcMinWidth(uint32_t idx)
{
if (idx >= RESTRICTION_MAX)
{
MPP_LOGE("invalid idx: %d", idx);
return 16;
}
return mSrcSizeRestrictions[idx].minFullWidth;
}
uint32_t ExynosMPP::getSrcMinHeight(struct exynos_image &src)
{
uint32_t idx = getRestrictionClassification(src);
return mSrcSizeRestrictions[idx].minFullHeight;
}
uint32_t ExynosMPP::getSrcMinHeight(uint32_t idx)
{
if (idx >= RESTRICTION_MAX)
{
MPP_LOGE("invalid idx: %d", idx);
return 16;
}
return mSrcSizeRestrictions[idx].minFullHeight;
}
uint32_t ExynosMPP::getSrcMaxCropWidth(struct exynos_image &src)
{
uint32_t idx = getRestrictionClassification(src);
return mSrcSizeRestrictions[idx].maxCropWidth;
}
uint32_t ExynosMPP::getSrcMaxCropHeight(struct exynos_image &src)
{
if ((mMPPType == MPP_TYPE_OTF) &&
(src.transform & HAL_TRANSFORM_ROT_90))
return 2160;
uint32_t idx = getRestrictionClassification(src);
return mSrcSizeRestrictions[idx].maxCropHeight;
}
uint32_t ExynosMPP::getSrcMaxCropSize(struct exynos_image &src)
{
return (getSrcMaxCropWidth(src) * getSrcMaxCropHeight(src));
}
uint32_t ExynosMPP::getSrcMinCropWidth(struct exynos_image &src)
{
if (((src.format == HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_S10B) ||
(src.format == HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_S10B)) &&
(mPhysicalType == MPP_G2D))
return 2;
uint32_t idx = getRestrictionClassification(src);
return mSrcSizeRestrictions[idx].minCropWidth;
}
uint32_t ExynosMPP::getSrcMinCropHeight(struct exynos_image &src)
{
if (((src.format == HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_S10B) ||
(src.format == HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_S10B)) &&
(mPhysicalType == MPP_G2D))
return 2;
uint32_t idx = getRestrictionClassification(src);
return mSrcSizeRestrictions[idx].minCropHeight;
}
uint32_t ExynosMPP::getSrcCropWidthAlign(const struct exynos_image &src) const {
if (((src.format == HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_S10B) ||
(src.format == HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_S10B)) &&
(mPhysicalType == MPP_G2D))
return 2;
uint32_t idx = getRestrictionClassification(src);
return mSrcSizeRestrictions[idx].cropWidthAlign;
}
/* This is used for only otfMPP */
uint32_t ExynosMPP::getSrcCropWidthAlign(uint32_t idx) const {
if (idx >= RESTRICTION_MAX)
{
MPP_LOGE("invalid idx: %d", idx);
return 16;
}
return mSrcSizeRestrictions[idx].cropWidthAlign;
}
uint32_t ExynosMPP::getSrcCropHeightAlign(const struct exynos_image &src) const {
if (((src.format == HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_S10B) ||
(src.format == HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_S10B)) &&
(mPhysicalType == MPP_G2D))
return 2;
uint32_t idx = getRestrictionClassification(src);
return mSrcSizeRestrictions[idx].cropHeightAlign;
}
/* This is used for only otfMPP */
uint32_t ExynosMPP::getSrcCropHeightAlign(uint32_t idx) const {
if (idx >= RESTRICTION_MAX)
{
MPP_LOGE("invalid idx: %d", idx);
return 16;
}
return mSrcSizeRestrictions[idx].cropHeightAlign;
}
uint32_t ExynosMPP::getDstMaxWidth(struct exynos_image &dst)
{
uint32_t idx = getRestrictionClassification(dst);
return mDstSizeRestrictions[idx].maxCropWidth;
}
uint32_t ExynosMPP::getDstMaxHeight(struct exynos_image &dst)
{
uint32_t idx = getRestrictionClassification(dst);
return mDstSizeRestrictions[idx].maxCropHeight;
}
uint32_t ExynosMPP::getDstMinWidth(struct exynos_image &dst)
{
if (((dst.format == HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_S10B) ||
(dst.format == HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_S10B)) &&
(mPhysicalType == MPP_G2D))
return 64;
if ((mNeedSolidColorLayer == false) && mNeedCompressedTarget)
return 16;
if ((mPhysicalType == MPP_G2D) && (mNeedSolidColorLayer == false) &&
isFormatSBWC(dst.format))
return 32;
uint32_t idx = getRestrictionClassification(dst);
return mDstSizeRestrictions[idx].minCropWidth;
}
uint32_t ExynosMPP::getDstMinHeight(struct exynos_image &dst)
{
if ((mNeedSolidColorLayer == false) && mNeedCompressedTarget)
return 16;
if ((mPhysicalType == MPP_G2D) && (mNeedSolidColorLayer == false) &&
isFormatSBWC(dst.format))
return 8;
uint32_t idx = getRestrictionClassification(dst);
return mDstSizeRestrictions[idx].minCropHeight;
}
uint32_t ExynosMPP::getDstWidthAlign(const struct exynos_image &dst) const {
if (((dst.format == HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_S10B) ||
(dst.format == HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_S10B)) &&
(mPhysicalType == MPP_G2D))
return 64;
if ((mNeedSolidColorLayer == false) && mNeedCompressedTarget)
return 16;
if ((mPhysicalType == MPP_G2D) && (mNeedSolidColorLayer == false) &&
isFormatSBWC(dst.format))
return 32;
uint32_t idx = getRestrictionClassification(dst);
return mDstSizeRestrictions[idx].cropWidthAlign;
}
uint32_t ExynosMPP::getDstHeightAlign(const struct exynos_image &dst) const {
if ((mNeedSolidColorLayer == false) && mNeedCompressedTarget)
return 16;
if ((mPhysicalType == MPP_G2D) && (mNeedSolidColorLayer == false) &&
isFormatSBWC(dst.format))
return 8;
uint32_t idx = getRestrictionClassification(dst);
return mDstSizeRestrictions[idx].cropHeightAlign;
}
uint32_t ExynosMPP::getDstXOffsetAlign(struct exynos_image &dst)
{
if ((mNeedSolidColorLayer == false) && mNeedCompressedTarget)
return 16;
if ((mPhysicalType == MPP_G2D) && (mNeedSolidColorLayer == false) &&
isFormatSBWC(dst.format))
return 32;
uint32_t idx = getRestrictionClassification(dst);
return mDstSizeRestrictions[idx].cropXAlign;
}
uint32_t ExynosMPP::getDstYOffsetAlign(struct exynos_image &dst)
{
if ((mNeedSolidColorLayer == false) && mNeedCompressedTarget)
return 16;
if ((mPhysicalType == MPP_G2D) && (mNeedSolidColorLayer == false) &&
isFormatSBWC(dst.format))
return 8;
uint32_t idx = getRestrictionClassification(dst);
return mDstSizeRestrictions[idx].cropYAlign;
}
uint32_t ExynosMPP::getOutBufAlign()
{
if (mNeedCompressedTarget)
return 16;
else
return 1;
}
int32_t ExynosMPP::isSupportLayerColorTransform(
struct exynos_image &src, struct exynos_image __unused &dst)
{
if (src.needColorTransform == false)
return true;
if (mAttr & MPP_ATTR_LAYER_TRANSFORM)
return true;
return false;
}
bool ExynosMPP::ResourceManageThread::threadLoop()
{
if (mExynosMPP == NULL)
return false;
ALOGI("%s threadLoop is started", mExynosMPP->mName.string());
while(mRunning) {
Mutex::Autolock lock(mMutex);
while((mFreedBuffers.size() == 0) &&
(mStateFences.size() == 0)) {
mCondition.wait(mMutex);
}
if ((mExynosMPP->mHWState == MPP_HW_STATE_RUNNING) &&
(mStateFences.size() != 0)) {
if (checkStateFences()) {
mExynosMPP->mHWState = MPP_HW_STATE_IDLE;
}
} else {
if ((mStateFences.size() != 0) &&
(mExynosMPP->mHWState != MPP_HW_STATE_RUNNING)) {
ALOGW("%s, mHWState(%d) but mStateFences size(%zu)",
mExynosMPP->mName.string(), mExynosMPP->mHWState,
mStateFences.size());
checkStateFences();
}
}
if (mFreedBuffers.size() != 0) {
freeBuffers();
}
}
return true;
}
void ExynosMPP::ResourceManageThread::freeBuffers()
{
VendorGraphicBufferAllocator& gAllocator(VendorGraphicBufferAllocator::get());
android::List<exynos_mpp_img_info >::iterator it;
android::List<exynos_mpp_img_info >::iterator end;
it = mFreedBuffers.begin();
end = mFreedBuffers.end();
uint32_t freebufNum = 0;
while (it != end) {
exynos_mpp_img_info freeBuffer = (exynos_mpp_img_info)(*it);
HDEBUGLOGD(eDebugMPP|eDebugFence|eDebugBuf, "freebufNum: %d, buffer: %p", freebufNum, freeBuffer.bufferHandle);
dumpExynosMPPImgInfo(eDebugMPP|eDebugFence|eDebugBuf, freeBuffer);
if (fence_valid(freeBuffer.acrylicAcquireFenceFd)) {
if (sync_wait(freeBuffer.acrylicAcquireFenceFd, 1000) < 0)
HWC_LOGE(NULL, "%s:: acquire fence sync_wait error", mExynosMPP->mName.string());
freeBuffer.acrylicAcquireFenceFd =
fence_close(freeBuffer.acrylicAcquireFenceFd, mExynosMPP->mAssignedDisplay,
FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_ALL);
}
if (fence_valid(freeBuffer.acrylicReleaseFenceFd)) {
if (sync_wait(freeBuffer.acrylicReleaseFenceFd, 1000) < 0)
HWC_LOGE(NULL, "%s:: release fence sync_wait error", mExynosMPP->mName.string());
freeBuffer.acrylicReleaseFenceFd =
fence_close(freeBuffer.acrylicReleaseFenceFd, mExynosMPP->mAssignedDisplay,
FENCE_TYPE_SRC_RELEASE, FENCE_IP_ALL);
}
gAllocator.free(freeBuffer.bufferHandle);
it = mFreedBuffers.erase(it);
}
}
bool ExynosMPP::ResourceManageThread::checkStateFences()
{
bool ret = true;
android::List<int >::iterator it;
android::List<int >::iterator end;
it = mStateFences.begin();
end = mStateFences.end();
uint32_t waitFenceNum = 0;
while (it != end) {
int fence = (int)(*it);
HDEBUGLOGD(eDebugMPP|eDebugFence, "%d wait fence: %d", waitFenceNum, fence);
waitFenceNum++;
if (fence_valid(fence)) {
if (sync_wait(fence, 5000) < 0) {
HWC_LOGE(NULL, "%s::[%s][%d] sync_wait(%d) error(%s)", __func__,
mExynosMPP->mName.string(), mExynosMPP->mLogicalIndex, fence, strerror(errno));
ret = false;
}
fence = fence_close(fence, mExynosMPP->mAssignedDisplay,
FENCE_TYPE_ALL, FENCE_IP_ALL);
}
it = mStateFences.erase(it);
}
return ret;
}
void ExynosMPP::ResourceManageThread::addFreedBuffer(exynos_mpp_img_info freedBuffer)
{
android::Mutex::Autolock lock(mMutex);
mFreedBuffers.push_back(freedBuffer);
mCondition.signal();
}
void ExynosMPP::ResourceManageThread::addStateFence(int fence)
{
Mutex::Autolock lock(mMutex);
HDEBUGLOGD(eDebugMPP|eDebugFence, "wait fence is added: %d", fence);
mStateFences.push_back(fence);
mCondition.signal();
}
/**
* @param w
* @param h
* @param color
* @param usage
* @return int32_t
*/
int32_t ExynosMPP::allocOutBuf(uint32_t w, uint32_t h, uint32_t format, uint64_t usage, uint32_t index) {
ATRACE_CALL();
uint32_t dstStride = 0;
MPP_LOGD(eDebugMPP|eDebugBuf, "index: %d++++++++", index);
if (index >= NUM_MPP_DST_BUFS(mLogicalType)) {
return -EINVAL;
}
exynos_mpp_img_info freeDstBuf = mDstImgs[index];
MPP_LOGD(eDebugMPP|eDebugBuf, "mDstImg[%d] is reallocated", index);
dumpExynosMPPImgInfo(eDebugMPP, mDstImgs[index]);
uint64_t allocUsage = getBufferUsage(usage);
buffer_handle_t dstBuffer;
MPP_LOGD(eDebugMPP|eDebugBuf, "\tw: %d, h: %d, format: 0x%8x, previousBuffer: %p, allocUsage: 0x%" PRIx64 ", usage: 0x%" PRIx64 "",
w, h, format, freeDstBuf.bufferHandle, allocUsage, usage);
status_t error = NO_ERROR;
{
ATRACE_CALL();
VendorGraphicBufferAllocator& gAllocator(VendorGraphicBufferAllocator::get());
error = gAllocator.allocate(w, h, format, 1, allocUsage, &dstBuffer, &dstStride, "HWC");
}
if ((error != NO_ERROR) || (dstBuffer == NULL)) {
MPP_LOGE("failed to allocate destination buffer(%dx%d): %d", w, h, error);
return -EINVAL;
}
memset(&mDstImgs[index], 0, sizeof(mDstImgs[index]));
mDstImgs[index].acrylicAcquireFenceFd = -1;
mDstImgs[index].acrylicReleaseFenceFd = -1;
mDstImgs[index].bufferHandle = dstBuffer;
mDstImgs[index].bufferType = getBufferType(usage);
mDstImgs[index].format = format;
MPP_LOGD(eDebugMPP|eDebugBuf, "free outbuf[%d] %p", index, freeDstBuf.bufferHandle);
if (freeDstBuf.bufferHandle != NULL)
freeOutBuf(freeDstBuf);
else {
if (mAssignedDisplay != NULL) {
freeDstBuf.acrylicAcquireFenceFd = fence_close(freeDstBuf.acrylicAcquireFenceFd,
mAssignedDisplay, FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_G2D);
freeDstBuf.acrylicReleaseFenceFd = fence_close(freeDstBuf.acrylicReleaseFenceFd,
mAssignedDisplay, FENCE_TYPE_SRC_RELEASE, FENCE_IP_G2D);
}
}
MPP_LOGD(eDebugMPP|eDebugBuf, "dstBuffer(%p)-----------", dstBuffer);
return NO_ERROR;
}
/**
* @param outbuf
* @return int32_t
*/
int32_t ExynosMPP::setOutBuf(buffer_handle_t outbuf, int32_t fence) {
mDstImgs[mCurrentDstBuf].bufferHandle = NULL;
if (outbuf != NULL) {
mDstImgs[mCurrentDstBuf].bufferHandle = outbuf;
mDstImgs[mCurrentDstBuf].format =
VendorGraphicBufferMeta::get_format(mDstImgs[mCurrentDstBuf].bufferHandle);
}
setDstAcquireFence(fence);
return NO_ERROR;
}
/**
* @param dst
* @return int32_t
*/
int32_t ExynosMPP::freeOutBuf(struct exynos_mpp_img_info dst) {
mResourceManageThread.addFreedBuffer(dst);
dst.bufferHandle = NULL;
return NO_ERROR;
}
uint32_t ExynosMPP::getBufferType(uint64_t usage)
{
if (getDrmMode(usage) == SECURE_DRM)
return MPP_BUFFER_SECURE_DRM;
else if (getDrmMode(usage) == NORMAL_DRM)
return MPP_BUFFER_NORMAL_DRM;
else {
if (exynosHWCControl.dumpMidBuf)
return MPP_BUFFER_DUMP;
else
return MPP_BUFFER_NORMAL;
}
}
uint32_t ExynosMPP::getBufferType(const buffer_handle_t handle)
{
uint64_t usage = VendorGraphicBufferMeta::get_usage(handle);
return getBufferType(usage);
}
uint64_t ExynosMPP::getBufferUsage(uint64_t usage)
{
uint64_t allocUsage = 0;
if (getBufferType(usage) == MPP_BUFFER_DUMP) {
allocUsage = BufferUsage::CPU_READ_OFTEN |
BufferUsage::CPU_WRITE_OFTEN;
} else {
allocUsage = BufferUsage::CPU_READ_NEVER |
BufferUsage::CPU_WRITE_NEVER |
VendorGraphicBufferUsage::NOZEROED |
BufferUsage::COMPOSER_OVERLAY;
}
if (getDrmMode(usage) == SECURE_DRM) {
allocUsage |= BufferUsage::PROTECTED;
allocUsage &= ~VendorGraphicBufferUsage::PRIVATE_NONSECURE;
} else if (getDrmMode(usage) == NORMAL_DRM) {
allocUsage |= BufferUsage::PROTECTED;
allocUsage |= VendorGraphicBufferUsage::PRIVATE_NONSECURE;
}
/* HACK: for distinguishing FIMD_VIDEO_region */
if (!((allocUsage & BufferUsage::PROTECTED) &&
!(allocUsage & VendorGraphicBufferUsage::PRIVATE_NONSECURE) &&
!(allocUsage & VendorGraphicBufferUsage::VIDEO_EXT))) {
allocUsage |= (BufferUsage::GPU_TEXTURE | BufferUsage::GPU_RENDER_TARGET);
}
return allocUsage;
}
bool ExynosMPP::needDstBufRealloc(struct exynos_image &dst, uint32_t index)
{
MPP_LOGD(eDebugMPP|eDebugBuf, "index: %d++++++++", index);
if (index >= NUM_MPP_DST_BUFS(mLogicalType)) {
MPP_LOGE("%s:: index(%d) is not valid", __func__, index);
return false;
}
buffer_handle_t dst_handle = NULL;
if (mDstImgs[index].bufferHandle != NULL)
dst_handle = mDstImgs[index].bufferHandle;
if (dst_handle == NULL) {
MPP_LOGD(eDebugMPP|eDebugBuf, "\tDstImag[%d] handle is NULL", index);
return true;
}
int32_t assignedDisplay = -1;
if (mAssignedDisplay != NULL) {
assignedDisplay = mAssignedDisplay->mType;
} else {
MPP_LOGE("%s:: mpp is not assigned", __func__);
return false;
}
VendorGraphicBufferMeta gmeta(dst_handle);
MPP_LOGD(eDebugMPP|eDebugBuf, "\tdst_handle(%p)", dst_handle);
MPP_LOGD(eDebugMPP|eDebugBuf, "\tAssignedDisplay[%d, %d] format[0x%8x, 0x%8x], bufferType[%d, %d], usageFlags: 0x%" PRIx64 "",
mPrevAssignedDisplayType, assignedDisplay, gmeta.format, dst.format,
mDstImgs[index].bufferType, getBufferType(dst.usageFlags), dst.usageFlags);
bool realloc = (mPrevAssignedDisplayType != assignedDisplay) ||
(formatToBpp(gmeta.format) < formatToBpp(dst.format)) ||
((gmeta.stride * gmeta.vstride) < (int)(dst.fullWidth * dst.fullHeight)) ||
(mDstImgs[index].bufferType != getBufferType(dst.usageFlags));
MPP_LOGD(eDebugMPP|eDebugBuf, "realloc: %d--------", realloc);
return realloc;
}
bool ExynosMPP::canUsePrevFrame()
{
if (exynosHWCControl.skipM2mProcessing == false)
return false;
/* virtual display always require composition */
if (mAllocOutBufFlag == false)
return false;
if (mPrevFrameInfo.srcNum != mAssignedSources.size())
return false;
for (uint32_t i = 0; i < mPrevFrameInfo.srcNum; i++) {
if ((mPrevFrameInfo.srcInfo[i].bufferHandle != mAssignedSources[i]->mSrcImg.bufferHandle) ||
(mPrevFrameInfo.srcInfo[i].x != mAssignedSources[i]->mSrcImg.x) ||
(mPrevFrameInfo.srcInfo[i].y != mAssignedSources[i]->mSrcImg.y) ||
(mPrevFrameInfo.srcInfo[i].w != mAssignedSources[i]->mSrcImg.w) ||
(mPrevFrameInfo.srcInfo[i].h != mAssignedSources[i]->mSrcImg.h) ||
(mPrevFrameInfo.srcInfo[i].format != mAssignedSources[i]->mSrcImg.format) ||
(mPrevFrameInfo.srcInfo[i].usageFlags != mAssignedSources[i]->mSrcImg.usageFlags) ||
(mPrevFrameInfo.srcInfo[i].dataSpace != mAssignedSources[i]->mSrcImg.dataSpace) ||
(mPrevFrameInfo.srcInfo[i].blending != mAssignedSources[i]->mSrcImg.blending) ||
(mPrevFrameInfo.srcInfo[i].transform != mAssignedSources[i]->mSrcImg.transform) ||
(mPrevFrameInfo.srcInfo[i].compressed != mAssignedSources[i]->mSrcImg.compressed) ||
(mPrevFrameInfo.srcInfo[i].planeAlpha != mAssignedSources[i]->mSrcImg.planeAlpha) ||
(mPrevFrameInfo.dstInfo[i].x != mAssignedSources[i]->mMidImg.x) ||
(mPrevFrameInfo.dstInfo[i].y != mAssignedSources[i]->mMidImg.y) ||
(mPrevFrameInfo.dstInfo[i].w != mAssignedSources[i]->mMidImg.w) ||
(mPrevFrameInfo.dstInfo[i].h != mAssignedSources[i]->mMidImg.h) ||
(mPrevFrameInfo.dstInfo[i].format != mAssignedSources[i]->mMidImg.format))
return false;
}
int32_t prevDstIndex = (mCurrentDstBuf + NUM_MPP_DST_BUFS(mLogicalType) - 1)% NUM_MPP_DST_BUFS(mLogicalType);
if (mDstImgs[prevDstIndex].bufferHandle == NULL)
return false;
return true;
}
int32_t ExynosMPP::setupLayer(exynos_mpp_img_info *srcImgInfo, struct exynos_image &src, struct exynos_image &dst)
{
int ret = NO_ERROR;
if (srcImgInfo->mppLayer == NULL) {
if ((srcImgInfo->mppLayer = mAcrylicHandle->createLayer()) == NULL)
{
MPP_LOGE("%s:: Fail to create layer", __func__);
return -EINVAL;
}
}
if (src.bufferHandle == NULL) {
MPP_LOGE("%s:: Invalid source handle", __func__);
return -EINVAL;
}
buffer_handle_t srcHandle = NULL;
if (src.bufferHandle != NULL)
srcHandle = src.bufferHandle;
VendorGraphicBufferMeta gmeta(srcHandle);
int bufFds[MAX_HW2D_PLANES];
size_t bufLength[MAX_HW2D_PLANES];
uint32_t attribute = 0;
uint32_t bufferNum = getBufferNumOfFormat(gmeta.format, getCompressionType(srcHandle));
android_dataspace_t dataspace = src.dataSpace;
if (dataspace == HAL_DATASPACE_UNKNOWN)
{
if (isFormatRgb(gmeta.format))
dataspace = HAL_DATASPACE_V0_SRGB;
else
dataspace = HAL_DATASPACE_V0_BT601_625;
}
if (bufferNum == 0)
{
MPP_LOGE("%s:: Fail to get bufferNum(%d), format(0x%8x, afbc %d)", __func__, bufferNum,
gmeta.format, isAFBCCompressed(srcHandle));
return -EINVAL;
}
bufFds[0] = gmeta.fd;
bufFds[1] = gmeta.fd1;
bufFds[2] = gmeta.fd2;
if (getBufLength(srcHandle, MAX_HW2D_PLANES, bufLength, gmeta.format, src.fullWidth, src.fullHeight) != NO_ERROR) {
MPP_LOGE("%s:: invalid bufferLength(%zu, %zu, %zu), format(0x%8x)", __func__,
bufLength[0], bufLength[1], bufLength[2], gmeta.format);
return -EINVAL;
}
/* HDR process */
if (hasHdrInfo(src)) {
unsigned int max = (src.metaParcel.sHdrStaticInfo.sType1.mMaxDisplayLuminance/10000);
unsigned int min = src.metaParcel.sHdrStaticInfo.sType1.mMinDisplayLuminance;
srcImgInfo->mppLayer->setMasterDisplayLuminance(min,max);
MPP_LOGD(eDebugMPP, "HWC2: G2D luminance min %d, max %d", min, max);
MPP_LOGD(eDebugMPP|eDebugFence, "G2D getting HDR source!");
}
/* Transfer MetaData */
if (src.hasMetaParcel) {
srcImgInfo->mppLayer->setLayerData(&src.metaParcel, sizeof(src.metaParcel));
}
srcImgInfo->bufferType = getBufferType(srcHandle);
if (srcImgInfo->bufferType == MPP_BUFFER_SECURE_DRM)
attribute |= AcrylicCanvas::ATTR_PROTECTED;
if (src.compressed)
attribute |= AcrylicCanvas::ATTR_COMPRESSED;
srcImgInfo->bufferHandle = srcHandle;
srcImgInfo->acrylicAcquireFenceFd =
hwcCheckFenceDebug(mAssignedDisplay, FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_G2D, src.acquireFenceFd);
MPP_LOGD(eDebugMPP|eDebugFence, "source configuration:");
MPP_LOGD(eDebugMPP, "\tImageDimension[%d, %d], ImageType[0x%8x, 0x%8x]",
src.fullWidth, src.fullHeight,
gmeta.format, dataspace);
MPP_LOGD(eDebugMPP|eDebugFence, "\tImageBuffer handle: %p, fds[%d, %d, %d], bufLength[%zu, %zu, %zu], bufferNum: %d, acquireFence: %d, attribute: %d",
srcHandle, bufFds[0], bufFds[1], bufFds[2], bufLength[0], bufLength[1], bufLength[2],
bufferNum, srcImgInfo->acrylicAcquireFenceFd, attribute);
MPP_LOGD(eDebugMPP, "\tsrc_rect[%d, %d, %d, %d], dst_rect[%d, %d, %d, %d], transform(0x%4x)",
(int)src.x, (int)src.y, (int)(src.x + src.w), (int)(src.y + src.h),
(int)dst.x, (int)dst.y, (int)(dst.x + dst.w), (int)(dst.y + dst.h), src.transform);
srcImgInfo->mppLayer->setImageDimension(src.fullWidth, src.fullHeight);
if (gmeta.format == HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_PRIV) {
srcImgInfo->mppLayer->setImageType(HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M, dataspace);
} else {
srcImgInfo->mppLayer->setImageType(gmeta.format, dataspace);
}
if (mPhysicalType == MPP_G2D) {
setFenceName(srcImgInfo->acrylicAcquireFenceFd, FENCE_G2D_SRC_LAYER);
setFenceInfo(srcImgInfo->acrylicAcquireFenceFd, mAssignedDisplay,
FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_G2D, FENCE_TO);
} else if (mPhysicalType == MPP_MSC) {
setFenceName(srcImgInfo->acrylicAcquireFenceFd, FENCE_MSC_SRC_LAYER);
setFenceInfo(srcImgInfo->acrylicAcquireFenceFd, mAssignedDisplay,
FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_MSC, FENCE_TO);
} else {
MPP_LOGE("%s:: invalid mPhysicalType(%d)", __func__, mPhysicalType);
}
srcImgInfo->mppLayer->setImageBuffer(bufFds, bufLength, bufferNum,
srcImgInfo->acrylicAcquireFenceFd, attribute);
if (mMaxSrcLayerNum > 1) {
srcImgInfo->mppLayer->setCompositMode(src.blending, (uint8_t)(255 * src.planeAlpha), src.zOrder);
} else {
srcImgInfo->mppLayer->setCompositMode(src.blending, 255, src.zOrder);
}
hwc_rect_t src_rect = {(int)src.x, (int)src.y, (int)(src.x + src.w), (int)(src.y + src.h)};
hwc_rect_t dst_rect = {(int)dst.x, (int)dst.y, (int)(dst.x + dst.w), (int)(dst.y + dst.h)};
if ((mAssignedDisplay != NULL) &&
((mAssignedDisplay->mType == HWC_DISPLAY_VIRTUAL) ||
(mAssignedDisplay->mType == HWC_DISPLAY_EXTERNAL)))
srcImgInfo->mppLayer->setCompositArea(src_rect, dst_rect, src.transform, AcrylicLayer::ATTR_NORESAMPLING);
else {
if(isFormatYUV(src.format))
srcImgInfo->mppLayer->setCompositArea(src_rect, dst_rect, src.transform, AcrylicLayer::ATTR_NORESAMPLING);
else
srcImgInfo->mppLayer->setCompositArea(src_rect, dst_rect, src.transform);
}
srcImgInfo->acrylicAcquireFenceFd = -1;
srcImgInfo->format = gmeta.format;
if (gmeta.format == HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_PRIV) {
srcImgInfo->format = HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M;
}
return ret;
}
dstMetaInfo_t ExynosMPP::getDstMetaInfo(android_dataspace_t dstDataspace)
{
dstMetaInfo_t metaInfo;
if ((mAssignedSources.size() <= 1) &&
(mAssignedSources[0]->mSrcImg.dataSpace == dstDataspace)) {
metaInfo.minLuminance =
(uint16_t)mAssignedSources[0]->mSrcImg.metaParcel.sHdrStaticInfo.sType1.mMinDisplayLuminance;
metaInfo.maxLuminance =
(uint16_t)(mAssignedSources[0]->mSrcImg.metaParcel.sHdrStaticInfo.sType1.mMaxDisplayLuminance/10000);
} else {
// minLuminance: 0.0001nit unit, maxLuminance: 1nit unit
metaInfo.minLuminance = (uint16_t)(mAssignedDisplay->mMinLuminance * 10000);
metaInfo.maxLuminance = (uint16_t)mAssignedDisplay->mMaxLuminance;
}
return metaInfo;
}
int32_t ExynosMPP::setupDst(exynos_mpp_img_info *dstImgInfo)
{
int ret = NO_ERROR;
bool isComposition = (mMaxSrcLayerNum > 1);
buffer_handle_t dstHandle = dstImgInfo->bufferHandle;
int bufFds[MAX_HW2D_PLANES];
size_t bufLength[MAX_HW2D_PLANES];
uint32_t attribute = 0;
uint32_t bufferNum = getBufferNumOfFormat(dstImgInfo->format, getCompressionType(dstHandle));
if (bufferNum == 0)
{
MPP_LOGE("%s:: Fail to get bufferNum(%d), format(0x%8x, afbc %d)", __func__, bufferNum,
dstImgInfo->format, isAFBCCompressed(dstHandle));
return -EINVAL;
}
android_dataspace_t dataspace = HAL_DATASPACE_UNKNOWN;
VendorGraphicBufferMeta gmeta(dstHandle);
if (isComposition) {
if (isFormatRgb(dstImgInfo->format)) {
if ((mAssignedDisplay != NULL) &&
(mAssignedDisplay->mColorMode != HAL_COLOR_MODE_NATIVE))
dataspace = colorModeToDataspace(mAssignedDisplay->mColorMode);
} else {
dataspace =
(android_dataspace)(HAL_DATASPACE_STANDARD_BT709 | HAL_DATASPACE_TRANSFER_GAMMA2_2 | HAL_DATASPACE_RANGE_LIMITED);
}
} else {
dataspace = mAssignedSources[0]->mMidImg.dataSpace;
}
if (dataspace == HAL_DATASPACE_UNKNOWN)
{
if (isFormatRgb(dstImgInfo->format))
dataspace = HAL_DATASPACE_V0_SRGB;
else
dataspace = HAL_DATASPACE_V0_BT601_625;
}
bufFds[0] = gmeta.fd;
bufFds[1] = gmeta.fd1;
bufFds[2] = gmeta.fd2;
if (getBufLength(dstHandle, MAX_HW2D_PLANES, bufLength, dstImgInfo->format,
gmeta.stride, gmeta.vstride) != NO_ERROR) {
MPP_LOGE("%s:: invalid bufferLength(%zu, %zu, %zu), format(0x%8x)", __func__,
bufLength[0], bufLength[1], bufLength[2], dstImgInfo->format);
return -EINVAL;
}
dstImgInfo->bufferType = getBufferType(dstHandle);
if (dstImgInfo->bufferType == MPP_BUFFER_SECURE_DRM)
attribute |= AcrylicCanvas::ATTR_PROTECTED;
if (mAssignedDisplay != NULL)
mAcrylicHandle->setCanvasDimension(pixel_align(mAssignedDisplay->mXres, G2D_JUSTIFIED_DST_ALIGN),
pixel_align(mAssignedDisplay->mYres, G2D_JUSTIFIED_DST_ALIGN));
/* setup dst */
if (isComposition && mNeedCompressedTarget)
attribute |= AcrylicCanvas::ATTR_COMPRESSED;
if (mPhysicalType == MPP_G2D) {
setFenceName(dstImgInfo->acrylicAcquireFenceFd, FENCE_G2D_DST_DPP);
/* Might be closed next frame */
setFenceInfo(dstImgInfo->acrylicAcquireFenceFd, mAssignedDisplay,
FENCE_TYPE_DST_ACQUIRE, FENCE_IP_G2D, FENCE_TO);
} else if (mPhysicalType == MPP_MSC) {
setFenceName(dstImgInfo->acrylicAcquireFenceFd, FENCE_MSC_DST_DPP);
/* Might be closed next frame */
setFenceInfo(dstImgInfo->acrylicAcquireFenceFd, mAssignedDisplay,
FENCE_TYPE_DST_ACQUIRE, FENCE_IP_MSC, FENCE_TO);
} else {
MPP_LOGE("%s:: invalid mPhysicalType(%d)", __func__, mPhysicalType);
}
mAcrylicHandle->setCanvasImageType(dstImgInfo->format, dataspace);
if ((mLogicalType == MPP_LOGICAL_G2D_COMBO) &&
(mAssignedDisplay != NULL) &&
(mAssignedDisplay->mType == HWC_DISPLAY_VIRTUAL) &&
(((ExynosVirtualDisplay *)mAssignedDisplay)->mIsWFDState == (int)LLWFD)) {
mAcrylicHandle->setCanvasImageType(HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN, dataspace);
dstImgInfo->acrylicAcquireFenceFd = fence_close(dstImgInfo->acrylicAcquireFenceFd,
mAssignedDisplay, FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_G2D);
mAcrylicHandle->setCanvasBuffer(bufFds, bufLength, bufferNum,
dstImgInfo->acrylicAcquireFenceFd, attribute);
mAcrylicHandle->setCanvasOTF(attribute);
}
else {
dstImgInfo->acrylicAcquireFenceFd =
hwcCheckFenceDebug(mAssignedDisplay, FENCE_TYPE_DST_ACQUIRE, FENCE_IP_G2D, dstImgInfo->acrylicAcquireFenceFd);
mAcrylicHandle->setCanvasBuffer(bufFds, bufLength, bufferNum,
dstImgInfo->acrylicAcquireFenceFd, attribute);
}
dstMetaInfo_t metaInfo = getDstMetaInfo(dataspace);
if ((mAssignedDisplay != NULL) &&
(mAssignedDisplay->mType != HWC_DISPLAY_VIRTUAL)) {
mAcrylicHandle->setTargetDisplayLuminance(metaInfo.minLuminance, metaInfo.maxLuminance);
}
MPP_LOGD(eDebugMPP|eDebugFence, "destination configuration:");
MPP_LOGD(eDebugMPP, "\tImageDimension[%d, %d], ImageType[0x%8x, %d], target luminance[%d, %d]",
gmeta.stride, gmeta.vstride,
dstImgInfo->format, dataspace, metaInfo.minLuminance, metaInfo.maxLuminance);
MPP_LOGD(eDebugMPP|eDebugFence, "\tImageBuffer handle: %p, fds[%d, %d, %d], bufLength[%zu, %zu, %zu], bufferNum: %d, acquireFence: %d, attribute: %d",
dstHandle, bufFds[0], bufFds[1], bufFds[2], bufLength[0], bufLength[1], bufLength[2],
bufferNum, dstImgInfo->acrylicAcquireFenceFd, attribute);
dstImgInfo->acrylicAcquireFenceFd = -1;
dstImgInfo->dataspace = dataspace;
return ret;
}
int32_t ExynosMPP::doPostProcessingInternal()
{
ATRACE_CALL();
int ret = NO_ERROR;
size_t sourceNum = mAssignedSources.size();
if (mAcrylicHandle == NULL) {
MPP_LOGE("%s:: mAcrylicHandle is NULL", __func__);
return -EINVAL;
}
/* setup source layers */
for(size_t i = 0; i < sourceNum; i++) {
MPP_LOGD(eDebugMPP|eDebugFence, "Setup [%zu] source: %p", i, mAssignedSources[i]);
if ((ret = setupLayer(&mSrcImgs[i], mAssignedSources[i]->mSrcImg, mAssignedSources[i]->mMidImg)) != NO_ERROR) {
MPP_LOGE("%s:: fail to setupLayer[%zu], ret %d",
__func__, i, ret);
return ret;
}
}
if ((ret = setColorConversionInfo()) != NO_ERROR) {
MPP_LOGE("%s:: fail to setColorConversionInfo ret %d",
__func__, ret);
return ret;
}
if (mPrevFrameInfo.srcNum > sourceNum) {
MPP_LOGD(eDebugMPP, "prev sourceNum(%d), current sourceNum(%zu)",
mPrevFrameInfo.srcNum, sourceNum);
for (size_t i = sourceNum; i < mPrevFrameInfo.srcNum; i++)
{
MPP_LOGD(eDebugMPP, "Remove mSrcImgs[%zu], %p", i, mSrcImgs[i].mppLayer);
if (mSrcImgs[i].mppLayer != NULL) {
delete mSrcImgs[i].mppLayer;
mSrcImgs[i].mppLayer = NULL;
}
}
}
if (mAcrylicHandle->layerCount() != mAssignedSources.size()) {
MPP_LOGE("Different layer number, acrylic layers(%d), assigned size(%zu)",
mAcrylicHandle->layerCount(), mAssignedSources.size());
return -EINVAL;
}
MPP_LOGD(eDebugFence, "setupDst ++ mDstImgs[%d] acrylicAcquireFenceFd(%d)",
mCurrentDstBuf, mDstImgs[mCurrentDstBuf].acrylicAcquireFenceFd);
setupDst(&mDstImgs[mCurrentDstBuf]);
MPP_LOGD(eDebugFence, "setupDst -- mDstImgs[%d] acrylicAcquireFenceFd(%d) closed",
mCurrentDstBuf, mDstImgs[mCurrentDstBuf].acrylicAcquireFenceFd);
int usingFenceCnt = 1;
bool acrylicReturn = true;
#ifndef DISABLE_FENCE
if (mUseM2MSrcFence)
usingFenceCnt = sourceNum + 1; // Get and Use src + dst fence
else
usingFenceCnt = 1; // Get and Use only dst fence
int *releaseFences = new int[usingFenceCnt];
int dstBufIdx = usingFenceCnt - 1;
#else
usingFenceCnt = 0; // Get and Use no fences
int dstBufIdx = 0;
int *releaseFences = NULL;
#endif
acrylicReturn = mAcrylicHandle->execute(releaseFences, usingFenceCnt);
if (acrylicReturn == false) {
MPP_LOGE("%s:: fail to excute compositor", __func__);
for(size_t i = 0; i < sourceNum; i++) {
mSrcImgs[i].acrylicReleaseFenceFd = -1;
MPP_LOGE("src[%zu]: ImageDimension[%d, %d], src_rect[%d, %d, %d, %d], dst_rect[%d, %d, %d, %d], transform(0x%4x)",
i,
mAssignedSources[i]->mSrcImg.fullWidth, mAssignedSources[i]->mSrcImg.fullHeight,
mAssignedSources[i]->mSrcImg.x, mAssignedSources[i]->mSrcImg.y,
mAssignedSources[i]->mSrcImg.x + mAssignedSources[i]->mSrcImg.w,
mAssignedSources[i]->mSrcImg.y + mAssignedSources[i]->mSrcImg.h,
mAssignedSources[i]->mMidImg.x, mAssignedSources[i]->mMidImg.y,
mAssignedSources[i]->mMidImg.x + mAssignedSources[i]->mMidImg.w,
mAssignedSources[i]->mMidImg.y + mAssignedSources[i]->mMidImg.h,
mAssignedSources[i]->mSrcImg.transform);
}
mDstImgs[mCurrentDstBuf].acrylicReleaseFenceFd = -1;
ret = -EPERM;
} else {
// set fence informations from acryl
if (mPhysicalType == MPP_G2D) {
setFenceInfo(releaseFences[dstBufIdx], mAssignedDisplay,
FENCE_TYPE_DST_ACQUIRE, FENCE_IP_G2D, FENCE_FROM);
if (usingFenceCnt > 1) {
for(size_t i = 0; i < sourceNum; i++) {
// TODO DPU release fence is tranferred to m2mMPP's source layer fence
setFenceInfo(releaseFences[i], mAssignedDisplay,
FENCE_TYPE_SRC_RELEASE, FENCE_IP_G2D, FENCE_FROM);
}
}
} else if (mPhysicalType == MPP_MSC) {
setFenceInfo(releaseFences[dstBufIdx], mAssignedDisplay,
FENCE_TYPE_DST_ACQUIRE, FENCE_IP_MSC, FENCE_FROM);
if (usingFenceCnt > 1) {
for(size_t i = 0; i < sourceNum; i++) {
// TODO DPU release fence is tranferred to m2mMPP's source layer fence
setFenceInfo(releaseFences[i], mAssignedDisplay,
FENCE_TYPE_SRC_RELEASE, FENCE_IP_MSC, FENCE_FROM);
}
}
} else {
MPP_LOGE("%s:: invalid mPhysicalType(%d)", __func__, mPhysicalType);
}
if ((mLogicalType == MPP_LOGICAL_G2D_COMBO) &&
(mAssignedDisplay != NULL) &&
(mAssignedDisplay->mType == HWC_DISPLAY_VIRTUAL)) {
if (((ExynosVirtualDisplay *)mAssignedDisplay)->mIsWFDState == (int)LLWFD) {
if (usingFenceCnt != 0) // Use no fences
releaseFences[dstBufIdx] = fence_close(releaseFences[dstBufIdx],
mAssignedDisplay, FENCE_TYPE_SRC_RELEASE, FENCE_IP_G2D); // Close dst buf's fence
}
if (mUseM2MSrcFence) {
if (((ExynosVirtualDisplay *)mAssignedDisplay)->mIsWFDState != (int)GOOGLEWFD) {
for (size_t i = 0; i < sourceNum; i++)
releaseFences[i] = fence_close(releaseFences[i],
mAssignedDisplay, FENCE_TYPE_SRC_RELEASE, FENCE_IP_G2D);
}
}
}
if (usingFenceCnt == 0) { // Use no fences
for(size_t i = 0; i < sourceNum; i++) {
mSrcImgs[i].acrylicReleaseFenceFd = -1;
}
mDstImgs[mCurrentDstBuf].acrylicReleaseFenceFd = -1;
} else {
for(size_t i = 0; i < sourceNum; i++) {
if (mUseM2MSrcFence)
mSrcImgs[i].acrylicReleaseFenceFd =
hwcCheckFenceDebug(mAssignedDisplay, FENCE_TYPE_SRC_RELEASE, FENCE_IP_G2D, releaseFences[i]);
else
mSrcImgs[i].acrylicReleaseFenceFd = -1;
MPP_LOGD(eDebugFence, "mSrcImgs[%zu] acrylicReleaseFenceFd: %d",
i, mSrcImgs[i].acrylicReleaseFenceFd);
}
if (mDstImgs[mCurrentDstBuf].acrylicReleaseFenceFd >= 0) {
MPP_LOGE("mDstImgs[%d].acrylicReleaseFenceFd(%d) is not initialized",
mCurrentDstBuf,
mDstImgs[mCurrentDstBuf].acrylicReleaseFenceFd);
}
if (mPhysicalType == MPP_G2D)
mDstImgs[mCurrentDstBuf].acrylicReleaseFenceFd =
hwcCheckFenceDebug(mAssignedDisplay, FENCE_TYPE_DST_RELEASE, FENCE_IP_G2D, releaseFences[dstBufIdx]);
else if (mPhysicalType == MPP_MSC)
mDstImgs[mCurrentDstBuf].acrylicReleaseFenceFd =
hwcCheckFenceDebug(mAssignedDisplay, FENCE_TYPE_DST_RELEASE, FENCE_IP_MSC, releaseFences[dstBufIdx]);
MPP_LOGD(eDebugFence, "mDstImgs[%d] acrylicReleaseFenceFd: %d , releaseFences[%d]",
mCurrentDstBuf, mDstImgs[mCurrentDstBuf].acrylicReleaseFenceFd, dstBufIdx);
}
if (exynosHWCControl.dumpMidBuf) {
ALOGI("dump image");
exynosHWCControl.dumpMidBuf = false;
if ((mDstImgs[mCurrentDstBuf].acrylicReleaseFenceFd > 0) &&
(sync_wait(mDstImgs[mCurrentDstBuf].acrylicReleaseFenceFd, 1000) < 0)) {
ALOGE("%s:: fence sync_wait error to dump image", __func__);
} else {
buffer_handle_t dstHandle = mDstImgs[mCurrentDstBuf].bufferHandle;
VendorGraphicBufferMeta gmeta(dstHandle);
ALOGI("dump image fw: %d, fh:%d, size: %d", gmeta.stride, gmeta.vstride, gmeta.size);
FILE *fp;
fp = fopen(MPP_DUMP_PATH,"ab");
if (fp) {
void *temp = mmap(0, gmeta.size, PROT_READ|PROT_WRITE, MAP_SHARED, gmeta.fd, 0);
if (temp) {
ALOGI("write...%p", temp);
int write_size = fwrite(temp, gmeta.size, 1, fp);
if (write_size < 0) {
ALOGI("write error: %s", strerror(errno));
} else {
ALOGI("write size: %d", write_size);
}
munmap(temp, gmeta.size);
} else {
ALOGE("mmap is NULL %s", strerror(errno));
}
fclose(fp);
} else {
ALOGE("open fail %s", strerror(errno));
}
}
}
}
#ifndef DISABLE_FENCE
delete [] releaseFences;
#endif
return ret;
}
bool ExynosMPP::canSkipProcessing()
{
if ((mAssignedDisplay == NULL) || (mAssignedSources.size() == 0))
return true;
ExynosMPPSource *source = mAssignedSources[0];
exynos_image dst = source->mMidImg;
if ((mLogicalType == MPP_LOGICAL_G2D_RGB) ||
(mLogicalType == MPP_LOGICAL_G2D_COMBO)) {
dst = mAssignedDisplay->mExynosCompositionInfo.mDstImg;
}
return ((needDstBufRealloc(dst, mCurrentDstBuf) == false) & canUsePrevFrame());
}
/**
* @param src
* @param dst
* @return int32_t releaseFenceFd of src buffer
*/
int32_t ExynosMPP::doPostProcessing(struct exynos_image &src, struct exynos_image &dst)
{
ATRACE_CALL();
MPP_LOGD(eDebugMPP, "total assigned sources (%zu)++++++++", mAssignedSources.size());
int ret = NO_ERROR;
bool realloc = false;
if (mAssignedSources.size() == 0) {
MPP_LOGE("Assigned source size(%zu) is not valid",
mAssignedSources.size());
ret = -EINVAL;
goto save_frame_info;
}
// Check whether destination buffer allocation is required
if (mAllocOutBufFlag) {
if ((realloc = needDstBufRealloc(dst, mCurrentDstBuf)) == true) {
// allocate mDstImgs[mCurrentDstBuf]
uint32_t bufAlign = getOutBufAlign();
bool isComposition = (mMaxSrcLayerNum > 1);
if (isComposition)
dst.format = DEFAULT_MPP_DST_FORMAT;
uint32_t allocFormat = dst.format;
uint32_t tempFormat = dst.format;
if (mFreeOutBufFlag == false)
allocFormat = DEFAULT_MPP_DST_FORMAT;
if ((allocFormat == HAL_PIXEL_FORMAT_RGBA_1010102) ||
(allocFormat == HAL_PIXEL_FORMAT_GOOGLE_NV12_SP_10B) ||
(allocFormat == HAL_PIXEL_FORMAT_YCBCR_P010))
allocFormat = DEFAULT_MPP_DST_FORMAT;
ret = allocOutBuf(ALIGN_UP(mAssignedDisplay->mXres, bufAlign),
ALIGN_UP(mAssignedDisplay->mYres, bufAlign),
allocFormat, dst.usageFlags, mCurrentDstBuf);
allocFormat = tempFormat;
}
if (ret < 0) {
MPP_LOGE("%s:: fail to allocate dst buffer[%d]", __func__, mCurrentDstBuf);
goto save_frame_info;
}
if (mDstImgs[mCurrentDstBuf].format != dst.format) {
MPP_LOGD(eDebugMPP, "dst format is changed (%d -> %d)",
mDstImgs[mCurrentDstBuf].format, dst.format);
mDstImgs[mCurrentDstBuf].format = dst.format;
}
}
if ((realloc == false) && canUsePrevFrame()) {
mCurrentDstBuf = (mCurrentDstBuf + NUM_MPP_DST_BUFS(mLogicalType) - 1)% NUM_MPP_DST_BUFS(mLogicalType);
MPP_LOGD(eDebugMPP|eDebugFence, "Reuse previous frame, dstImg[%d]", mCurrentDstBuf);
for (uint32_t i = 0; i < mAssignedSources.size(); i++) {
mAssignedSources[i]->mSrcImg.acquireFenceFd =
fence_close(mAssignedSources[i]->mSrcImg.acquireFenceFd,
mAssignedDisplay, FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_G2D);
}
goto save_frame_info;
}
/* G2D or sclaer case */
if ((ret = doPostProcessingInternal()) < 0) {
MPP_LOGE("%s:: fail to post processing, ret %d",
__func__, ret);
goto save_frame_info;
}
save_frame_info:
/* Save current frame information for next frame*/
mPrevAssignedDisplayType = mAssignedDisplay->mType;
mPrevFrameInfo.srcNum = (uint32_t)mAssignedSources.size();
for (uint32_t i = 0; i < mPrevFrameInfo.srcNum; i++) {
mPrevFrameInfo.srcInfo[i] = mAssignedSources[i]->mSrcImg;
mPrevFrameInfo.dstInfo[i] = mAssignedSources[i]->mMidImg;
}
MPP_LOGD(eDebugMPP, "mPrevAssignedState: %d, mPrevAssignedDisplayType: %d--------------",
mAssignedState, mAssignedDisplay->mType);
return ret;
}
/*
* This function should be called after doPostProcessing()
* because doPostProcessing() sets
* mSrcImgs[].mppImg.releaseFenceFd
*/
int32_t ExynosMPP::getSrcReleaseFence(uint32_t srcIndex)
{
if (srcIndex >= NUM_MPP_SRC_BUFS)
return -EINVAL;
return mSrcImgs[srcIndex].acrylicReleaseFenceFd;
return -EINVAL;
}
int32_t ExynosMPP::resetSrcReleaseFence()
{
MPP_LOGD(eDebugFence, "");
for (uint32_t i = 0; i < mAssignedSources.size(); i++) {
mSrcImgs[i].acrylicReleaseFenceFd = -1;
}
return NO_ERROR;
}
int32_t ExynosMPP::getDstImageInfo(exynos_image *img)
{
if ((mCurrentDstBuf < 0) || (mCurrentDstBuf >= NUM_MPP_DST_BUFS(mLogicalType)) ||
(mAssignedDisplay == NULL)) {
MPP_LOGE("mCurrentDstBuf(%d), mAssignedDisplay(%p)", mCurrentDstBuf, mAssignedDisplay);
return -EINVAL;
}
memset(img, 0, sizeof(exynos_image));
img->acquireFenceFd = -1;
img->releaseFenceFd = -1;
if (mDstImgs[mCurrentDstBuf].bufferHandle == NULL) {
img->acquireFenceFd = -1;
img->releaseFenceFd = -1;
return -EFAULT;
} else {
img->bufferHandle = mDstImgs[mCurrentDstBuf].bufferHandle;
VendorGraphicBufferMeta gmeta(img->bufferHandle);
img->fullWidth = gmeta.stride;
img->fullHeight = gmeta.vstride;
if ((mLogicalType == MPP_LOGICAL_G2D_RGB) ||
(mLogicalType == MPP_LOGICAL_G2D_COMBO)) {
if (mAssignedSources.size() == 1) {
img->x = mAssignedSources[0]->mDstImg.x;
img->y = mAssignedSources[0]->mDstImg.y;
img->w = mAssignedSources[0]->mDstImg.w;
img->h = mAssignedSources[0]->mDstImg.h;
} else {
img->x = 0;
img->y = 0;
img->w = mAssignedDisplay->mXres;
img->h = mAssignedDisplay->mXres;
}
} else {
img->x = mAssignedSources[0]->mMidImg.x;
img->y = mAssignedSources[0]->mMidImg.y;
img->w = mAssignedSources[0]->mMidImg.w;
img->h = mAssignedSources[0]->mMidImg.h;
img->needColorTransform =
mAssignedSources[0]->mMidImg.needColorTransform;
}
img->format = mDstImgs[mCurrentDstBuf].format;
MPP_LOGD(eDebugFence, "get dstBuf[%d] accquireFence(%d)", mCurrentDstBuf,
mDstImgs[mCurrentDstBuf].acrylicAcquireFenceFd);
img->acquireFenceFd = mDstImgs[mCurrentDstBuf].acrylicAcquireFenceFd;
img->releaseFenceFd = mDstImgs[mCurrentDstBuf].acrylicReleaseFenceFd;
img->dataSpace = mDstImgs[mCurrentDstBuf].dataspace;
}
return NO_ERROR;
}
/*
* This function should be called after getDstReleaseFence()
* by ExynosDisplay
*/
int32_t ExynosMPP::setDstAcquireFence(int acquireFence)
{
int dstBufIndex = 0;
dstBufIndex = mPrivDstBuf;
if (mPrivDstBuf == mCurrentDstBuf)
MPP_LOGD(eDebugFence|eDebugMPP,
"M2MMPP : same buffer was reused idx %d, %d",mPrivDstBuf, mCurrentDstBuf);
if (dstBufIndex < 0 || dstBufIndex >= NUM_MPP_DST_BUFS(mLogicalType)) {
// TODO fence_close..
acquireFence = fence_close(acquireFence, mAssignedDisplay, FENCE_TYPE_DST_ACQUIRE, FENCE_IP_ALL);
mPrivDstBuf = mCurrentDstBuf;
return -EINVAL;
}
if (acquireFence < 0) {
mPrivDstBuf = mCurrentDstBuf;
return -EINVAL;
}
if (mDstImgs[dstBufIndex].acrylicAcquireFenceFd >= 0) {
MPP_LOGD(eDebugFence,"mDstImgs[%d].acrylicAcquireFenceFd: %d is closed", dstBufIndex,
mDstImgs[dstBufIndex].acrylicAcquireFenceFd);
fence_close(mDstImgs[dstBufIndex].acrylicAcquireFenceFd, mAssignedDisplay,
FENCE_TYPE_DST_ACQUIRE, FENCE_IP_ALL);
}
if (mPhysicalType == MPP_MSC)
mDstImgs[dstBufIndex].acrylicAcquireFenceFd =
hwcCheckFenceDebug(mAssignedDisplay, FENCE_TYPE_DST_ACQUIRE, FENCE_IP_MSC, acquireFence);
else
mDstImgs[dstBufIndex].acrylicAcquireFenceFd =
hwcCheckFenceDebug(mAssignedDisplay, FENCE_TYPE_DST_ACQUIRE, FENCE_IP_G2D, acquireFence);
MPP_LOGD(eDebugFence,"->mDstImgs[%d].acrylicAcquireFenceFd: %d", dstBufIndex,
mDstImgs[dstBufIndex].acrylicAcquireFenceFd);
mPrivDstBuf = mCurrentDstBuf;
return NO_ERROR;
}
int32_t ExynosMPP::resetDstReleaseFence()
{
MPP_LOGD(eDebugFence, "");
if (mCurrentDstBuf < 0 || mCurrentDstBuf >= NUM_MPP_DST_BUFS(mLogicalType))
return -EINVAL;
mDstImgs[mCurrentDstBuf].acrylicReleaseFenceFd = -1;
return NO_ERROR;
}
int32_t ExynosMPP::requestHWStateChange(uint32_t state)
{
MPP_LOGD(eDebugMPP|eDebugFence|eDebugBuf, "state: %d", state);
/* Set HW state to running */
if (mHWState == state) {
if ((mPhysicalType == MPP_G2D) && (state == MPP_HW_STATE_IDLE) && (mHWBusyFlag == false)) {
int ret = NO_ERROR;
if ((ret = prioritize(-1)) != NO_ERROR)
MPP_LOGI("prioritize (%d) will be applied on next work", ret);
}
return NO_ERROR;
}
if (state == MPP_HW_STATE_RUNNING)
mHWState = MPP_HW_STATE_RUNNING;
else if (state == MPP_HW_STATE_IDLE) {
if (mLastStateFenceFd >= 0)
mResourceManageThread.addStateFence(mLastStateFenceFd);
else
mHWState = MPP_HW_STATE_IDLE;
mLastStateFenceFd = -1;
if ((mPhysicalType == MPP_G2D) && (mHWBusyFlag == false)) {
int ret = NO_ERROR;
if ((ret = prioritize(-1)) != NO_ERROR)
MPP_LOGI("prioritize (%d) is not applied on next work", ret);
}
/* Free all of output buffers */
if (mMPPType == MPP_TYPE_M2M) {
for(uint32_t i = 0; i < NUM_MPP_DST_BUFS(mLogicalType); i++) {
exynos_mpp_img_info freeDstBuf = mDstImgs[i];
memset(&mDstImgs[i], 0, sizeof(mDstImgs[i]));
mDstImgs[i].acrylicAcquireFenceFd = freeDstBuf.acrylicAcquireFenceFd;
mDstImgs[i].acrylicReleaseFenceFd = freeDstBuf.acrylicReleaseFenceFd;
freeDstBuf.acrylicAcquireFenceFd = -1;
freeDstBuf.acrylicReleaseFenceFd = -1;
if (mFreeOutBufFlag == true) {
MPP_LOGD(eDebugMPP|eDebugFence|eDebugBuf, "free outbuf[%d] %p",
i, freeDstBuf.bufferHandle);
if (freeDstBuf.bufferHandle != NULL && mAllocOutBufFlag) {
freeOutBuf(freeDstBuf);
}
} else {
mDstImgs[i].bufferHandle = freeDstBuf.bufferHandle;
mDstImgs[i].bufferType = freeDstBuf.bufferType;
}
}
}
for (uint32_t i = 0; i < NUM_MPP_SRC_BUFS; i++)
{
if (mSrcImgs[i].mppLayer != NULL) {
delete mSrcImgs[i].mppLayer;
mSrcImgs[i].mppLayer = NULL;
}
}
memset(&mPrevFrameInfo, 0, sizeof(mPrevFrameInfo));
for (int i = 0; i < NUM_MPP_SRC_BUFS; i++) {
mPrevFrameInfo.srcInfo[i].acquireFenceFd = -1;
mPrevFrameInfo.srcInfo[i].releaseFenceFd = -1;
mPrevFrameInfo.dstInfo[i].acquireFenceFd = -1;
mPrevFrameInfo.dstInfo[i].releaseFenceFd = -1;
}
}
return NO_ERROR;
}
int32_t ExynosMPP::setHWStateFence(int32_t fence)
{
MPP_LOGD(eDebugFence, "Update HWState fence, Close(%d), set(%d)",
mLastStateFenceFd, fence);
mLastStateFenceFd = fence;
return NO_ERROR;
}
/**
* @param ..
* @return int32_t
*/
int32_t ExynosMPP::setupRestriction() {
MPP_LOGD(eDebugMPP, "mPhysicalType(%d)", mPhysicalType);
for (uint32_t i = 0; i < RESTRICTION_MAX; i++) {
const restriction_size_element *restriction_size_table = mResourceManager->mSizeRestrictions[i];
for (uint32_t j = 0; j < mResourceManager->mSizeRestrictionCnt[i]; j++) {
if (restriction_size_table[j].key.hwType == mPhysicalType) {
if ((restriction_size_table[j].key.nodeType == NODE_SRC) ||
(restriction_size_table[j].key.nodeType == NODE_NONE)) {
memcpy(&mSrcSizeRestrictions[i], &restriction_size_table[j].sizeRestriction,
sizeof(mSrcSizeRestrictions[i]));
MPP_LOGD(eDebugMPP, "\tSet mSrcSizeRestrictions[%d], "
"[%d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d]",
i, mSrcSizeRestrictions[i].maxDownScale, mSrcSizeRestrictions[i].maxUpScale,
mSrcSizeRestrictions[i].maxFullWidth, mSrcSizeRestrictions[i].maxFullHeight,
mSrcSizeRestrictions[i].minFullWidth, mSrcSizeRestrictions[i].minFullHeight,
mSrcSizeRestrictions[i].fullWidthAlign, mSrcSizeRestrictions[i].fullHeightAlign,
mSrcSizeRestrictions[i].maxCropWidth, mSrcSizeRestrictions[i].maxCropHeight,
mSrcSizeRestrictions[i].minCropWidth, mSrcSizeRestrictions[i].minCropHeight,
mSrcSizeRestrictions[i].cropXAlign, mSrcSizeRestrictions[i].cropYAlign,
mSrcSizeRestrictions[i].cropWidthAlign, mSrcSizeRestrictions[i].cropHeightAlign);
}
if ((restriction_size_table[j].key.nodeType == NODE_DST) ||
(restriction_size_table[j].key.nodeType == NODE_NONE)) {
memcpy(&mDstSizeRestrictions[i], &restriction_size_table[j].sizeRestriction,
sizeof(mDstSizeRestrictions[i]));
MPP_LOGD(eDebugMPP, "\tSet mDstSizeRestrictions[%d], "
"[%d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d]",
i, mDstSizeRestrictions[i].maxDownScale, mDstSizeRestrictions[i].maxUpScale,
mDstSizeRestrictions[i].maxFullWidth, mDstSizeRestrictions[i].maxFullHeight,
mDstSizeRestrictions[i].minFullWidth, mDstSizeRestrictions[i].minFullHeight,
mDstSizeRestrictions[i].fullWidthAlign, mDstSizeRestrictions[i].fullHeightAlign,
mDstSizeRestrictions[i].maxCropWidth, mDstSizeRestrictions[i].maxCropHeight,
mDstSizeRestrictions[i].minCropWidth, mDstSizeRestrictions[i].minCropHeight,
mDstSizeRestrictions[i].cropXAlign, mDstSizeRestrictions[i].cropYAlign,
mDstSizeRestrictions[i].cropWidthAlign, mDstSizeRestrictions[i].cropHeightAlign);
}
}
}
}
return NO_ERROR;
}
int64_t ExynosMPP::isSupported(ExynosDisplay &display, struct exynos_image &src, struct exynos_image &dst)
{
uint32_t maxSrcWidth = getSrcMaxWidth(src);
uint32_t maxSrcHeight = getSrcMaxHeight(src);
uint32_t minSrcWidth = getSrcMinWidth(src);
uint32_t minSrcHeight = getSrcMinHeight(src);
uint32_t srcWidthAlign = getSrcWidthAlign(src);
uint32_t srcHeightAlign = getSrcHeightAlign(src);
uint32_t maxSrcCropWidth = getSrcMaxCropWidth(src);
uint32_t maxSrcCropHeight = getSrcMaxCropHeight(src);
uint32_t maxSrcCropSize = getSrcMaxCropSize(src);
uint32_t minSrcCropWidth = getSrcMinCropWidth(src);
uint32_t minSrcCropHeight = getSrcMinCropHeight(src);
uint32_t srcCropWidthAlign = getSrcCropWidthAlign(src);
uint32_t srcCropHeightAlign = getSrcCropHeightAlign(src);
uint32_t srcXOffsetAlign = getSrcXOffsetAlign(src);
uint32_t srcYOffsetAlign = getSrcYOffsetAlign(src);
uint32_t maxDstWidth = getDstMaxWidth(dst);
uint32_t maxDstHeight = getDstMaxHeight(dst);
uint32_t minDstWidth = getDstMinWidth(dst);
uint32_t minDstHeight = getDstMinHeight(dst);
uint32_t dstWidthAlign = getDstWidthAlign(dst);
uint32_t dstHeightAlign = getDstHeightAlign(dst);
uint32_t dstXOffsetAlign = getDstXOffsetAlign(dst);
uint32_t dstYOffsetAlign = getDstYOffsetAlign(dst);
uint32_t maxDownscale = getMaxDownscale(display, src, dst);
uint32_t maxUpscale = getMaxUpscale(src, dst);
exynos_image rot_dst = dst;
bool isPerpendicular = !!(src.transform & HAL_TRANSFORM_ROT_90);
if (isPerpendicular) {
rot_dst.w = dst.h;
rot_dst.h = dst.w;
}
if (rot_dst.w > maxDstWidth)
return -eMPPExeedMaxDstWidth;
else if (rot_dst.h > maxDstHeight)
return -eMPPExeedMaxDstHeight;
else if (rot_dst.w < minDstWidth)
return -eMPPExeedMinDstWidth;
else if (rot_dst.h < minDstHeight)
return -eMPPExeedMinDstHeight;
else if (src.isDimLayer()) { // Dim layer
if (isDimLayerSupported()) {
return NO_ERROR;
} else {
return -eMPPUnsupportedDIMLayer;
}
}
if (!isSupportedCapability(display, src))
return -eMPPSaveCapability;
else if (!isSrcFormatSupported(src))
return -eMPPUnsupportedFormat;
else if (!isDstFormatSupported(dst))
return -eMPPUnsupportedFormat;
else if (!isDataspaceSupportedByMPP(src, dst))
return -eMPPUnsupportedCSC;
else if (!isSupportedHDR10Plus(src, dst))
return -eMPPUnsupportedDynamicMeta;
else if (!isSupportedBlend(src))
return -eMPPUnsupportedBlending;
else if (!isSupportedTransform(src))
return -eMPPUnsupportedRotation;
else if (src.fullWidth < minSrcWidth)
return -eMPPExeedMinSrcWidth;
else if (src.fullHeight < minSrcHeight)
return -eMPPExeedMinSrcHeight;
else if (src.w < minSrcCropWidth)
return -eMPPExeedSrcWCropMin;
else if (src.h < minSrcCropHeight)
return -eMPPExeedSrcHCropMin;
else if ((rot_dst.w % dstWidthAlign != 0) || (rot_dst.h % dstHeightAlign != 0))
return -eMPPNotAlignedDstSize;
else if (src.w > rot_dst.w * maxDownscale)
return -eMPPExeedMaxDownScale;
else if (rot_dst.w > src.w * maxUpscale)
return -eMPPExeedMaxUpScale;
else if (src.h > rot_dst.h * maxDownscale)
return -eMPPExeedMaxDownScale;
else if (rot_dst.h > src.h * maxUpscale)
return -eMPPExeedMaxUpScale;
else if (!isSupportedDRM(src))
return -eMPPUnsupportedDRM;
else if (!isSupportedHStrideCrop(src))
return -eMPPStrideCrop;
else if (src.fullWidth > maxSrcWidth)
return -eMPPExceedHStrideMaximum;
else if (src.fullWidth % srcWidthAlign != 0)
return -eMPPNotAlignedHStride;
if ((src.w * src.h) > maxSrcCropSize)
return -eMPPExeedSrcCropMax;
if (getDrmMode(src.usageFlags) == NO_DRM) {
if (src.fullHeight > maxSrcHeight)
return -eMPPExceedVStrideMaximum;
else if (src.fullHeight % srcHeightAlign != 0)
return -eMPPNotAlignedVStride;
else if (src.w > maxSrcCropWidth)
return -eMPPExeedSrcWCropMax;
else if (src.h > maxSrcCropHeight)
return -eMPPExeedSrcHCropMax;
else if ((src.w % srcCropWidthAlign != 0) || (src.h % srcCropHeightAlign != 0))
return -eMPPNotAlignedCrop;
else if ((src.x % srcXOffsetAlign != 0) || (src.y % srcYOffsetAlign != 0))
return -eMPPNotAlignedOffset;
}
if ((dst.x % dstXOffsetAlign != 0) || (dst.y % dstYOffsetAlign != 0))
return -eMPPNotAlignedOffset;
if (!isSupportedCompression(src))
return -eMPPUnsupportedCompression;
if (!isSupportLayerColorTransform(src,dst))
return -eMPPUnsupportedColorTransform;
return NO_ERROR;
}
int32_t ExynosMPP::resetMPP()
{
mAssignedState = MPP_ASSIGN_STATE_FREE;
mAssignedDisplay = NULL;
mAssignedSources.clear();
resetUsedCapacity();
mReservedDisplay = -1;
mHWBusyFlag = false;
return NO_ERROR;
}
int32_t ExynosMPP::resetAssignedState()
{
for (int i = (int)mAssignedSources.size(); i-- > 0;) {
ExynosMPPSource *mppSource = mAssignedSources[i];
if (mppSource->mOtfMPP == this) {
mppSource->mOtfMPP = NULL;
}
if (mppSource->mM2mMPP == this) {
mppSource->mM2mMPP = NULL;
}
mAssignedSources.removeItemsAt(i);
}
/* Keep status if mAssignedState is MPP_ASSIGN_STATE_RESERVED */
if ((mAssignedState & MPP_ASSIGN_STATE_ASSIGNED) &&
(mAssignedSources.size() == 0)) {
mAssignedState &= ~MPP_ASSIGN_STATE_ASSIGNED;
mAssignedDisplay = NULL;
}
/* All mpp source are removed, reset capacity information */
resetUsedCapacity();
return NO_ERROR;
}
int32_t ExynosMPP::resetAssignedState(ExynosMPPSource *mppSource)
{
bool needUpdateCapacity = false;
for (int i = (int)mAssignedSources.size(); i-- > 0;) {
ExynosMPPSource *source = mAssignedSources[i];
if (source == mppSource) {
if (mppSource->mM2mMPP == this) {
mppSource->mM2mMPP = NULL;
}
/* Update information for used capacity */
/* This should be called before mAssignedSources.removeItemsAt(mppSource) */
needUpdateCapacity = removeCapacity(mppSource);
mAssignedSources.removeItemsAt(i);
if (needUpdateCapacity)
updateUsedCapacity();
break;
}
}
/* Keep status if mAssignedState is MPP_ASSIGN_STATE_RESERVED */
if ((mAssignedState & MPP_ASSIGN_STATE_ASSIGNED) &&
(mAssignedSources.size() == 0)) {
mAssignedState &= ~MPP_ASSIGN_STATE_ASSIGNED;
mAssignedDisplay = NULL;
}
return NO_ERROR;
}
int32_t ExynosMPP::reserveMPP(int32_t displayType)
{
mAssignedState |= MPP_ASSIGN_STATE_RESERVED;
mReservedDisplay = displayType;
return NO_ERROR;
}
int32_t ExynosMPP::assignMPP(ExynosDisplay *display, ExynosMPPSource* mppSource)
{
mAssignedState |= MPP_ASSIGN_STATE_ASSIGNED;
if (mMPPType == MPP_TYPE_OTF)
mppSource->mOtfMPP = this;
else if (mMPPType == MPP_TYPE_M2M)
mppSource->mM2mMPP = this;
else {
MPP_LOGE("%s:: Invalid mppType(%d)", __func__, mMPPType);
return -EINVAL;
}
mAssignedDisplay = display;
/* Update information for used capacity */
/* This should be called before mAssignedSources.add(mppSource) */
bool needUpdateCapacity = addCapacity(mppSource);
mAssignedSources.add(mppSource);
MPP_LOGD(eDebugCapacity|eDebugMPP, "\tassigned to source(%p) type(%d), mAssignedSources(%zu)",
mppSource, mppSource->mSourceType,
mAssignedSources.size());
if (needUpdateCapacity)
updateUsedCapacity();
if (mMaxSrcLayerNum > 1) {
std::sort(mAssignedSources.begin(), mAssignedSources.end(), exynosMPPSourceComp);
}
return NO_ERROR;
}
uint32_t ExynosMPP::getSrcMaxBlendingNum(struct exynos_image __unused &src, struct exynos_image __unused &dst)
{
uint32_t maxSrcLayerNum = mMaxSrcLayerNum;
return maxSrcLayerNum;
}
uint32_t ExynosMPP::getAssignedSourceNum()
{
return mAssignedSources.size();
}
/* Based on multi-resolution support */
void ExynosMPP::setDstAllocSize(uint32_t width, uint32_t height)
{
switch(width) {
case 720:
mDstAllocatedSize = ((height >= 1480) ? DST_SIZE_HD_PLUS : DST_SIZE_HD);
break;
case 1080:
mDstAllocatedSize = ((height >= 2220) ? DST_SIZE_FHD_PLUS : DST_SIZE_FHD);
break;
case 1440:
mDstAllocatedSize = ((height >= 2960) ? DST_SIZE_WQHD_PLUS : DST_SIZE_WQHD);
break;
default:
mDstAllocatedSize = DST_SIZE_UNKNOWN;
break;
}
}
dst_alloc_buf_size_t ExynosMPP::getDstAllocSize()
{
return mDstAllocatedSize;
}
bool ExynosMPP::needPreAllocation()
{
bool ret = false;
if ((mLogicalType == MPP_LOGICAL_G2D_RGB) &&
(mPreAssignDisplayList[mResourceManager->mDevice->mDisplayMode] == HWC_DISPLAY_PRIMARY_BIT))
ret = true;
return ret;
}
bool ExynosMPP::isAssignableState(ExynosDisplay *display, struct exynos_image &src, struct exynos_image &dst)
{
bool isAssignable = false;
if (mAssignedState == MPP_ASSIGN_STATE_FREE) {
if (mHWState == MPP_HW_STATE_IDLE)
isAssignable = true;
else {
if ((mPrevAssignedDisplayType < 0) ||
((uint32_t)mPrevAssignedDisplayType == display->mType))
isAssignable = true;
else
isAssignable = false;
}
}
if ((mAssignedState & MPP_ASSIGN_STATE_ASSIGNED) && (mAssignedState & MPP_ASSIGN_STATE_RESERVED))
{
if (mReservedDisplay == (int32_t)display->mType) {
if (mAssignedSources.size() < getSrcMaxBlendingNum(src, dst))
isAssignable = true;
else
isAssignable = false;
} else {
isAssignable = false;
}
} else if ((mAssignedState & MPP_ASSIGN_STATE_ASSIGNED) && !(mAssignedState & MPP_ASSIGN_STATE_RESERVED)) {
if (mAssignedSources.size() < getSrcMaxBlendingNum(src, dst))
isAssignable = true;
else
isAssignable = false;
} else if (mAssignedState & MPP_ASSIGN_STATE_RESERVED) {
if (mReservedDisplay == (int32_t)display->mType)
isAssignable = true;
else
isAssignable = false;
}
MPP_LOGD(eDebugMPP, "\tisAssignableState(%d), assigned size(%zu), getSrcMaxBlendingNum(%d)",
isAssignable, mAssignedSources.size(), getSrcMaxBlendingNum(src, dst));
return isAssignable;
}
bool ExynosMPP::isAssignable(ExynosDisplay *display,
struct exynos_image &src, struct exynos_image &dst)
{
bool isAssignable = isAssignableState(display, src, dst);
return (isAssignable && hasEnoughCapa(display, src, dst));
}
bool ExynosMPP::hasEnoughCapa(ExynosDisplay *display, struct exynos_image &src, struct exynos_image &dst)
{
if (mCapacity == -1)
return true;
float totalUsedCapacity = ExynosResourceManager::getResourceUsedCapa(*this);
MPP_LOGD(eDebugCapacity|eDebugMPP, "totalUsedCapacity(%f), mUsedCapacity(%f)",
totalUsedCapacity, mUsedCapacity);
/* mUsedCapacity should be re-calculated including src, dst passed as parameters*/
totalUsedCapacity -= mUsedCapacity;
float requiredCapacity = getRequiredCapacity(display, src, dst);
MPP_LOGD(eDebugCapacity|eDebugMPP, "mCapacity(%f), usedCapacity(%f), RequiredCapacity(%f)",
mCapacity, totalUsedCapacity, requiredCapacity);
if (mCapacity >= (totalUsedCapacity + requiredCapacity))
return true;
else if ((hasHdrInfo(src)) &&
(totalUsedCapacity == 0) && (requiredCapacity < (mCapacity * 1.2))) {
/* HDR video will be excepted from G2D capa calculation */
/* if DRM has assigned before, totalUsedCapacity will be non-zero */
return true;
} else
return false;
}
void ExynosMPP::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)
{
formatIndex = 0;
rotIndex = 0;
scaleIndex = 0;
/* Compare SBWC and 10bitYUV420 first! because can be overlapped with other format */
if (isFormatSBWC(criteria.format) && hasPPC(mPhysicalType, PPC_FORMAT_SBWC, PPC_ROT_NO))
formatIndex = PPC_FORMAT_SBWC;
else if (isFormatP010(criteria.format) && hasPPC(mPhysicalType, PPC_FORMAT_P010, PPC_ROT_NO))
formatIndex = PPC_FORMAT_P010;
else if (isFormatYUV8_2(criteria.format) && hasPPC(mPhysicalType, PPC_FORMAT_YUV8_2, PPC_ROT_NO))
formatIndex = PPC_FORMAT_YUV8_2;
else if (isFormatYUV420(criteria.format) && hasPPC(mPhysicalType, PPC_FORMAT_YUV420, PPC_ROT_NO))
formatIndex = PPC_FORMAT_YUV420;
else if (isFormatYUV422(criteria.format) && hasPPC(mPhysicalType, PPC_FORMAT_YUV422, PPC_ROT_NO))
formatIndex = PPC_FORMAT_YUV422;
else if ((src.compressed == 1) && hasPPC(mPhysicalType, PPC_FORMAT_AFBC, PPC_ROT_NO))
formatIndex = PPC_FORMAT_AFBC;
else
formatIndex = PPC_FORMAT_RGB32;
if (((criteria.transform & HAL_TRANSFORM_ROT_90) != 0) ||
(mRotatedSrcCropBW > 0))
rotIndex = PPC_ROT;
else
rotIndex = PPC_ROT_NO;
uint32_t srcResolution = src.w * src.h;
uint32_t dstResolution = dst.w * dst.h;
if (mPhysicalType == MPP_G2D) {
if (srcResolution == dstResolution) {
scaleIndex = PPC_SCALE_NO;
} else if (dstResolution > srcResolution) {
/* scale up case */
if (dstResolution >= (srcResolution * 4))
scaleIndex = PPC_SCALE_UP_4_;
else
scaleIndex = PPC_SCALE_UP_1_4;
} else {
/* scale down case */
if ((dstResolution * 16) <= srcResolution)
scaleIndex = PPC_SCALE_DOWN_16_;
else if (((dstResolution * 9) <= srcResolution) &&
(srcResolution < (dstResolution * 16)))
scaleIndex = PPC_SCALE_DOWN_9_16;
else if (((dstResolution * 4) <= srcResolution) &&
(srcResolution < (dstResolution * 9)))
scaleIndex = PPC_SCALE_DOWN_4_9;
else
scaleIndex = PPC_SCALE_DOWN_1_4;
}
} else scaleIndex = 0; /* MSC doesn't refer scale Index */
}
float ExynosMPP::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)
{
float PPC = 0;
uint32_t formatIndex = 0;
uint32_t rotIndex = 0;
uint32_t scaleIndex = 0;
getPPCIndex(src, dst, formatIndex, rotIndex, scaleIndex, criteria);
if ((rotIndex == PPC_ROT_NO) && (assignCheckSrc != NULL) &&
((assignCheckSrc->transform & HAL_TRANSFORM_ROT_90) != 0)) {
rotIndex = PPC_ROT;
}
if (mPhysicalType == MPP_G2D || mPhysicalType == MPP_MSC) {
if (hasPPC(mPhysicalType, formatIndex, rotIndex)) {
PPC = ppc_table_map.at(PPC_IDX(mPhysicalType, formatIndex, rotIndex)).ppcList[scaleIndex];
}
}
if (PPC == 0) {
MPP_LOGE("%s:: mPhysicalType(%d), formatIndex(%d), rotIndex(%d), scaleIndex(%d), PPC(%f) is not valid",
__func__, mPhysicalType, formatIndex, rotIndex, scaleIndex, PPC);
PPC = 0.000001; /* It means can't use mPhysicalType H/W */
}
MPP_LOGD(eDebugCapacity, "srcW(%d), srcH(%d), dstW(%d), dstH(%d), rot(%d)"
"formatIndex(%d), rotIndex(%d), scaleIndex(%d), PPC(%f)",
src.w, src.h, dst.w, dst.h, src.transform,
formatIndex, rotIndex, scaleIndex, PPC);
return PPC;
}
float ExynosMPP::getAssignedCapacity()
{
float capacity = 0;
float baseCycles = 0;
uint32_t rotIndex = 0;
if (mPhysicalType != MPP_G2D)
return 0;
/*
* Client target is assigned to m2mMPP
* even if capacity is not enough
*/
if ((mAssignedDisplay != NULL) &&
(mAssignedDisplay->mType == HWC_DISPLAY_VIRTUAL))
return 0;
for (uint32_t i = 0; i < mAssignedSources.size(); i++) {
if ((mAssignedSources[i]->mSrcImg.transform & HAL_TRANSFORM_ROT_90) != 0)
rotIndex = PPC_ROT;
}
MPP_LOGD(eDebugCapacity, "Check all of assigned layers cycles");
/* PPC of layers that were added before should be changed */
/* Check cycles of all assigned layers again */
if ((mAssignedDisplay != NULL) && (mMaxSrcLayerNum > 1)) {
baseCycles += ((mAssignedDisplay->mXres * mAssignedDisplay->mYres) / G2D_BASE_PPC_COLORFILL);
MPP_LOGD(eDebugCapacity, "colorfill cycles: %f, total cycles: %f",
((mAssignedDisplay->mXres * mAssignedDisplay->mYres) / G2D_BASE_PPC_COLORFILL), baseCycles);
}
for (uint32_t i = 0; i < mAssignedSources.size(); i++) {
float srcCycles = 0;
uint32_t srcResolution = mAssignedSources[i]->mSrcImg.w * mAssignedSources[i]->mSrcImg.h;
uint32_t dstResolution = mAssignedSources[i]->mMidImg.w * mAssignedSources[i]->mMidImg.h;
uint32_t maxResolution = max(srcResolution, dstResolution);
float PPC = 0;
if (mAssignedSources[i]->mSrcImg.layerFlags & EXYNOS_HWC_DIM_LAYER) {
PPC = G2D_BASE_PPC_COLORFILL;
} else {
PPC = getPPC(mAssignedSources[i]->mSrcImg, mAssignedSources[i]->mMidImg, mAssignedSources[i]->mSrcImg,
&mAssignedSources[i]->mSrcImg, &mAssignedSources[i]->mMidImg);
}
srcCycles = maxResolution/PPC;
/* Hdr and drm layer is exception */
if ((hasHdrInfo(mAssignedSources[i]->mSrcImg) ||
(getDrmMode(mAssignedSources[i]->mSrcImg.usageFlags) != NO_DRM))) {
MPP_LOGD(eDebugCapacity, "Src[%d] is skipped(drm or hdr), cycles: %f, PPC: %f, srcResolution: %d, dstResolution: %d, rot(%d)",
i, srcCycles, PPC, srcResolution, dstResolution, mAssignedSources[i]->mSrcImg.transform);
continue;
}
baseCycles += srcCycles;
MPP_LOGD(eDebugCapacity, "Src[%d] cycles: %f, total cycles: %f, PPC: %f, srcResolution: %d, dstResolution: %d, rot(%d)",
i, srcCycles, baseCycles, PPC, srcResolution, dstResolution, mAssignedSources[i]->mSrcImg.transform);
}
capacity = baseCycles / mClockKhz;
return capacity;
}
float ExynosMPP::getRequiredCapacity(ExynosDisplay *display, struct exynos_image &src,
struct exynos_image &dst)
{
float capacity = 0;
float cycles = 0;
if (mPhysicalType == MPP_G2D) {
/* Initialize value with the cycles that were already assigned */
float baseCycles = mUsedBaseCycles;
float srcCycles = 0;
uint32_t srcResolution = src.w * src.h;
uint32_t dstResolution = dst.w * dst.h;
uint32_t maxResolution = max(srcResolution, dstResolution);
float curBaseCycles = 0;
float PPC = 0;
if ((mAssignedSources.size() == 0) ||
(mRotatedSrcCropBW != 0) ||
((mRotatedSrcCropBW == 0) &&
((src.transform & HAL_TRANSFORM_ROT_90) == 0))) {
/* Just add cycles for current layer */
if ((mAssignedSources.size() == 0) &&
(display != NULL) && (mMaxSrcLayerNum > 1)) {
curBaseCycles = ((display->mXres * display->mYres) / G2D_BASE_PPC_COLORFILL);
MPP_LOGD(eDebugCapacity, "There is no assigned layer. Colorfill cycles: %f should be added",
curBaseCycles);
}
curBaseCycles += getRequiredBaseCycles(src, dst);
baseCycles += curBaseCycles;
MPP_LOGD(eDebugCapacity, "mUsedBaseCycles was %f, Add base cycles %f, totalBaseCycle(%f)",
mUsedBaseCycles, curBaseCycles, baseCycles);
} else {
/* Recalculate cycles for all of layers */
baseCycles = 0;
MPP_LOGD(eDebugCapacity, "Check all of assigned layers cycles");
/* PPC of layers that were added before should be changed */
/* Check cycles of all assigned layers again */
if ((display != NULL) && (mMaxSrcLayerNum > 1)) {
baseCycles += ((display->mXres * display->mYres) / G2D_BASE_PPC_COLORFILL);
MPP_LOGD(eDebugCapacity, "colorfill cycles: %f, total cycles: %f",
((display->mXres * display->mYres) / G2D_BASE_PPC_COLORFILL), cycles);
}
for (uint32_t i = 0; i < mAssignedSources.size(); i++) {
float assignedSrcCycles = 0;
uint32_t assignedSrcResolution = mAssignedSources[i]->mSrcImg.w * mAssignedSources[i]->mSrcImg.h;
uint32_t assignedDstResolution = mAssignedSources[i]->mMidImg.w * mAssignedSources[i]->mMidImg.h;
uint32_t assignedMaxResolution = max(assignedSrcResolution, assignedDstResolution);
float assignedPPC = getPPC(mAssignedSources[i]->mSrcImg, mAssignedSources[i]->mMidImg,
mAssignedSources[i]->mSrcImg, &src, &dst);
assignedSrcCycles = assignedMaxResolution/assignedPPC;
baseCycles += assignedSrcCycles;
MPP_LOGD(eDebugCapacity, "Src[%d] cycles: %f, total cycles: %f, PPC: %f, srcResolution: %d, dstResolution: %d, rot(%d)",
i, assignedSrcCycles, baseCycles, assignedPPC, assignedSrcResolution, assignedDstResolution, mAssignedSources[i]->mSrcImg.transform);
}
PPC = getPPC(src, dst, src, &src, &dst);
srcCycles = maxResolution/PPC;
baseCycles += srcCycles;
MPP_LOGD(eDebugCapacity, "check mppSource cycles: %f, total cycles: %f, PPC: %f, srcResolution: %d, dstResolution: %d, rot(%d)",
srcCycles, baseCycles, PPC, srcResolution, dstResolution, src.transform);
}
capacity = baseCycles / mClockKhz;
MPP_LOGD(eDebugCapacity, "baseCycles: %f, capacity: %f",
baseCycles, capacity);
} else if (mPhysicalType == MPP_MSC) {
/* Initialize value with the capacity that were already assigned */
capacity = mUsedCapacity;
/* Just add capacity for current layer */
float srcPPC = getPPC(src, dst, src);
float dstPPC = getPPC(src, dst, dst);
float srcCapacity = (float((src.w * src.h))) / (mClockKhz * srcPPC);
float dstCapacity = (float((dst.w * dst.h))) / (mClockKhz * dstPPC);
capacity += max(srcCapacity, dstCapacity);
}
return capacity;
}
float ExynosMPP::getRequiredBaseCycles(struct exynos_image &src, struct exynos_image &dst)
{
if (mPhysicalType != MPP_G2D)
return 0;
uint32_t srcResolution = src.w * src.h;
uint32_t dstResolution = dst.w * dst.h;
uint32_t maxResolution = max(srcResolution, dstResolution);
return maxResolution/(float)getPPC(src, dst, src);
}
bool ExynosMPP::addCapacity(ExynosMPPSource* mppSource)
{
if ((mppSource == NULL) || mCapacity == -1)
return false;
if (mPhysicalType == MPP_G2D) {
bool needUpdateCapacity = true;
if ((mAssignedSources.size() == 0) ||
(mRotatedSrcCropBW != 0) ||
((mRotatedSrcCropBW == 0) &&
((mppSource->mSrcImg.transform & HAL_TRANSFORM_ROT_90) == 0))) {
needUpdateCapacity = false;
}
if (needUpdateCapacity)
return true;
if ((mMaxSrcLayerNum > 1) &&
(mAssignedSources.size() == 0)) {
if (mAssignedDisplay != NULL) {
/* This will be the first mppSource that is assigned to the ExynosMPP */
/* Add capacity for background */
mUsedBaseCycles += ((mAssignedDisplay->mXres * mAssignedDisplay->mYres) / G2D_BASE_PPC_COLORFILL);
MPP_LOGD(eDebugCapacity, "\tcolorfill cycles: %f, total cycles: %f",
((mAssignedDisplay->mXres * mAssignedDisplay->mYres) / G2D_BASE_PPC_COLORFILL), mUsedBaseCycles);
} else {
MPP_LOGE("mAssignedDisplay is null");
}
}
float baseCycles = getRequiredBaseCycles(mppSource->mSrcImg, mppSource->mMidImg);
mUsedBaseCycles += baseCycles;
uint32_t srcResolution = mppSource->mSrcImg.w * mppSource->mSrcImg.h;
uint32_t dstResolution = mppSource->mMidImg.w * mppSource->mMidImg.h;
if ((mppSource->mSrcImg.transform & HAL_TRANSFORM_ROT_90) == 0)
mNoRotatedSrcCropBW += srcResolution;
else
mRotatedSrcCropBW += srcResolution;
mUsedCapacity = mUsedBaseCycles / mClockKhz;
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)",
mAssignedSources.size(),
baseCycles, mUsedBaseCycles, mUsedCapacity, srcResolution, dstResolution,
mppSource->mSrcImg.transform, mNoRotatedSrcCropBW, mRotatedSrcCropBW);
} else if (mPhysicalType == MPP_MSC) {
mUsedCapacity = getRequiredCapacity(NULL, mppSource->mSrcImg, mppSource->mMidImg);
}
return false;
}
bool ExynosMPP::removeCapacity(ExynosMPPSource* mppSource)
{
if ((mppSource == NULL) || (mCapacity == -1))
return false;
if (mPhysicalType == MPP_G2D) {
uint32_t srcResolution = mppSource->mSrcImg.w * mppSource->mSrcImg.h;
uint32_t dstResolution = mppSource->mDstImg.w * mppSource->mDstImg.h;
uint32_t prevRotatedSrcCropBW = mRotatedSrcCropBW;
if (mppSource->mSrcImg.transform == 0)
mNoRotatedSrcCropBW -= srcResolution;
else
mRotatedSrcCropBW -= srcResolution;
if ((prevRotatedSrcCropBW > 0) && (mRotatedSrcCropBW == 0))
return true;
float baseCycles = getRequiredBaseCycles(mppSource->mSrcImg, mppSource->mMidImg);
mUsedBaseCycles -= baseCycles;
mUsedCapacity = mUsedBaseCycles / mClockKhz;
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)",
mAssignedSources.size(),
baseCycles, mUsedBaseCycles, mUsedCapacity, srcResolution, dstResolution,
mppSource->mSrcImg.transform, mNoRotatedSrcCropBW, mRotatedSrcCropBW);
} else if (mPhysicalType == MPP_MSC) {
exynos_image &src = mppSource->mSrcImg;
exynos_image &dst = mppSource->mDstImg;
uint32_t srcResolution = src.w * src.h;
uint32_t dstResolution = dst.w * dst.h;
float srcCapacity = (float)srcResolution / getPPC(src, dst, src);
float dstCapacity = (float)dstResolution / getPPC(src, dst, dst);
mUsedCapacity -= max(srcCapacity, dstCapacity);
}
return false;
}
void ExynosMPP::resetUsedCapacity()
{
mUsedCapacity = 0;
mUsedBaseCycles = 0;
mRotatedSrcCropBW = 0;
mNoRotatedSrcCropBW = 0;
}
int32_t ExynosMPP::updateUsedCapacity()
{
int32_t ret = NO_ERROR;
if (mCapacity == -1)
return ret;
float capacity = 0;
mUsedCapacity = 0;
mRotatedSrcCropBW = 0;
mNoRotatedSrcCropBW = 0;
if ((mPhysicalType == MPP_G2D) &&
(mAssignedDisplay != NULL) &&
(mAssignedSources.size() > 0)) {
float cycles = 0;
if (mMaxSrcLayerNum > 1) {
cycles += ((mAssignedDisplay->mXres * mAssignedDisplay->mYres) / G2D_BASE_PPC_COLORFILL);
MPP_LOGD(eDebugCapacity, "\tcolorfill cycles: %f, total cycles: %f",
((mAssignedDisplay->mXres * mAssignedDisplay->mYres) / G2D_BASE_PPC_COLORFILL), cycles);
}
for (uint32_t i = 0; i < mAssignedSources.size(); i++) {
uint32_t srcResolution = mAssignedSources[i]->mSrcImg.w * mAssignedSources[i]->mSrcImg.h;
if ((mAssignedSources[i]->mSrcImg.transform & HAL_TRANSFORM_ROT_90) == 0)
mNoRotatedSrcCropBW += srcResolution;
else
mRotatedSrcCropBW += srcResolution;
}
MPP_LOGD(eDebugCapacity, "mNoRotatedSrcCropBW(%d), mRotatedSrcCropBW(%d)",
mNoRotatedSrcCropBW, mRotatedSrcCropBW);
for (uint32_t i = 0; i < mAssignedSources.size(); i++) {
float srcCycles = 0;
uint32_t srcResolution = mAssignedSources[i]->mSrcImg.w * mAssignedSources[i]->mSrcImg.h;
uint32_t dstResolution = mAssignedSources[i]->mMidImg.w * mAssignedSources[i]->mMidImg.h;
uint32_t maxResolution = max(srcResolution, dstResolution);
float PPC = getPPC(mAssignedSources[i]->mSrcImg, mAssignedSources[i]->mMidImg, mAssignedSources[i]->mSrcImg);
srcCycles = maxResolution/PPC;
cycles += srcCycles;
MPP_LOGD(eDebugCapacity, "Src[%d] cycles: %f, total cycles: %f, PPC: %f, srcResolution: %d, dstResolution: %d, rot(%d)",
i, srcCycles, cycles, PPC, srcResolution, dstResolution, mAssignedSources[i]->mSrcImg.transform);
}
mUsedBaseCycles = cycles;
capacity = cycles / mClockKhz;
mUsedCapacity = capacity;
}
MPP_LOGD(eDebugCapacity, "assigned layer size(%zu), mUsedCapacity: %f", mAssignedSources.size(), mUsedCapacity);
return mUsedCapacity;
}
uint32_t ExynosMPP::getRestrictionClassification(const struct exynos_image &img) const {
return !!(isFormatRgb(img.format) == false);
}
int ExynosMPP::prioritize(int priority)
{
if ((mPhysicalType != MPP_G2D) ||
(mAcrylicHandle == NULL)) {
MPP_LOGE("invalid function call");
return -1;
}
int ret = NO_ERROR;
ret = mAcrylicHandle->prioritize(priority);
if ((priority > 0) && (ret == 1))
{
/* G2D Driver returned EBUSY */
mHWBusyFlag = true;
}
MPP_LOGD(eDebugMPP, "set resource prioritize (%d), ret(%d), mHWBusyFlag(%d)", priority, ret, mHWBusyFlag);
return ret;
}
uint32_t ExynosMPP::increaseDstBuffIndex()
{
if (mAllocOutBufFlag)
mCurrentDstBuf = (mCurrentDstBuf + 1) % NUM_MPP_DST_BUFS(mLogicalType);
return mCurrentDstBuf;
}
void ExynosMPP::reloadResourceForHWFC()
{
ALOGI("reloadResourceForHWFC()");
delete mAcrylicHandle;
mAcrylicHandle = AcrylicFactory::createAcrylic("default_compositor");
if (mAcrylicHandle == NULL) {
MPP_LOGE("Fail to allocate compositor");
} else {
mAcrylicHandle->setDefaultColor(0, 0, 0, 0);
MPP_LOGI("The resource is reloaded for HWFC: %p", mAcrylicHandle);
}
for (uint32_t i = 0; i < NUM_MPP_SRC_BUFS; i++)
{
if (mSrcImgs[i].mppLayer != NULL) {
delete mSrcImgs[i].mppLayer;
mSrcImgs[i].mppLayer = NULL;
}
}
}
void ExynosMPP::setTargetDisplayLuminance(uint16_t min, uint16_t max)
{
MPP_LOGD(eDebugMPP, "%s: min(%d), max(%d)", __func__, min, max);
if (mAcrylicHandle == NULL) {
MPP_LOGE("mAcrylicHandle is NULL");
} else
mAcrylicHandle->setTargetDisplayLuminance(min, max);
}
void ExynosMPP::setTargetDisplayDevice(int device)
{
ALOGI("%s: device(%d)", __func__, device);
if (mAcrylicHandle == NULL) {
MPP_LOGE("mAcrylicHandle is NULL");
} else
mAcrylicHandle->setTargetDisplayInfo(&device);
}
void ExynosMPP::dump(String8& result)
{
int32_t assignedDisplayType = -1;
if (mAssignedDisplay != NULL)
assignedDisplayType = mAssignedDisplay->mType;
result.appendFormat("%s: types mppType(%d), (p:%d, l:0x%2x), indexs(p:%d, l:%d), preAssignDisplay(0x%2x)\n",
mName.string(), mMPPType, mPhysicalType, mLogicalType, mPhysicalIndex, mLogicalIndex, mPreAssignDisplayInfo);
result.appendFormat("\tEnable: %d, HWState: %d, AssignedState: %d, assignedDisplay(%d)\n",
mEnable, mHWState, mAssignedState, assignedDisplayType);
result.appendFormat("\tPrevAssignedState: %d, PrevAssignedDisplayType: %d, ReservedDisplay: %d\n",
mPrevAssignedState, mPrevAssignedDisplayType, mReservedDisplay);
result.appendFormat("\tassinedSourceNum(%zu), Capacity(%f), CapaUsed(%f), mCurrentDstBuf(%d)\n",
mAssignedSources.size(), mCapacity, mUsedCapacity, mCurrentDstBuf);
}
void ExynosMPP::closeFences()
{
for (uint32_t i = 0; i < mAssignedSources.size(); i++)
{
mSrcImgs[i].acrylicAcquireFenceFd =
fence_close(mSrcImgs[i].acrylicAcquireFenceFd, mAssignedDisplay,
FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_G2D);
mSrcImgs[i].acrylicReleaseFenceFd =
fence_close(mSrcImgs[i].acrylicReleaseFenceFd, mAssignedDisplay,
FENCE_TYPE_SRC_RELEASE, FENCE_IP_G2D);
}
mDstImgs[mCurrentDstBuf].acrylicAcquireFenceFd =
fence_close(mDstImgs[mCurrentDstBuf].acrylicAcquireFenceFd, mAssignedDisplay,
FENCE_TYPE_DST_ACQUIRE, FENCE_IP_G2D);
mDstImgs[mCurrentDstBuf].acrylicReleaseFenceFd =
fence_close(mDstImgs[mCurrentDstBuf].acrylicReleaseFenceFd, mAssignedDisplay,
FENCE_TYPE_DST_RELEASE, FENCE_IP_G2D);
}
void ExynosMPP::updateAttr()
{
MPP_LOGD(eDebugAttrSetting, "updateAttr::mPhysicalType(%d), mAttr(0x%" PRIx64 ")",
mPhysicalType, mAttr);
if (mResourceManager == NULL) return;
auto iter = mResourceManager->mMPPAttrs.find(mPhysicalType);
if (iter != mResourceManager->mMPPAttrs.end()) {
mAttr = iter->second;
MPP_LOGD(eDebugAttrSetting, "After mAttr(0x%" PRIx64 ")", mAttr);
}
}