/* * Copyright (C) 2019 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 "ExynosDeviceInterface.h" #include #include #include #include "ExynosDevice.h" #include "ExynosHWCDebug.h" #include "ExynosMPP.h" #include "ExynosResourceManager.h" #include "ExynosResourceRestriction.h" #ifndef USE_MODULE_ATTR extern feature_support_t feature_table[]; #endif void ExynosDeviceInterface::printDppRestriction(struct hwc_dpp_ch_restriction res) { ALOGD("========================================================="); ALOGD("id: %d", res.id); ALOGD("hwc_dpp_restriction"); ALOGD("src_f_w (%d, %d, %d)", res.restriction.src_f_w.min, res.restriction.src_f_w.max, res.restriction.src_f_w.align); ALOGD("src_f_h (%d, %d, %d)", res.restriction.src_f_h.min, res.restriction.src_f_h.max, res.restriction.src_f_h.align); ALOGD("src_w (%d, %d, %d)", res.restriction.src_w.min, res.restriction.src_w.max, res.restriction.src_w.align); ALOGD("src_h (%d, %d, %d)", res.restriction.src_h.min, res.restriction.src_h.max, res.restriction.src_h.align); ALOGD("src_x_align(%d), src_y_align(%d)", res.restriction.src_x_align, res.restriction.src_y_align); ALOGD("dst_f_w (%d, %d, %d)", res.restriction.dst_f_w.min, res.restriction.dst_f_w.max, res.restriction.dst_f_w.align); ALOGD("dst_f_h (%d, %d, %d)", res.restriction.dst_f_h.min, res.restriction.dst_f_h.max, res.restriction.dst_f_h.align); ALOGD("dst_w (%d, %d, %d)", res.restriction.dst_w.min, res.restriction.dst_w.max, res.restriction.dst_w.align); ALOGD("dst_h (%d, %d, %d)", res.restriction.dst_h.min, res.restriction.dst_h.max, res.restriction.dst_h.align); ALOGD("dst_x_align(%d), dst_y_align(%d)", res.restriction.dst_x_align, res.restriction.dst_y_align); ALOGD("src_h_rot_max(%d)", res.restriction.src_h_rot_max); ALOGD("blk_w (%d, %d, %d)", res.restriction.blk_w.min, res.restriction.blk_w.max, res.restriction.blk_w.align); ALOGD("blk_h (%d, %d, %d)", res.restriction.blk_h.min, res.restriction.blk_h.max, res.restriction.blk_h.align); ALOGD("blk_x_align(%d), blk_y_align(%d)", res.restriction.blk_x_align, res.restriction.blk_y_align); ALOGD("format cnt: %zu", res.restriction.formats.size()); for(int i = 0; i < res.restriction.formats.size(); i++) { ALOGD("[%d] format: %d", i, res.restriction.formats[i]); } ALOGD("scale down: %d, up: %d", res.restriction.scale_down, res.restriction.scale_up); ALOGD("attr: 0x%lx", res.attr); } int32_t ExynosDeviceInterface::makeDPURestrictions() { #ifdef DISABLE_READ_RESTRICTIONS return -EINVAL; #endif int32_t ret = 0; struct hwc_dpp_restrictions_info *dpuInfo = &mDPUInfo.dpuInfo; HDEBUGLOGD(eDebugAttrSetting, "DPP ver : %d, cnt : %zu", dpuInfo->ver, dpuInfo->dpp_chs.size()); ExynosResourceManager *resourceManager = mExynosDevice->mResourceManager; /* format resctriction */ for (int i = 0; i < dpuInfo->dpp_chs.size(); i++){ hwc_dpp_restriction r = dpuInfo->dpp_chs[i].restriction; HDEBUGLOGD(eDebugAttrSetting, "id : %d, format count : %zu", i, r.formats.size()); } /* Check attribute overlap */ std::unordered_set attrs; for (size_t i = 0; i < dpuInfo->dpp_chs.size(); ++i) { const hwc_dpp_ch_restriction &r = dpuInfo->dpp_chs[i]; if (attrs.find(r.attr) != attrs.end()) mDPUInfo.overlap[i] = true; else attrs.insert(r.attr); HDEBUGLOGD(eDebugAttrSetting, "Index : %zu, overlap %d", i, mDPUInfo.overlap[i]); } for (int i = 0; i < dpuInfo->dpp_chs.size(); i++){ if (mDPUInfo.overlap[i]) continue; hwc_dpp_restriction r = dpuInfo->dpp_chs[i].restriction; mpp_phycal_type_t hwType = resourceManager->getPhysicalType(i); for (auto &format: r.formats) { restriction_key_t queried_format; queried_format.hwType = hwType; queried_format.nodeType = NODE_NONE; /* format is HAL format */ queried_format.format = format; queried_format.reserved = 0; resourceManager->makeFormatRestrictions(queried_format); HDEBUGLOGD(eDebugAttrSetting, "%s : %d", getMPPStr(hwType).string(), format); } } for (int i = 0; i < dpuInfo->dpp_chs.size(); i++){ if (mDPUInfo.overlap[i]) continue; const hwc_dpp_restriction &r = dpuInfo->dpp_chs[i].restriction; /* RGB size restrictions */ restriction_size rSize; rSize.maxDownScale = r.scale_down; rSize.maxUpScale = r.scale_up; rSize.maxFullWidth = r.dst_f_w.max; rSize.maxFullHeight = r.dst_f_h.max; rSize.minFullWidth = r.dst_f_w.min; rSize.minFullHeight = r.dst_f_h.min;; rSize.fullWidthAlign = r.dst_x_align; rSize.fullHeightAlign = r.dst_y_align;; rSize.maxCropWidth = r.src_w.max; rSize.maxCropHeight = r.src_h.max; rSize.minCropWidth = r.src_w.min; rSize.minCropHeight = r.src_h.min; rSize.cropXAlign = r.src_x_align; rSize.cropYAlign = r.src_y_align; rSize.cropWidthAlign = r.blk_x_align; rSize.cropHeightAlign = r.blk_y_align; mpp_phycal_type_t hwType = resourceManager->getPhysicalType(i); if (hwType <= MPP_DPP_NUM) { auto newMaxDownscale = static_cast(property_get_int32("vendor.hwc.dpp.downscale", 0)); if (newMaxDownscale != 0) { rSize.maxDownScale = min(rSize.maxDownScale, newMaxDownscale); ALOGI("%s:: Apply DPP downscale restriction on 1/%d", __func__, rSize.maxDownScale); } } resourceManager->makeSizeRestrictions(hwType, rSize, RESTRICTION_RGB); /* YUV size restrictions */ rSize.minCropWidth = 32; //r.src_w.min; rSize.minCropHeight = 32; //r.src_h.min; rSize.fullWidthAlign = max(r.dst_x_align, YUV_CHROMA_H_SUBSAMPLE); rSize.fullHeightAlign = max(r.dst_y_align, YUV_CHROMA_V_SUBSAMPLE); rSize.cropXAlign = max(r.src_x_align, YUV_CHROMA_H_SUBSAMPLE); rSize.cropYAlign = max(r.src_y_align, YUV_CHROMA_V_SUBSAMPLE); rSize.cropWidthAlign = max(r.blk_x_align, YUV_CHROMA_H_SUBSAMPLE); rSize.cropHeightAlign = max(r.blk_y_align, YUV_CHROMA_V_SUBSAMPLE); resourceManager->makeSizeRestrictions(hwType, rSize, RESTRICTION_YUV); } for (auto it: resourceManager->getOtfMPPs()) { if (mDPUInfo.dpuInfo.ppc) it->setPPC(static_cast(mDPUInfo.dpuInfo.ppc)); if (mDPUInfo.dpuInfo.max_disp_freq) it->setClockKhz(mDPUInfo.dpuInfo.max_disp_freq); } return ret; } int32_t ExynosDeviceInterface::updateFeatureTable() { const struct hwc_dpp_restrictions_info &dpuInfo = mDPUInfo.dpuInfo; if (mExynosDevice->mResourceManager == NULL) return -1; const ExynosResourceManager &resourceManager = *(mExynosDevice->mResourceManager); const uint32_t featureTableCnt = resourceManager.getFeatureTableSize(); const int attrMapCnt = sizeof(dpu_attr_map_table)/sizeof(dpu_attr_map_t); const int dpp_cnt = dpuInfo.dpp_chs.size(); HDEBUGLOGD(eDebugAttrSetting, "Before"); for (uint32_t j = 0; j < featureTableCnt; j++){ HDEBUGLOGD(eDebugAttrSetting, "type : %d, feature : 0x%lx", feature_table[j].hwType, (unsigned long)feature_table[j].attr); } // dpp count for (int i = 0; i < dpp_cnt; i++){ hwc_dpp_ch_restriction c_r = dpuInfo.dpp_chs[i]; if (mDPUInfo.overlap[i]) continue; HDEBUGLOGD(eDebugAttrSetting, "DPU attr : (ch:%d), 0x%lx", i, (unsigned long)c_r.attr); mpp_phycal_type_t hwType = resourceManager.getPhysicalType(i); // feature table count for (uint32_t j = 0; j < featureTableCnt; j++){ if (feature_table[j].hwType == hwType) { uint64_t attr = 0; // dpp attr count for (int k = 0; k < attrMapCnt; k++) { if (c_r.attr & (1 << dpu_attr_map_table[k].dpp_attr)) { attr |= dpu_attr_map_table[k].hwc_attr; } } auto it = sw_feature_table.find(hwType); if (it != sw_feature_table.end()) attr |= it->second; feature_table[j].attr = attr; } } } HDEBUGLOGD(eDebugAttrSetting, "After"); for (uint32_t j = 0; j < featureTableCnt; j++){ HDEBUGLOGD(eDebugAttrSetting, "type : %d, feature : 0x%lx", feature_table[j].hwType, (unsigned long)feature_table[j].attr); mExynosDevice->mResourceManager->mMPPAttrs.insert(std::make_pair((uint32_t)feature_table[j].hwType, (uint64_t)feature_table[j].attr)); } return 0; }