diff options
author | Yichi Chen <yichichen@google.com> | 2021-01-08 20:24:31 +0800 |
---|---|---|
committer | Yichi Chen <yichichen@google.com> | 2021-01-14 22:46:44 +0800 |
commit | e677d5cb14ece2127103a77f45f10d1848536cd6 (patch) | |
tree | ee2eed9111afb2aa946e91a8feb50063e63a7286 /libhwc2.1/libresource/ExynosResourceManager.cpp | |
parent | e97c480fd6deefb6b6c2e9cbd08774173394260d (diff) |
libhwc2.1: Support G2D plus DPP downscale
To support YouTube mini player with over 1/4 downscale request, it is
necessary to have G2D + DPP downscale to support 1/16 downscale instead
of falling back to client composition.
Bug: 176158392
Test: Enable YUV surface with 1/8, 1/16 downscale
Change-Id: I9300a7a78143fe5d4c7a1fa3b30edb224a02cb11
Diffstat (limited to 'libhwc2.1/libresource/ExynosResourceManager.cpp')
-rw-r--r-- | libhwc2.1/libresource/ExynosResourceManager.cpp | 243 |
1 files changed, 163 insertions, 80 deletions
diff --git a/libhwc2.1/libresource/ExynosResourceManager.cpp b/libhwc2.1/libresource/ExynosResourceManager.cpp index 622bf05..f4c0861 100644 --- a/libhwc2.1/libresource/ExynosResourceManager.cpp +++ b/libhwc2.1/libresource/ExynosResourceManager.cpp @@ -19,17 +19,21 @@ */ #define ATRACE_TAG (ATRACE_TAG_GRAPHICS | ATRACE_TAG_HAL) +#include "ExynosResourceManager.h" + #include <cutils/properties.h> + +#include <numeric> #include <unordered_set> -#include "ExynosResourceManager.h" -#include "ExynosMPPModule.h" -#include "ExynosLayer.h" + +#include "ExynosDeviceInterface.h" +#include "ExynosExternalDisplay.h" #include "ExynosHWCDebug.h" -#include "hardware/exynos/acryl.h" +#include "ExynosLayer.h" +#include "ExynosMPPModule.h" #include "ExynosPrimaryDisplayModule.h" #include "ExynosVirtualDisplay.h" -#include "ExynosExternalDisplay.h" -#include "ExynosDeviceInterface.h" +#include "hardware/exynos/acryl.h" #ifndef USE_MODULE_ATTR /* Basic supported features */ @@ -1125,6 +1129,158 @@ int32_t ExynosResourceManager::validateLayer(uint32_t index, ExynosDisplay *disp return NO_ERROR; } +exynos_image ExynosResourceManager::getAlignedImage(exynos_image image, const ExynosMPP *m2mMpp, + const ExynosMPP *otfMpp) const { + const auto srcCropWidthAlign = otfMpp->getSrcCropWidthAlign(image); + const auto srcCropHeightAlign = otfMpp->getSrcCropHeightAlign(image); + const auto dstwidthAlign = m2mMpp->getDstWidthAlign(image); + const auto dstHeightAlign = m2mMpp->getDstHeightAlign(image); + + const auto widthAlign = std::lcm(srcCropWidthAlign, dstwidthAlign); + const auto heighAlign = std::lcm(srcCropHeightAlign, dstHeightAlign); + + image.w = pixel_align(image.w, widthAlign); + image.h = pixel_align(image.h, heighAlign); + + return image; +} + +void ExynosResourceManager::getCandidateScalingM2mMPPOutImages( + const ExynosDisplay *display, exynos_image src_img, exynos_image dst_img, + std::vector<exynos_image> &image_lists) { + uint32_t dstW = dst_img.w; + uint32_t dstH = dst_img.h; + bool isPerpendicular = !!(src_img.transform & HAL_TRANSFORM_ROT_90); + if (isPerpendicular) { + dstW = dst_img.h; + dstH = dst_img.w; + } + + const bool scaleUp = (dstW > src_img.w && dstH > src_img.h); + const bool scaleDown = (dstW < src_img.w && dstH < src_img.h); + + if (!scaleUp && !scaleDown) { + return; + } + + /* otfMPP doesn't rotate image, m2mMPP rotates image */ + exynos_image dst_scale_img = dst_img; + dst_scale_img.transform = src_img.transform; + src_img.transform = 0; + + if (hasHdrInfo(src_img)) { + if (isFormatYUV(src_img.format)) + dst_scale_img.format = HAL_PIXEL_FORMAT_YCBCR_P010; + else + dst_scale_img.format = HAL_PIXEL_FORMAT_RGBA_1010102; + } else { + if (isFormatYUV(src_img.format)) { + dst_scale_img.format = DEFAULT_MPP_DST_YUV_FORMAT; + } + } + + const uint32_t reqRatio = (scaleUp ? max((dstW - 1) / src_img.w, (dstH - 1) / src_img.h) + : max((src_img.w - 1) / dstW, (src_img.h - 1) / dstH)) + + 1; + + ExynosMPP *otfMpp = nullptr; + ExynosMPP *m2mMpp = nullptr; + uint32_t otfMppRatio = 1; + uint32_t m2mMppRatio = 1; + if (scaleUp) { + std::find_if(mOtfMPPs.begin(), mOtfMPPs.end(), + [&dst_scale_img, &dst_img, &otfMpp, &otfMppRatio](auto m) { + auto ratio = m->getMaxUpscale(dst_scale_img, dst_img); + if (ratio > 1) { + otfMpp = m; + otfMppRatio = ratio; + return true; + } + return false; + }); + std::find_if(mM2mMPPs.begin(), mM2mMPPs.end(), + [&src_img, &dst_scale_img, otfMppRatio, reqRatio, &m2mMpp, + &m2mMppRatio](auto m) { + auto ratio = m->getMaxUpscale(src_img, dst_scale_img); + if (ratio * otfMppRatio >= reqRatio) { + m2mMpp = m; + m2mMppRatio = ratio; + return true; + } + return false; + }); + } else { + std::find_if(mM2mMPPs.begin(), mM2mMPPs.end(), + [&src_img, &dst_scale_img, display, &m2mMpp, &m2mMppRatio](auto m) { + auto ratio = m->getMaxDownscale(*display, src_img, dst_scale_img); + if (ratio > 1) { + m2mMpp = m; + m2mMppRatio = ratio; + return true; + } + return false; + }); + std::find_if(mOtfMPPs.begin(), mOtfMPPs.end(), + [&dst_scale_img, &dst_img, display, m2mMppRatio, reqRatio, &otfMpp, + &otfMppRatio](auto m) { + auto ratio = m->getMaxDownscale(*display, dst_scale_img, dst_img); + if (ratio * m2mMppRatio >= reqRatio) { + otfMpp = m; + otfMppRatio = ratio; + return true; + } + return false; + }); + } + + if (!otfMpp || !m2mMpp) { + HDEBUGLOGD(eDebugResourceManager, + "Cannot find available MPP for scaling w: %d, h: %d, ratio %d", dst_scale_img.w, + dst_scale_img.h, reqRatio); + return; + } + + dst_scale_img.x = 0; + dst_scale_img.y = 0; + dst_scale_img.w = scaleDown ? dst_img.w : isPerpendicular ? src_img.h : src_img.w; + dst_scale_img.h = scaleDown ? dst_img.h : isPerpendicular ? src_img.w : src_img.h; + + HDEBUGLOGD(eDebugResourceManager, + "scaling w: %d, h: %d, ratio %d = (otfType %d - %d, m2mType %d - %d)", + dst_scale_img.w, dst_scale_img.h, reqRatio, otfMpp->mLogicalType, otfMppRatio, + m2mMpp->mLogicalType, m2mMppRatio); + if (scaleUp) { + if (dst_scale_img.w * otfMppRatio < dst_img.w) { + dst_scale_img.w = uint32_t(ceilf(float(dst_img.w) / float(otfMppRatio))); + } + if (dst_scale_img.h * otfMppRatio < dst_img.h) { + dst_scale_img.h = uint32_t(ceilf(float(dst_img.h) / float(otfMppRatio))); + } + } else { + if (dst_scale_img.w * m2mMppRatio < src_img.w) { + dst_scale_img.w = uint32_t(ceilf(float(src_img.w) / float(m2mMppRatio))); + } + if (dst_scale_img.h * m2mMppRatio < src_img.h) { + dst_scale_img.h = uint32_t(ceilf(float(src_img.h) / float(m2mMppRatio))); + } + } + HDEBUGLOGD(eDebugResourceManager, + "\tsrc[%d, %d, %d,%d], dst[%d, %d, %d,%d], mid[%d, %d, %d, %d]", src_img.x, + src_img.y, src_img.w, src_img.h, dst_img.x, dst_img.y, dst_img.w, dst_img.h, + dst_scale_img.x, dst_scale_img.y, dst_scale_img.w, dst_scale_img.h); + + if (isFormatSBWC(dst_scale_img.format)) { + image_lists.emplace_back(getAlignedImage(dst_scale_img, m2mMpp, otfMpp)); + /* + * SBWC format could not be supported in specific dst size + * Add uncompressed YUV format to cover this size + */ + dst_scale_img.format = DEFAULT_MPP_DST_UNCOMP_YUV_FORMAT; + } + + image_lists.emplace_back(getAlignedImage(dst_scale_img, m2mMpp, otfMpp)); +} + int32_t ExynosResourceManager::getCandidateM2mMPPOutImages(ExynosDisplay *display, ExynosLayer *layer, std::vector<exynos_image> &image_lists) { @@ -1144,80 +1300,7 @@ int32_t ExynosResourceManager::getCandidateM2mMPPOutImages(ExynosDisplay *displa /* Copy origin source HDR metadata */ dst_img.metaParcel = src_img.metaParcel; - uint32_t dstW = dst_img.w; - uint32_t dstH = dst_img.h; - bool isPerpendicular = !!(src_img.transform & HAL_TRANSFORM_ROT_90); - if (isPerpendicular) { - dstW = dst_img.h; - dstH = dst_img.w; - } - - /* Scale up case */ - if ((dstW > src_img.w) && (dstH > src_img.h)) - { - /* otfMPP doesn't rotate image, m2mMPP rotates image */ - src_img.transform = 0; - exynos_image dst_scale_img = dst_img; - - ExynosMPP *otfMppForScale = nullptr; - auto mpp_it = std::find_if(mOtfMPPs.begin(), mOtfMPPs.end(), - [&src_img, &dst_scale_img](auto m) { - return (m->getMaxUpscale(src_img, dst_scale_img) > 1); - }); - otfMppForScale = mpp_it == mOtfMPPs.end() ? nullptr : *mpp_it; - - if (hasHdrInfo(src_img)) { - if (isFormatYUV(src_img.format)) - dst_scale_img.format = HAL_PIXEL_FORMAT_YCBCR_P010; - else - dst_scale_img.format = HAL_PIXEL_FORMAT_RGBA_1010102; - } else { - if (isFormatYUV(src_img.format)) { - dst_scale_img.format = DEFAULT_MPP_DST_YUV_FORMAT; - } - } - - if (otfMppForScale) { - uint32_t upScaleRatio = otfMppForScale->getMaxUpscale(src_img, dst_scale_img); - uint32_t downScaleRatio = otfMppForScale->getMaxDownscale(*display, src_img, dst_scale_img); - uint32_t srcCropWidthAlign = otfMppForScale->getSrcCropWidthAlign(src_img); - uint32_t srcCropHeightAlign = otfMppForScale->getSrcCropHeightAlign(src_img); - - dst_scale_img.x = 0; - dst_scale_img.y = 0; - if (isPerpendicular) { - dst_scale_img.w = pixel_align(src_img.h, srcCropWidthAlign); - dst_scale_img.h = pixel_align(src_img.w, srcCropHeightAlign); - } else { - dst_scale_img.w = pixel_align(src_img.w, srcCropWidthAlign); - dst_scale_img.h = pixel_align(src_img.h, srcCropHeightAlign); - } - - HDEBUGLOGD(eDebugResourceManager, "scale up w: %d, h: %d, ratio(type: %d, %d, %d)", - dst_scale_img.w, dst_scale_img.h, - otfMppForScale->mLogicalType, upScaleRatio, downScaleRatio); - if (dst_scale_img.w * upScaleRatio < dst_img.w) { - dst_scale_img.w = pixel_align((uint32_t)ceilf((float)dst_img.w/(float)upScaleRatio), srcCropWidthAlign); - } - if (dst_scale_img.h * upScaleRatio < dst_img.h) { - dst_scale_img.h = pixel_align((uint32_t)ceilf((float)dst_img.h/(float)upScaleRatio), srcCropHeightAlign); - } - HDEBUGLOGD(eDebugResourceManager, "\tsrc[%d, %d, %d,%d], dst[%d, %d, %d,%d], mid[%d, %d, %d, %d]", - src_img.x, src_img.y, src_img.w, src_img.h, - dst_img.x, dst_img.y, dst_img.w, dst_img.h, - dst_scale_img.x, dst_scale_img.y, dst_scale_img.w, dst_scale_img.h); - image_lists.push_back(dst_scale_img); - - if (isFormatSBWC(dst_scale_img.format)) { - /* - * SBWC format could not be supported in specific dst size - * Add uncompressed YUV format to cover this size - */ - dst_scale_img.format = DEFAULT_MPP_DST_UNCOMP_YUV_FORMAT; - image_lists.push_back(dst_scale_img); - } - } - } + getCandidateScalingM2mMPPOutImages(display, src_img, dst_img, image_lists); if (isFormatYUV(src_img.format) && !hasHdrInfo(src_img)) { dst_img.format = DEFAULT_MPP_DST_YUV_FORMAT; |