2902 lines
106 KiB
C++
2902 lines
106 KiB
C++
/*
|
|
* 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_MAX),
|
|
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(android::sp<ResourceManageThread>::make(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 displayRatio_V) const {
|
|
if (mPhysicalType >= MPP_DPP_NUM) return true;
|
|
|
|
return float(mClockKhz) >= ((resolution * VPP_RESOL_MARGIN) / (mPPC * displayRatio_V));
|
|
}
|
|
|
|
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) {
|
|
float resolution = float(src.w) * float(src.h) * display.getBtsRefreshRate() / 1000;
|
|
if (!checkDownscaleCap(resolution, float(dst.h) / float(display.mYres))) {
|
|
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);
|
|
if (!needCompressDstBuf()) {
|
|
allocUsage |= VendorGraphicBufferUsage::NO_AFBC;
|
|
}
|
|
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;
|
|
}
|
|
|
|
return allocUsage;
|
|
}
|
|
|
|
bool ExynosMPP::needCompressDstBuf() const {
|
|
return (mMaxSrcLayerNum > 1) && mNeedCompressedTarget;
|
|
}
|
|
|
|
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) afbc (%u) sbwc (%u) lossy (%u)", dst_handle,
|
|
isAFBCCompressed(dst_handle), isFormatSBWC(gmeta.format), isFormatLossy(gmeta.format));
|
|
MPP_LOGD(eDebugMPP | eDebugBuf,
|
|
"\tAssignedDisplay[%d, %d] format[0x%8x, 0x%8x], bufferType[%d, %d], usageFlags: "
|
|
"0x%" PRIx64 ", need afbc %u sbwc %u lossy %u",
|
|
mPrevAssignedDisplayType, assignedDisplay, gmeta.format, dst.format,
|
|
mDstImgs[index].bufferType, getBufferType(dst.usageFlags), dst.usageFlags,
|
|
dst.compressed, isFormatSBWC(dst.format), isFormatLossy(dst.format));
|
|
|
|
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)) ||
|
|
(isAFBCCompressed(dst_handle) != dst.compressed) ||
|
|
(isFormatSBWC(gmeta.format) != isFormatSBWC(dst.format)) ||
|
|
(isFormatLossy(gmeta.format) != isFormatLossy(dst.format));
|
|
|
|
MPP_LOGD(eDebugMPP|eDebugBuf, "realloc: %d--------", realloc);
|
|
return realloc;
|
|
}
|
|
|
|
bool ExynosMPP::canUsePrevFrame()
|
|
{
|
|
if ((mAssignedDisplay && !mAssignedDisplay->mDisplayControl.skipM2mProcessing) ||
|
|
!exynosHWCControl.skipM2mProcessing)
|
|
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, HwcFenceDirection::TO);
|
|
} else if (mPhysicalType == MPP_MSC) {
|
|
setFenceName(srcImgInfo->acrylicAcquireFenceFd, FENCE_MSC_SRC_LAYER);
|
|
setFenceInfo(srcImgInfo->acrylicAcquireFenceFd, mAssignedDisplay, FENCE_TYPE_SRC_ACQUIRE,
|
|
FENCE_IP_MSC, HwcFenceDirection::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 (needCompressDstBuf()) {
|
|
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, HwcFenceDirection::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, HwcFenceDirection::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, HwcFenceDirection::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, HwcFenceDirection::FROM);
|
|
}
|
|
}
|
|
} else if (mPhysicalType == MPP_MSC) {
|
|
setFenceInfo(releaseFences[dstBufIdx], mAssignedDisplay, FENCE_TYPE_DST_ACQUIRE,
|
|
FENCE_IP_MSC, HwcFenceDirection::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, HwcFenceDirection::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;
|
|
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);
|
|
}
|
|
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;
|
|
|
|
img->compressed = needCompressDstBuf();
|
|
|
|
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 (dst.w > maxDstWidth)
|
|
return -eMPPExeedMaxDstWidth;
|
|
else if (dst.h > maxDstHeight)
|
|
return -eMPPExeedMaxDstHeight;
|
|
else if (dst.w < minDstWidth)
|
|
return -eMPPExeedMinDstWidth;
|
|
else if (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 ((dst.w % dstWidthAlign != 0) || (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 displayId)
|
|
{
|
|
mAssignedState |= MPP_ASSIGN_STATE_RESERVED;
|
|
mReservedDisplay = displayId;
|
|
|
|
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->getId()) {
|
|
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->getId())
|
|
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, AFBC 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 (src.compressed == 1) {
|
|
if ((isFormatRgb(criteria.format)) && hasPPC(mPhysicalType, PPC_FORMAT_AFBC_RGB, PPC_ROT_NO))
|
|
formatIndex = PPC_FORMAT_AFBC_RGB;
|
|
else if ((isFormatYUV(criteria.format)) && hasPPC(mPhysicalType, PPC_FORMAT_AFBC_YUV, PPC_ROT_NO))
|
|
formatIndex = PPC_FORMAT_AFBC_YUV;
|
|
else {
|
|
formatIndex = PPC_FORMAT_RGB32;
|
|
MPP_LOGW("%s:: AFBC PPC is not existed. Use default PPC", __func__);
|
|
}
|
|
} else if (isFormatP010(criteria.format) && hasPPC(mPhysicalType, PPC_FORMAT_P010, PPC_ROT_NO))
|
|
formatIndex = PPC_FORMAT_P010;
|
|
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
|
|
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);
|
|
}
|
|
}
|
|
|