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 24#include <stdlib.h> 25 26#include <cutils/log.h> 27#include <cutils/properties.h> 28#include <sw_sync.h> 29#include <sync/sync.h> 30 31namespace android { 32 33DrmComposition::DrmComposition(DrmResources *drm, Importer *importer) 34 : drm_(drm), importer_(importer) { 35 char use_overlay_planes_prop[PROPERTY_VALUE_MAX]; 36 property_get("hwc.drm.use_overlay_planes", use_overlay_planes_prop, "1"); 37 bool use_overlay_planes = atoi(use_overlay_planes_prop); 38 39 for (DrmResources::PlaneIter iter = drm_->begin_planes(); 40 iter != drm_->end_planes(); ++iter) { 41 if ((*iter)->type() == DRM_PLANE_TYPE_PRIMARY) 42 primary_planes_.push_back(*iter); 43 else if (use_overlay_planes && (*iter)->type() == DRM_PLANE_TYPE_OVERLAY) 44 overlay_planes_.push_back(*iter); 45 } 46} 47 48int DrmComposition::Init(uint64_t frame_no) { 49 for (DrmResources::ConnectorIter iter = drm_->begin_connectors(); 50 iter != drm_->end_connectors(); ++iter) { 51 int display = (*iter)->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_, frame_no); 62 if (ret) { 63 ALOGE("Failed to init display composition for %d", display); 64 return ret; 65 } 66 } 67 return 0; 68} 69 70int DrmComposition::SetLayers(size_t num_displays, 71 DrmCompositionDisplayLayersMap *maps) { 72 int ret = 0; 73 for (size_t display_index = 0; display_index < num_displays; 74 display_index++) { 75 DrmCompositionDisplayLayersMap &map = maps[display_index]; 76 int display = map.display; 77 78 if (!drm_->GetConnectorForDisplay(display)) { 79 ALOGE("Invalid display given to SetLayers %d", display); 80 continue; 81 } 82 83 ret = composition_map_[display]->SetLayers( 84 map.layers.data(), map.layers.size(), map.geometry_changed); 85 if (ret) 86 return ret; 87 } 88 89 return 0; 90} 91 92int DrmComposition::SetDpmsMode(int display, uint32_t dpms_mode) { 93 return composition_map_[display]->SetDpmsMode(dpms_mode); 94} 95 96int DrmComposition::SetDisplayMode(int display, const DrmMode &display_mode) { 97 return composition_map_[display]->SetDisplayMode(display_mode); 98} 99 100std::unique_ptr<DrmDisplayComposition> DrmComposition::TakeDisplayComposition( 101 int display) { 102 return std::move(composition_map_[display]); 103} 104 105int DrmComposition::Plan(std::map<int, DrmDisplayCompositor> &compositor_map) { 106 int ret = 0; 107 for (DrmResources::ConnectorIter iter = drm_->begin_connectors(); 108 iter != drm_->end_connectors(); ++iter) { 109 int display = (*iter)->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 122int DrmComposition::DisableUnusedPlanes() { 123 for (DrmResources::ConnectorIter iter = drm_->begin_connectors(); 124 iter != drm_->end_connectors(); ++iter) { 125 int display = (*iter)->display(); 126 DrmDisplayComposition *comp = GetDisplayComposition(display); 127 128 /* 129 * Leave empty compositions alone 130 * TODO: re-visit this and potentially disable leftover planes after the 131 * active compositions have gobbled up all they can 132 */ 133 if (comp->type() == DRM_COMPOSITION_TYPE_EMPTY || 134 comp->type() == DRM_COMPOSITION_TYPE_MODESET) 135 continue; 136 137 DrmCrtc *crtc = drm_->GetCrtcForDisplay(display); 138 if (!crtc) { 139 ALOGE("Failed to find crtc for display %d", display); 140 continue; 141 } 142 143 for (std::vector<DrmPlane *>::iterator iter = primary_planes_.begin(); 144 iter != primary_planes_.end(); ++iter) { 145 if ((*iter)->GetCrtcSupported(*crtc)) { 146 comp->AddPlaneDisable(*iter); 147 primary_planes_.erase(iter); 148 break; 149 } 150 } 151 for (std::vector<DrmPlane *>::iterator iter = overlay_planes_.begin(); 152 iter != overlay_planes_.end();) { 153 if ((*iter)->GetCrtcSupported(*crtc)) { 154 comp->AddPlaneDisable(*iter); 155 iter = overlay_planes_.erase(iter); 156 } else { 157 iter++; 158 } 159 } 160 } 161 return 0; 162} 163 164DrmDisplayComposition *DrmComposition::GetDisplayComposition(int display) { 165 return composition_map_[display].get(); 166} 167} 168