OSDN Git Service

drm_hwcomposer: Add rotation support for hw planes
[android-x86/external-drm_hwcomposer.git] / drmcomposition.cpp
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
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
45 DrmComposition::~DrmComposition() {
46 }
47
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
66 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::vector<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
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::vector<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
121 int DrmComposition::AddDpmsMode(int display, uint32_t dpms_mode) {
122   return composition_map_[display]->AddDpmsMode(dpms_mode);
123 }
124
125 std::unique_ptr<DrmDisplayComposition> DrmComposition::TakeDisplayComposition(
126     int display) {
127   return std::move(composition_map_[display]);
128 }
129
130 int DrmComposition::DisableUnusedPlanes() {
131   for (DrmResources::ConnectorIter iter = drm_->begin_connectors();
132        iter != drm_->end_connectors(); ++iter) {
133     int display = (*iter)->display();
134     DrmDisplayComposition *comp = GetDisplayComposition(display);
135
136     /*
137      * Leave empty compositions alone
138      * TODO: re-visit this and potentially disable leftover planes after the
139      *       active compositions have gobbled up all they can
140      */
141     if (comp->type() == DRM_COMPOSITION_TYPE_EMPTY)
142       continue;
143
144     DrmCrtc *crtc = drm_->GetCrtcForDisplay(display);
145     if (!crtc) {
146       ALOGE("Failed to find crtc for display %d", display);
147       continue;
148     }
149
150     for (std::vector<DrmPlane *>::iterator iter = primary_planes_.begin();
151          iter != primary_planes_.end(); ++iter) {
152       if ((*iter)->GetCrtcSupported(*crtc)) {
153         comp->AddPlaneDisable(*iter);
154         primary_planes_.erase(iter);
155         break;
156       }
157     }
158     for (std::vector<DrmPlane *>::iterator iter = overlay_planes_.begin();
159          iter != overlay_planes_.end();) {
160       if ((*iter)->GetCrtcSupported(*crtc)) {
161         comp->AddPlaneDisable(*iter);
162         iter = overlay_planes_.erase(iter);
163       } else {
164         iter++;
165       }
166     }
167   }
168   return 0;
169 }
170
171 DrmDisplayComposition *DrmComposition::GetDisplayComposition(int display) {
172   return composition_map_[display].get();
173 }
174 }