Home | History | Annotate | Download | only in drm_hwcomposer
      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:
     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:
     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
     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
     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
     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:
    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>
    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