From ee24aca7b8fbceab1011a4bb36b0baff08d9cdbc Mon Sep 17 00:00:00 2001 From: Adrian Salido Date: Mon, 17 Jul 2017 17:58:50 -0700 Subject: drm_hwcomposer: add checks for tegra hardware limitation Current approach is to allow atomic_check figure out any issues with composition strategy and fallback to squash if there the atomic_check fails. This leads to issues when there's a protected content as it cannot be handled in squash. Adding a new provisioning stage to check for hardware limitations and address them early so a proper fall back can be in place. Bug: 36731060 Change-Id: I6482953044bcea9c9a655f28672927b32ac57097 --- platformnv.cpp | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ platformnv.h | 13 +++++++++++ 2 files changed, 82 insertions(+) diff --git a/platformnv.cpp b/platformnv.cpp index 4a3a957..d3e5d70 100644 --- a/platformnv.cpp +++ b/platformnv.cpp @@ -22,6 +22,7 @@ #include #include +#include #include #include @@ -199,6 +200,7 @@ int NvImporter::GrallocSetNvBuffer(buffer_handle_t handle, NvBuffer_t *buf) { // static std::unique_ptr Planner::CreateInstance(DrmResources *) { std::unique_ptr planner(new Planner); + planner->AddStage(); planner->AddStage(); planner->AddStage(); planner->AddStage(); @@ -283,4 +285,71 @@ int PlanStageProtectedRotated::ProvisionPlanes( } return 0; } + +bool PlanStageNvLimits::CheckLayer(DrmHwcLayer *layer) { + auto src_w = layer->source_crop.width(); + auto src_h = layer->source_crop.height(); + auto dst_w = layer->display_frame.width(); + auto dst_h = layer->display_frame.height(); + int h_limit = 4; + int v_limit; + + switch (layer->buffer->format) { + case DRM_FORMAT_YVU420: + case DRM_FORMAT_BGR565: + v_limit = 4; + break; + default: + v_limit = 2; + break; + } + + if (layer->transform & + (DrmHwcTransform::kRotate90 | DrmHwcTransform::kRotate270)) + std::swap(dst_w, dst_h); + + // check for max supported down scaling + if (((src_w / dst_w) > h_limit) || ((src_h / dst_h) > v_limit)) + return false; + + return true; +} + +int PlanStageNvLimits::ProvisionPlanes( + std::vector *composition, + std::map &layers, DrmCrtc *crtc, + std::vector *planes) { + int ret; + + for (auto i = layers.begin(); i != layers.end();) { + // Skip layer if supported + if (CheckLayer(i->second)) { + i++; + continue; + } + + if (i->second->protected_usage()) { + // Drop the layer if unsupported and protected, this will just display + // black in the area of this layer but it's better than failing miserably + i = layers.erase(i); + continue; + } + + // If there's no precomp layer already queued, queue one now. + DrmCompositionPlane *precomp = GetPrecomp(composition); + if (precomp) { + precomp->source_layers().emplace_back(i->first); + } else if (!planes->empty()) { + DrmPlane *precomp_plane = planes->back(); + planes->pop_back(); + composition->emplace_back(DrmCompositionPlane::Type::kPrecomp, + precomp_plane, crtc, i->first); + } else { + ALOGE("Not enough planes to reserve for precomp fb"); + } + i = layers.erase(i); + } + + return 0; +} } diff --git a/platformnv.h b/platformnv.h index 678ccfa..3c1f49e 100644 --- a/platformnv.h +++ b/platformnv.h @@ -72,6 +72,19 @@ class PlanStageProtectedRotated : public Planner::PlanStage { std::map &layers, DrmCrtc *crtc, std::vector *planes); }; + +// This stage looks for layers that would not be supported by Tegra driver due +// to limitations such as downscaling. If the layer is unprotected it will be +// punted for precomp to handle, other wise if protected it will be dropped as +// it cannot be supported by any means. +class PlanStageNvLimits : public Planner::PlanStage { + public: + int ProvisionPlanes(std::vector *composition, + std::map &layers, DrmCrtc *crtc, + std::vector *planes); + protected: + bool CheckLayer(DrmHwcLayer *layer); +}; } #endif -- cgit v1.2.3