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 places as many layers on dedicated planes as possible (first
156 // come first serve), and then sticks the rest in a precomposition plane (if
157 // needed).
158 class PlanStageGreedy : public Planner::PlanStage {
159  public:
160   int ProvisionPlanes(std::vector<DrmCompositionPlane> *composition,
161                       std::map<size_t, DrmHwcLayer *> &layers, DrmCrtc *crtc,
162                       std::vector<DrmPlane *> *planes);
163 };
164 }
165 #endif
166