blob: aa19e021e3016a794bd6c7ad84e86e448d0ffae0 [file] [log] [blame]
/*
* Copyright (C) 2012 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "ExynosMPPModule.h"
#include "ExynosHWCDebug.h"
#include <hardware/exynos/hdrInterface.h>
ExynosMPPModule::ExynosMPPModule(uint32_t physicalType, uint32_t logicalType,
const char *name, uint32_t physicalIndex, uint32_t logicalIndex,
uint32_t preAssignInfo, uint32_t mppType)
: ExynosMPP(physicalType, logicalType, name, physicalIndex, logicalIndex, preAssignInfo, mppType)
{
}
ExynosMPPModule::~ExynosMPPModule()
{
}
uint32_t ExynosMPPModule::getMPPClock()
{
if (mPhysicalType == MPP_G2D)
return 667000;
else
return 0;
}
bool ExynosMPPModule::isDataspaceSupportedByMPP(struct exynos_image &src, struct exynos_image &dst)
{
if ((mLogicalType == MPP_LOGICAL_G2D_YUV) &&
(hasHdrInfo(src)) && (dst.exynosFormat == HAL_PIXEL_FORMAT_YCBCR_P010) &&
(src.dataSpace == dst.dataSpace))
return false;
return ExynosMPP::isDataspaceSupportedByMPP(src, dst);
}
#ifdef USE_HDR_INTERFACE
bool ExynosMPPModule::isQualifiedHDRPipeRestriction(DisplayInfo &display,
struct exynos_image &src, struct exynos_image &dst)
{
bool ret = true;
if (mPhysicalType == MPP_G2D) {
android_dataspace_t src_dataSpace = src.dataSpace;
android_dataspace_t dst_dataSpace = getDstDataspace(dst.exynosFormat.halFormat(), display, dst.dataSpace);
int hdrError = 0;
struct hdrCoef output[MPP_G2D_HDR_PIPE_NUM];
int hdr_map[MPP_G2D_HDR_PIPE_NUM];
/* If G2D doesn't support WCG and color mode is NATIVE,
* G2D can composit layers without WCG processing.
* So we will return true forcely if it meets the condition. */
if ((mMaxSrcLayerNum > 1) && ((mAttr & MPP_ATTR_WCG) == 0) &&
(display.colorMode == HAL_COLOR_MODE_NATIVE))
return true;
memset(&output, 0, sizeof(struct hdrCoef) * MPP_G2D_HDR_PIPE_NUM);
memset(&hdr_map, 0, sizeof(int) * MPP_G2D_HDR_PIPE_NUM);
if (hasHdrInfo(src) && src.metaParcel)
mAssignedLuminance.push(src.metaParcel->sHdrStaticInfo.sType1.mMaxDisplayLuminance/10000);
else
mAssignedLuminance.push(0);
/* Google gave guide that HAL_DATSPACE_UNKNOWN should trigger
the same behavior in HWC as HAL_DATASPACE_V0_SRGB. (11251035)
So we modified data space from UNKNOWN to V0_SRGB */
if (src_dataSpace == HAL_DATASPACE_UNKNOWN) {
if (src.exynosFormat.isRgb())
src_dataSpace = HAL_DATASPACE_V0_SRGB;
else
src_dataSpace = HAL_DATASPACE_V0_BT601_625;
}
mAssignedDataspace.push(src_dataSpace);
if (dst_dataSpace == HAL_DATASPACE_UNKNOWN)
dst_dataSpace = HAL_DATASPACE_V0_SRGB;
if ((hdrError = mHdrCoefInterface->getHdrCoef(
const_cast<android_dataspace *>(mAssignedDataspace.array()),
const_cast<int *>(mAssignedLuminance.array()),
mAssignedDataspace.size(), dst_dataSpace, 0,
output, hdr_map)) < 0) {
ret = false;
/* TODO: Need to change to check enum */
if (hdrError != -2)
MPP_LOGE("%s:: getHdrCoef error(%d)", __func__, hdrError);
MPP_LOGD(eDebugMPP, "getHdrCoef ret(%d)", hdrError);
}
mAssignedDataspace.pop();
mAssignedLuminance.pop();
}
return ret;
}
int32_t ExynosMPPModule::resetMPP()
{
int32_t ret = ExynosMPP::resetMPP();
if (mPhysicalType == MPP_G2D) {
mAssignedDataspace.clear();
mAssignedLuminance.clear();
}
return ret;
}
int32_t ExynosMPPModule::resetAssignedState()
{
int32_t ret = ExynosMPP::resetAssignedState();
for (int i = (int)mAssignedSources.size(); i-- > 0;) {
if (mPhysicalType == MPP_G2D) {
mAssignedDataspace.removeItemsAt(i);
mAssignedLuminance.removeItemsAt(i);
}
}
return ret;
}
int32_t ExynosMPPModule::resetAssignedState(ExynosMPPSource *mppSource)
{
int32_t ret = ExynosMPP::resetAssignedState(mppSource);
for (int i = (int)mAssignedSources.size(); i-- > 0;) {
if (mAssignedSources[i] == mppSource) {
if (mPhysicalType == MPP_G2D) {
mAssignedDataspace.removeItemsAt(i);
mAssignedLuminance.removeItemsAt(i);
}
}
}
return ret;
}
bool ExynosMPPModule::isAssignableState(DisplayInfo &display, struct exynos_image &src, struct exynos_image &dst)
{
bool ret = ExynosMPP::isAssignableState(display, src, dst);
if (ret)
return isQualifiedHDRPipeRestriction(display, src, dst);
else
return false;
}
int32_t ExynosMPPModule::setG2DColorConversionInfo()
{
int32_t ret = 0;
if (mPhysicalType == MPP_G2D) {
struct hdrCoef output[MPP_G2D_HDR_PIPE_NUM];
int hdr_map[MPP_G2D_HDR_PIPE_NUM];
int hdrError = 0;
int sourceNum = mAssignedSources.size();
memset(&output, 0, sizeof(struct hdrCoef) * MPP_G2D_HDR_PIPE_NUM);
memset(&hdr_map, 0, sizeof(int) * MPP_G2D_HDR_PIPE_NUM);
Vector<android_dataspace> assignedDataspace;
Vector<int> assignedLuminance;
android_dataspace_t dst_dataSpace = mDstImgs[mCurrentDstBuf].dataspace;
String8 log;
/* If G2D doesn't support WCG and color mode is NATIVE,
* G2D can composit layers without WCG processing.
* So we will return true forcely if it meets the condition. */
if ((mMaxSrcLayerNum > 1) && ((mAttr & MPP_ATTR_WCG) == 0) &&
(mAssignedDisplayInfo.displayIdentifier.id != UINT32_MAX) &&
(mAssignedDisplayInfo.colorMode == HAL_COLOR_MODE_NATIVE)) {
mAcrylicHandle->clearLibHdrCoefficient();
return ret;
}
if (sourceNum > 1) {
assignedDataspace.add(HAL_DATASPACE_V0_SRGB);
assignedLuminance.add(0);
}
for (size_t i = 0; i < sourceNum; i++) {
android_dataspace src_dataSpace = mAssignedSources[i]->mSrcImg.dataSpace;
/* Google gave guide that HAL_DATSPACE_UNKNOWN should trigger
the same behavior in HWC as HAL_DATASPACE_V0_SRGB. (11251035)
So we modified data space from UNKNOWN to V0_SRGB */
if (src_dataSpace == HAL_DATASPACE_UNKNOWN) {
if (mAssignedSources[i]->mSrcImg.exynosFormat.isRgb())
src_dataSpace = HAL_DATASPACE_V0_SRGB;
else
src_dataSpace = HAL_DATASPACE_V0_BT601_625;
}
assignedDataspace.add(src_dataSpace);
if (hasHdrInfo(mAssignedSources[i]->mSrcImg) &&
mAssignedSources[i]->mSrcImg.metaParcel)
assignedLuminance.add(mAssignedSources[i]->mSrcImg.metaParcel->sHdrStaticInfo.sType1.mMaxDisplayLuminance/10000);
else
assignedLuminance.add(0);
}
if (dst_dataSpace == HAL_DATASPACE_UNKNOWN)
dst_dataSpace = HAL_DATASPACE_V0_SRGB;
if ((hdrError = mHdrCoefInterface->getHdrCoef(
const_cast<android_dataspace *>(assignedDataspace.array()),
const_cast<int *>(assignedLuminance.array()),
assignedDataspace.size(), dst_dataSpace, 0,
output, hdr_map)) == NO_ERROR) {
/* Propagate hdr coef to libacryl */
mAcrylicHandle->setLibHdrCoefficient(hdr_map, output);
} else {
if (hdrError < 0)
MPP_LOGE("%s:: getHdrCoef error(%d)", __func__, hdrError);
/*
* It is error case if the return value is minus.
* There is no layer that needs conversion
* if return value is positive number.
* Clear hdr coef setting for libacryl in those cases
*/
/* Clear hdr coef setting to libacryl */
mAcrylicHandle->clearLibHdrCoefficient();
}
}
return ret;
}
int32_t ExynosMPPModule::assignMPP(DisplayInfo &display, ExynosMPPSource *mppSource)
{
int32_t ret = ExynosMPP::assignMPP(display, mppSource);
if (mPhysicalType == MPP_G2D) {
android_dataspace src_dataSpace = mppSource->mSrcImg.dataSpace;
if ((mNeedSolidColorLayer == true) && (mAssignedDataspace.size() == 0)) {
mAssignedDataspace.add(HAL_DATASPACE_V0_SRGB);
mAssignedLuminance.add(0);
}
/* Google gave guide that HAL_DATSPACE_UNKNOWN should trigger
the same behavior in HWC as HAL_DATASPACE_V0_SRGB. (11251035)
So we modified data space from UNKNOWN to V0_SRGB */
if (src_dataSpace == HAL_DATASPACE_UNKNOWN) {
if (mppSource->mSrcImg.exynosFormat.isRgb())
src_dataSpace = HAL_DATASPACE_V0_SRGB;
else
src_dataSpace = HAL_DATASPACE_V0_BT601_625;
}
mAssignedDataspace.add(src_dataSpace);
if (hasHdrInfo(mppSource->mSrcImg) && mppSource->mSrcImg.metaParcel)
mAssignedLuminance.add(mppSource->mSrcImg.metaParcel->sHdrStaticInfo.sType1.mMaxDisplayLuminance/10000);
else
mAssignedLuminance.add(0);
}
return ret;
}
int32_t ExynosMPPModule::doPostProcessingInternal()
{
int32_t ret = 0;
if (mAcrylicHandle == NULL) {
MPP_LOGE("%s:: mAcrylicHandle is NULL", __func__);
return -EINVAL;
}
if (mPhysicalType == MPP_G2D) {
if ((ret = setG2DColorConversionInfo()) != NO_ERROR) {
MPP_LOGE("%s:: fail to setColorConversionInfo ret %d", __func__, ret);
return ret;
}
}
return ExynosMPP::doPostProcessingInternal();
}
#endif