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 29namespace android { 30 31class DrmResources; 32 33class Importer { 34 public: 35 virtual ~Importer() { 36 } 37 38 // Creates a platform-specific importer instance 39 static Importer *CreateInstance(DrmResources *drm); 40 41 // Imports EGLImage for glcompositor, since NV handles this in non-standard 42 // way, and fishing out the details is specific to the gralloc used. 43 virtual EGLImageKHR ImportImage(EGLDisplay egl_display, buffer_handle_t handle) = 0; 44 45 // Imports the buffer referred to by handle into bo. 46 // 47 // Note: This can be called from a different thread than ReleaseBuffer. The 48 // implementation is responsible for ensuring thread safety. 49 virtual int ImportBuffer(buffer_handle_t handle, hwc_drm_bo_t *bo) = 0; 50 51 // Releases the buffer object (ie: does the inverse of ImportBuffer) 52 // 53 // Note: This can be called from a different thread than ImportBuffer. The 54 // implementation is responsible for ensuring thread safety. 55 virtual int ReleaseBuffer(hwc_drm_bo_t *bo) = 0; 56}; 57 58class Planner { 59 public: 60 class PlanStage { 61 public: 62 virtual ~PlanStage() { 63 } 64 65 virtual int ProvisionPlanes(std::vector<DrmCompositionPlane> *composition, 66 std::map<size_t, DrmHwcLayer *> &layers, 67 DrmCrtc *crtc, 68 std::vector<DrmPlane *> *planes) = 0; 69 70 protected: 71 // Removes and returns the next available plane from planes 72 static DrmPlane *PopPlane(std::vector<DrmPlane *> *planes) { 73 if (planes->empty()) 74 return NULL; 75 DrmPlane *plane = planes->front(); 76 planes->erase(planes->begin()); 77 return plane; 78 } 79 80 // Finds and returns the squash layer from the composition 81 static DrmCompositionPlane *GetPrecomp( 82 std::vector<DrmCompositionPlane> *composition) { 83 auto l = GetPrecompIter(composition); 84 if (l == composition->end()) 85 return NULL; 86 return &(*l); 87 } 88 89 // Inserts the given layer:plane in the composition right before the precomp 90 // layer 91 static int Emplace(std::vector<DrmCompositionPlane> *composition, 92 std::vector<DrmPlane *> *planes, 93 DrmCompositionPlane::Type type, DrmCrtc *crtc, 94 size_t source_layer) { 95 DrmPlane *plane = PopPlane(planes); 96 if (!plane) 97 return -ENOENT; 98 99 auto precomp = GetPrecompIter(composition); 100 composition->emplace(precomp, type, plane, crtc, source_layer); 101 return 0; 102 } 103 104 private: 105 static std::vector<DrmCompositionPlane>::iterator GetPrecompIter( 106 std::vector<DrmCompositionPlane> *composition) { 107 return std::find_if(composition->begin(), composition->end(), 108 [](const DrmCompositionPlane &p) { 109 return p.type() == DrmCompositionPlane::Type::kPrecomp; 110 }); 111 } 112 }; 113 114 // Creates a planner instance with platform-specific planning stages 115 static std::unique_ptr<Planner> CreateInstance(DrmResources *drm); 116 117 // Takes a stack of layers and provisions hardware planes for them. If the 118 // entire stack can't fit in hardware, the Planner may place the remaining 119 // layers in a PRECOMP plane. Layers in the PRECOMP plane will be composited 120 // using GL. PRECOMP planes should be placed above any 1:1 layer:plane 121 // compositions. If use_squash_fb is true, the Planner should try to reserve a 122 // plane at the highest z-order with type SQUASH. 123 // 124 // @layers: a map of index:layer of layers to composite 125 // @use_squash_fb: reserve a squash framebuffer 126 // @primary_planes: a vector of primary planes available for this frame 127 // @overlay_planes: a vector of overlay planes available for this frame 128 // 129 // Returns: A tuple with the status of the operation (0 for success) and 130 // a vector of the resulting plan (ie: layer->plane mapping). 131 std::tuple<int, std::vector<DrmCompositionPlane>> ProvisionPlanes( 132 std::map<size_t, DrmHwcLayer *> &layers, bool use_squash_fb, 133 DrmCrtc *crtc, std::vector<DrmPlane *> *primary_planes, 134 std::vector<DrmPlane *> *overlay_planes); 135 136 template <typename T, typename... A> 137 void AddStage(A &&... args) { 138 stages_.emplace_back( 139 std::unique_ptr<PlanStage>(new T(std::forward(args)...))); 140 } 141 142 private: 143 std::vector<DrmPlane *> GetUsablePlanes( 144 DrmCrtc *crtc, std::vector<DrmPlane *> *primary_planes, 145 std::vector<DrmPlane *> *overlay_planes); 146 147 std::vector<std::unique_ptr<PlanStage>> stages_; 148}; 149 150// This plan stage extracts all protected layers and places them on dedicated 151// planes. 152class PlanStageProtected : public Planner::PlanStage { 153 public: 154 int ProvisionPlanes(std::vector<DrmCompositionPlane> *composition, 155 std::map<size_t, DrmHwcLayer *> &layers, DrmCrtc *crtc, 156 std::vector<DrmPlane *> *planes); 157}; 158 159// This plan stage provisions the precomp plane with any remaining layers that 160// are on top of the current precomp layers. This stage should be included in 161// all platforms before loosely allocating layers (i.e. PlanStageGreedy) if 162// any previous plan could have modified the precomp plane layers 163// (ex. PlanStageProtected). 164class PlanStagePrecomp : public Planner::PlanStage { 165 public: 166 int ProvisionPlanes(std::vector<DrmCompositionPlane> *composition, 167 std::map<size_t, DrmHwcLayer *> &layers, DrmCrtc *crtc, 168 std::vector<DrmPlane *> *planes); 169}; 170 171// This plan stage places as many layers on dedicated planes as possible (first 172// come first serve), and then sticks the rest in a precomposition plane (if 173// needed). 174class PlanStageGreedy : public Planner::PlanStage { 175 public: 176 int ProvisionPlanes(std::vector<DrmCompositionPlane> *composition, 177 std::map<size_t, DrmHwcLayer *> &layers, DrmCrtc *crtc, 178 std::vector<DrmPlane *> *planes); 179}; 180} 181#endif 182