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 <sw_sync.h>
28 #include <sync/sync.h>
29 
30 namespace android {
31 
32 static const bool kUseOverlayPlanes = true;
33 
DrmComposition(DrmResources * drm,Importer * importer)34 DrmComposition::DrmComposition(DrmResources *drm, Importer *importer)
35     : drm_(drm), importer_(importer) {
36   for (DrmResources::PlaneIter iter = drm_->begin_planes();
37        iter != drm_->end_planes(); ++iter) {
38     if ((*iter)->type() == DRM_PLANE_TYPE_PRIMARY)
39       primary_planes_.push_back(*iter);
40     else if (kUseOverlayPlanes && (*iter)->type() == DRM_PLANE_TYPE_OVERLAY)
41       overlay_planes_.push_back(*iter);
42   }
43 }
44 
~DrmComposition()45 DrmComposition::~DrmComposition() {
46 }
47 
Init()48 int DrmComposition::Init() {
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     int ret = composition_map_[(*iter)->display()]->Init(drm_, importer_);
58     if (ret) {
59       ALOGE("Failed to init display composition for %d", (*iter)->display());
60       return ret;
61     }
62   }
63   return 0;
64 }
65 
GetRemainingLayers(int display,unsigned num_needed) const66 unsigned DrmComposition::GetRemainingLayers(int display,
67                                             unsigned num_needed) const {
68   DrmCrtc *crtc = drm_->GetCrtcForDisplay(display);
69   if (!crtc) {
70     ALOGE("Failed to find crtc for display %d", display);
71     return 0;
72   }
73 
74   unsigned num_planes = 0;
75   for (std::vector<DrmPlane *>::const_iterator iter = primary_planes_.begin();
76        iter != primary_planes_.end(); ++iter) {
77     if ((*iter)->GetCrtcSupported(*crtc))
78       ++num_planes;
79   }
80   for (std::deque<DrmPlane *>::const_iterator iter = overlay_planes_.begin();
81        iter != overlay_planes_.end(); ++iter) {
82     if ((*iter)->GetCrtcSupported(*crtc))
83       ++num_planes;
84   }
85   return std::min(num_planes, num_needed);
86 }
87 
AddLayer(int display,hwc_layer_1_t * layer,hwc_drm_bo * bo)88 int DrmComposition::AddLayer(int display, hwc_layer_1_t *layer,
89                              hwc_drm_bo *bo) {
90   DrmCrtc *crtc = drm_->GetCrtcForDisplay(display);
91   if (!crtc) {
92     ALOGE("Failed to find crtc for display %d", display);
93     return -ENODEV;
94   }
95 
96   // Find a plane for the layer
97   DrmPlane *plane = NULL;
98   for (std::vector<DrmPlane *>::iterator iter = primary_planes_.begin();
99        iter != primary_planes_.end(); ++iter) {
100     if ((*iter)->GetCrtcSupported(*crtc)) {
101       plane = *iter;
102       primary_planes_.erase(iter);
103       break;
104     }
105   }
106   for (std::deque<DrmPlane *>::iterator iter = overlay_planes_.begin();
107        !plane && iter != overlay_planes_.end(); ++iter) {
108     if ((*iter)->GetCrtcSupported(*crtc)) {
109       plane = *iter;
110       overlay_planes_.erase(iter);
111       break;
112     }
113   }
114   if (!plane) {
115     ALOGE("Failed to find plane for display %d", display);
116     return -ENOENT;
117   }
118   return composition_map_[display]->AddLayer(layer, bo, crtc, plane);
119 }
120 
AddDpmsMode(int display,uint32_t dpms_mode)121 int DrmComposition::AddDpmsMode(int display, uint32_t dpms_mode) {
122   return composition_map_[display]->AddDpmsMode(dpms_mode);
123 }
124 
TakeDisplayComposition(int display)125 std::unique_ptr<DrmDisplayComposition> DrmComposition::TakeDisplayComposition(
126     int display) {
127   return std::move(composition_map_[display]);
128 }
129 }
130