diff options
-rw-r--r-- | platformnv.cpp | 69 | ||||
-rw-r--r-- | platformnv.h | 13 |
2 files changed, 82 insertions, 0 deletions
diff --git a/platformnv.cpp b/platformnv.cpp index 084d4f0..9ea1467 100644 --- a/platformnv.cpp +++ b/platformnv.cpp @@ -22,6 +22,7 @@ #include <cinttypes> #include <stdatomic.h> +#include <drm/drm_fourcc.h> #include <xf86drm.h> #include <xf86drmMode.h> @@ -188,6 +189,7 @@ int NvImporter::GrallocSetNvBuffer(buffer_handle_t handle, NvBuffer_t *buf) { // static std::unique_ptr<Planner> Planner::CreateInstance(DrmResources *) { std::unique_ptr<Planner> planner(new Planner); + planner->AddStage<PlanStageNvLimits>(); planner->AddStage<PlanStageProtectedRotated>(); planner->AddStage<PlanStageProtected>(); planner->AddStage<PlanStagePrecomp>(); @@ -272,4 +274,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<DrmCompositionPlane> *composition, + std::map<size_t, DrmHwcLayer *> &layers, DrmCrtc *crtc, + std::vector<DrmPlane *> *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 a9e5d39..df2a242 100644 --- a/platformnv.h +++ b/platformnv.h @@ -71,6 +71,19 @@ class PlanStageProtectedRotated : public Planner::PlanStage { std::map<size_t, DrmHwcLayer *> &layers, DrmCrtc *crtc, std::vector<DrmPlane *> *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<DrmCompositionPlane> *composition, + std::map<size_t, DrmHwcLayer *> &layers, DrmCrtc *crtc, + std::vector<DrmPlane *> *planes); + protected: + bool CheckLayer(DrmHwcLayer *layer); +}; } #endif |