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 #define LOG_TAG "hwc-drm-composition"
     18 
     19 #include "drmcomposition.h"
     20 #include "drmcrtc.h"
     21 #include "drmplane.h"
     22 #include "drmresources.h"
     23 #include "platform.h"
     24 
     25 #include <stdlib.h>
     26 
     27 #include <cutils/log.h>
     28 #include <cutils/properties.h>
     29 #include <sw_sync.h>
     30 #include <sync/sync.h>
     31 
     32 namespace android {
     33 
     34 DrmComposition::DrmComposition(DrmResources *drm, Importer *importer,
     35                                Planner *planner)
     36     : drm_(drm), importer_(importer), planner_(planner) {
     37   char use_overlay_planes_prop[PROPERTY_VALUE_MAX];
     38   property_get("hwc.drm.use_overlay_planes", use_overlay_planes_prop, "1");
     39   bool use_overlay_planes = atoi(use_overlay_planes_prop);
     40 
     41   for (auto &plane : drm->planes()) {
     42     if (plane->type() == DRM_PLANE_TYPE_PRIMARY)
     43       primary_planes_.push_back(plane.get());
     44     else if (use_overlay_planes && plane->type() == DRM_PLANE_TYPE_OVERLAY)
     45       overlay_planes_.push_back(plane.get());
     46   }
     47 }
     48 
     49 int DrmComposition::Init(uint64_t frame_no) {
     50   for (auto &conn : drm_->connectors()) {
     51     int display = conn->display();
     52     composition_map_[display].reset(new DrmDisplayComposition());
     53     if (!composition_map_[display]) {
     54       ALOGE("Failed to allocate new display composition\n");
     55       return -ENOMEM;
     56     }
     57 
     58     // If the display hasn't been modeset yet, this will be NULL
     59     DrmCrtc *crtc = drm_->GetCrtcForDisplay(display);
     60 
     61     int ret = composition_map_[display]->Init(drm_, crtc, importer_, planner_,
     62                                               frame_no);
     63     if (ret) {
     64       ALOGE("Failed to init display composition for %d", display);
     65       return ret;
     66     }
     67   }
     68   return 0;
     69 }
     70 
     71 int DrmComposition::SetLayers(size_t num_displays,
     72                               DrmCompositionDisplayLayersMap *maps) {
     73   int ret = 0;
     74   for (size_t display_index = 0; display_index < num_displays;
     75        display_index++) {
     76     DrmCompositionDisplayLayersMap &map = maps[display_index];
     77     int display = map.display;
     78 
     79     if (!drm_->GetConnectorForDisplay(display)) {
     80       ALOGE("Invalid display given to SetLayers %d", display);
     81       continue;
     82     }
     83 
     84     ret = composition_map_[display]->SetLayers(
     85         map.layers.data(), map.layers.size(), map.geometry_changed);
     86     if (ret)
     87       return ret;
     88   }
     89 
     90   return 0;
     91 }
     92 
     93 int DrmComposition::SetDpmsMode(int display, uint32_t dpms_mode) {
     94   return composition_map_[display]->SetDpmsMode(dpms_mode);
     95 }
     96 
     97 int DrmComposition::SetDisplayMode(int display, const DrmMode &display_mode) {
     98   return composition_map_[display]->SetDisplayMode(display_mode);
     99 }
    100 
    101 std::unique_ptr<DrmDisplayComposition> DrmComposition::TakeDisplayComposition(
    102     int display) {
    103   return std::move(composition_map_[display]);
    104 }
    105 
    106 int DrmComposition::Plan(std::map<int, DrmDisplayCompositor> &compositor_map) {
    107   int ret = 0;
    108   for (auto &conn : drm_->connectors()) {
    109     int display = conn->display();
    110     DrmDisplayComposition *comp = GetDisplayComposition(display);
    111     ret = comp->Plan(compositor_map[display].squash_state(), &primary_planes_,
    112                      &overlay_planes_);
    113     if (ret) {
    114       ALOGE("Failed to plan composition for dislay %d", display);
    115       return ret;
    116     }
    117   }
    118 
    119   return 0;
    120 }
    121 
    122 int DrmComposition::DisableUnusedPlanes() {
    123   for (auto &conn : drm_->connectors()) {
    124     int display = conn->display();
    125     DrmDisplayComposition *comp = GetDisplayComposition(display);
    126 
    127     /*
    128      * Leave empty compositions alone
    129      * TODO: re-visit this and potentially disable leftover planes after the
    130      *       active compositions have gobbled up all they can
    131      */
    132     if (comp->type() == DRM_COMPOSITION_TYPE_EMPTY ||
    133         comp->type() == DRM_COMPOSITION_TYPE_MODESET)
    134       continue;
    135 
    136     DrmCrtc *crtc = drm_->GetCrtcForDisplay(display);
    137     if (!crtc) {
    138       ALOGE("Failed to find crtc for display %d", display);
    139       continue;
    140     }
    141 
    142     for (std::vector<DrmPlane *>::iterator iter = primary_planes_.begin();
    143          iter != primary_planes_.end(); ++iter) {
    144       if ((*iter)->GetCrtcSupported(*crtc)) {
    145         comp->AddPlaneDisable(*iter);
    146         primary_planes_.erase(iter);
    147         break;
    148       }
    149     }
    150     for (std::vector<DrmPlane *>::iterator iter = overlay_planes_.begin();
    151          iter != overlay_planes_.end();) {
    152       if ((*iter)->GetCrtcSupported(*crtc)) {
    153         comp->AddPlaneDisable(*iter);
    154         iter = overlay_planes_.erase(iter);
    155       } else {
    156         iter++;
    157       }
    158     }
    159   }
    160   return 0;
    161 }
    162 
    163 DrmDisplayComposition *DrmComposition::GetDisplayComposition(int display) {
    164   return composition_map_[display].get();
    165 }
    166 }
    167