1 /* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef ANDROID_DRM_PLATFORM_H_ 18 #define ANDROID_DRM_PLATFORM_H_ 19 20 #include "drmdisplaycomposition.h" 21 #include "drmhwcomposer.h" 22 23 #include <hardware/hardware.h> 24 #include <hardware/hwcomposer.h> 25 26 #include <map> 27 #include <vector> 28 29 namespace android { 30 31 class DrmResources; 32 33 class Importer { 34 public: ~Importer()35 virtual ~Importer() { 36 } 37 38 // Creates a platform-specific importer instance 39 static Importer *CreateInstance(DrmResources *drm); 40 41 // Imports the buffer referred to by handle into bo. 42 // 43 // Note: This can be called from a different thread than ReleaseBuffer. The 44 // implementation is responsible for ensuring thread safety. 45 virtual int ImportBuffer(buffer_handle_t handle, hwc_drm_bo_t *bo) = 0; 46 47 // Releases the buffer object (ie: does the inverse of ImportBuffer) 48 // 49 // Note: This can be called from a different thread than ImportBuffer. The 50 // implementation is responsible for ensuring thread safety. 51 virtual int ReleaseBuffer(hwc_drm_bo_t *bo) = 0; 52 }; 53 54 class Planner { 55 public: 56 class PlanStage { 57 public: ~PlanStage()58 virtual ~PlanStage() { 59 } 60 61 virtual int ProvisionPlanes(std::vector<DrmCompositionPlane> *composition, 62 std::map<size_t, DrmHwcLayer *> &layers, 63 DrmCrtc *crtc, 64 std::vector<DrmPlane *> *planes) = 0; 65 66 protected: 67 // Removes and returns the next available plane from planes PopPlane(std::vector<DrmPlane * > * planes)68 static DrmPlane *PopPlane(std::vector<DrmPlane *> *planes) { 69 if (planes->empty()) 70 return NULL; 71 DrmPlane *plane = planes->front(); 72 planes->erase(planes->begin()); 73 return plane; 74 } 75 76 // Finds and returns the squash layer from the composition GetPrecomp(std::vector<DrmCompositionPlane> * composition)77 static DrmCompositionPlane *GetPrecomp( 78 std::vector<DrmCompositionPlane> *composition) { 79 auto l = GetPrecompIter(composition); 80 if (l == composition->end()) 81 return NULL; 82 return &(*l); 83 } 84 85 // Inserts the given layer:plane in the composition right before the precomp 86 // layer Emplace(std::vector<DrmCompositionPlane> * composition,std::vector<DrmPlane * > * planes,DrmCompositionPlane::Type type,DrmCrtc * crtc,size_t source_layer)87 static int Emplace(std::vector<DrmCompositionPlane> *composition, 88 std::vector<DrmPlane *> *planes, 89 DrmCompositionPlane::Type type, DrmCrtc *crtc, 90 size_t source_layer) { 91 DrmPlane *plane = PopPlane(planes); 92 if (!plane) 93 return -ENOENT; 94 95 auto precomp = GetPrecompIter(composition); 96 composition->emplace(precomp, type, plane, crtc, source_layer); 97 return 0; 98 } 99 100 private: GetPrecompIter(std::vector<DrmCompositionPlane> * composition)101 static std::vector<DrmCompositionPlane>::iterator GetPrecompIter( 102 std::vector<DrmCompositionPlane> *composition) { 103 return std::find_if(composition->begin(), composition->end(), 104 [](const DrmCompositionPlane &p) { 105 return p.type() == DrmCompositionPlane::Type::kPrecomp; 106 }); 107 } 108 }; 109 110 // Creates a planner instance with platform-specific planning stages 111 static std::unique_ptr<Planner> CreateInstance(DrmResources *drm); 112 113 // Takes a stack of layers and provisions hardware planes for them. If the 114 // entire stack can't fit in hardware, the Planner may place the remaining 115 // layers in a PRECOMP plane. Layers in the PRECOMP plane will be composited 116 // using GL. PRECOMP planes should be placed above any 1:1 layer:plane 117 // compositions. If use_squash_fb is true, the Planner should try to reserve a 118 // plane at the highest z-order with type SQUASH. 119 // 120 // @layers: a map of index:layer of layers to composite 121 // @use_squash_fb: reserve a squash framebuffer 122 // @primary_planes: a vector of primary planes available for this frame 123 // @overlay_planes: a vector of overlay planes available for this frame 124 // 125 // Returns: A tuple with the status of the operation (0 for success) and 126 // a vector of the resulting plan (ie: layer->plane mapping). 127 std::tuple<int, std::vector<DrmCompositionPlane>> ProvisionPlanes( 128 std::map<size_t, DrmHwcLayer *> &layers, bool use_squash_fb, 129 DrmCrtc *crtc, std::vector<DrmPlane *> *primary_planes, 130 std::vector<DrmPlane *> *overlay_planes); 131 132 template <typename T, typename... A> AddStage(A &&...args)133 void AddStage(A &&... args) { 134 stages_.emplace_back( 135 std::unique_ptr<PlanStage>(new T(std::forward(args)...))); 136 } 137 138 private: 139 std::vector<DrmPlane *> GetUsablePlanes( 140 DrmCrtc *crtc, std::vector<DrmPlane *> *primary_planes, 141 std::vector<DrmPlane *> *overlay_planes); 142 143 std::vector<std::unique_ptr<PlanStage>> stages_; 144 }; 145 146 // This plan stage extracts all protected layers and places them on dedicated 147 // planes. 148 class PlanStageProtected : public Planner::PlanStage { 149 public: 150 int ProvisionPlanes(std::vector<DrmCompositionPlane> *composition, 151 std::map<size_t, DrmHwcLayer *> &layers, DrmCrtc *crtc, 152 std::vector<DrmPlane *> *planes); 153 }; 154 155 // This plan stage provisions the precomp plane with any remaining layers that 156 // are on top of the current precomp layers. This stage should be included in 157 // all platforms before loosely allocating layers (i.e. PlanStageGreedy) if 158 // any previous plan could have modified the precomp plane layers 159 // (ex. PlanStageProtected). 160 class PlanStagePrecomp : public Planner::PlanStage { 161 public: 162 int ProvisionPlanes(std::vector<DrmCompositionPlane> *composition, 163 std::map<size_t, DrmHwcLayer *> &layers, DrmCrtc *crtc, 164 std::vector<DrmPlane *> *planes); 165 }; 166 167 // This plan stage places as many layers on dedicated planes as possible (first 168 // come first serve), and then sticks the rest in a precomposition plane (if 169 // needed). 170 class PlanStageGreedy : public Planner::PlanStage { 171 public: 172 int ProvisionPlanes(std::vector<DrmCompositionPlane> *composition, 173 std::map<size_t, DrmHwcLayer *> &layers, DrmCrtc *crtc, 174 std::vector<DrmPlane *> *planes); 175 }; 176 } 177 #endif 178