OSDN Git Service

drm_hwcomposer: Do not close duplicate gem handles in nvimporter
[android-x86/external-drm_hwcomposer.git] / drmdisplaycomposition.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-display-composition"
18
19 #include "drmdisplaycomposition.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 #include <xf86drmMode.h>
30
31 namespace android {
32
33 DrmCompositionLayer::DrmCompositionLayer(DrmCrtc *crtc, DrmHwcLayer &&l)
34     : crtc(crtc),
35       sf_handle(l.sf_handle),
36       buffer(std::move(l.buffer)),
37       handle(std::move(l.handle)),
38       transform(l.transform),
39       blending(l.blending),
40       alpha(l.alpha),
41       source_crop(l.source_crop),
42       display_frame(l.display_frame),
43       source_damage(l.source_damage),
44       acquire_fence(std::move(l.acquire_fence)) {
45 }
46
47 DrmDisplayComposition::DrmDisplayComposition()
48     : drm_(NULL),
49       importer_(NULL),
50       type_(DRM_COMPOSITION_TYPE_EMPTY),
51       timeline_fd_(-1),
52       timeline_(0),
53       timeline_current_(0),
54       timeline_pre_comp_done_(0),
55       pre_composition_layer_index_(-1),
56       dpms_mode_(DRM_MODE_DPMS_ON),
57       frame_no_(0) {
58 }
59
60 DrmDisplayComposition::~DrmDisplayComposition() {
61   if (timeline_fd_ >= 0) {
62     FinishComposition();
63     close(timeline_fd_);
64     timeline_fd_ = -1;
65   }
66 }
67
68 int DrmDisplayComposition::Init(DrmResources *drm, DrmCrtc *crtc,
69                                 Importer *importer, uint64_t frame_no) {
70   drm_ = drm;
71   crtc_ = crtc;  // Can be NULL if we haven't modeset yet
72   importer_ = importer;
73   frame_no_ = frame_no;
74
75   int ret = sw_sync_timeline_create();
76   if (ret < 0) {
77     ALOGE("Failed to create sw sync timeline %d", ret);
78     return ret;
79   }
80   timeline_fd_ = ret;
81   return 0;
82 }
83
84 DrmCompositionType DrmDisplayComposition::type() const {
85   return type_;
86 }
87
88 bool DrmDisplayComposition::validate_composition_type(DrmCompositionType des) {
89   return type_ == DRM_COMPOSITION_TYPE_EMPTY || type_ == des;
90 }
91
92 static DrmPlane *TakePlane(DrmCrtc *crtc, std::vector<DrmPlane *> *planes) {
93   for (auto iter = planes->begin(); iter != planes->end(); ++iter) {
94     if ((*iter)->GetCrtcSupported(*crtc)) {
95       DrmPlane *plane = *iter;
96       planes->erase(iter);
97       return plane;
98     }
99   }
100   return NULL;
101 }
102
103 static DrmPlane *TakePlane(DrmCrtc *crtc,
104                            std::vector<DrmPlane *> *primary_planes,
105                            std::vector<DrmPlane *> *overlay_planes) {
106   DrmPlane *plane = TakePlane(crtc, primary_planes);
107   if (plane)
108     return plane;
109   return TakePlane(crtc, overlay_planes);
110 }
111
112 int DrmDisplayComposition::CreateNextTimelineFence() {
113   ++timeline_;
114   return sw_sync_fence_create(timeline_fd_, "drm_fence", timeline_);
115 }
116
117 int DrmDisplayComposition::IncreaseTimelineToPoint(int point) {
118   int timeline_increase = point - timeline_current_;
119   if (timeline_increase <= 0)
120     return 0;
121
122   int ret = sw_sync_timeline_inc(timeline_fd_, timeline_increase);
123   if (ret)
124     ALOGE("Failed to increment sync timeline %d", ret);
125   else
126     timeline_current_ = point;
127
128   return ret;
129 }
130
131 int DrmDisplayComposition::SetLayers(DrmHwcLayer *layers, size_t num_layers,
132                                      std::vector<DrmPlane *> *primary_planes,
133                                      std::vector<DrmPlane *> *overlay_planes) {
134   int ret = 0;
135   if (!validate_composition_type(DRM_COMPOSITION_TYPE_FRAME))
136     return -EINVAL;
137
138   for (size_t layer_index = 0; layer_index < num_layers; layer_index++) {
139     DrmHwcLayer *layer = &layers[layer_index];
140
141     layers_.emplace_back(crtc_, std::move(*layer));
142     DrmCompositionLayer *c_layer = &layers_.back();
143
144     if (pre_composition_layer_index_ == -1) {
145       c_layer->plane = TakePlane(crtc_, primary_planes, overlay_planes);
146       if (c_layer->plane == NULL) {
147         if (layers_.size() <= 1) {
148           ALOGE("Failed to match any planes to the crtc of this display");
149           ret = -ENODEV;
150           goto fail;
151         }
152
153         layers_.emplace_back();
154         // c_layer's address might have changed when we resized the vector
155         c_layer = &layers_[layers_.size() - 2];
156         DrmCompositionLayer &pre_comp_layer = layers_.back();
157         pre_comp_layer.crtc = crtc_;
158
159         pre_composition_layer_index_ = layers_.size() - 1;
160
161         // This is all to fix up the previous layer, which has now become part
162         // of the set of pre-composition layers because we are stealing its
163         // plane.
164         DrmCompositionLayer &last_c_layer = layers_[layers_.size() - 3];
165         std::swap(pre_comp_layer.plane, last_c_layer.plane);
166         OutputFd &last_release_fence = layers[layer_index - 1].release_fence;
167         last_release_fence.Set(CreateNextTimelineFence());
168         ret = last_release_fence.get();
169         if (ret < 0) {
170           ALOGE("Could not create release fence %d", ret);
171           goto fail;
172         }
173       }
174     }
175
176     if (c_layer->plane == NULL) {
177       // Layers to be pre composited all get the earliest release fences as they
178       // will get released soonest.
179       layer->release_fence.Set(CreateNextTimelineFence());
180       ret = layer->release_fence.get();
181       if (ret < 0) {
182         ALOGE("Could not create release fence %d", ret);
183         goto fail;
184       }
185     }
186   }
187
188   timeline_pre_comp_done_ = timeline_;
189
190   for (size_t layer_index = 0; layer_index < num_layers; layer_index++) {
191     DrmHwcLayer *layer = &layers[layer_index];
192     if (layer->release_fence.get() >= 0)
193       continue;
194
195     ret = layer->release_fence.Set(CreateNextTimelineFence());
196     if (ret < 0) {
197       ALOGE("Could not create release fence %d", ret);
198       goto fail;
199     }
200   }
201
202   type_ = DRM_COMPOSITION_TYPE_FRAME;
203   return 0;
204
205 fail:
206
207   for (size_t c_layer_index = 0; c_layer_index < layers_.size();
208        c_layer_index++) {
209     DrmCompositionLayer &c_layer = layers_[c_layer_index];
210     if (c_layer.plane != NULL) {
211       std::vector<DrmPlane *> *return_to =
212           (c_layer.plane->type() == DRM_PLANE_TYPE_PRIMARY) ? primary_planes
213                                                             : overlay_planes;
214       return_to->insert(return_to->begin() + c_layer_index, c_layer.plane);
215     }
216   }
217
218   layers_.clear();
219
220   sw_sync_timeline_inc(timeline_fd_, timeline_ - timeline_current_);
221
222   timeline_ = timeline_current_;
223   return ret;
224 }
225
226 int DrmDisplayComposition::SetDpmsMode(uint32_t dpms_mode) {
227   if (!validate_composition_type(DRM_COMPOSITION_TYPE_DPMS))
228     return -EINVAL;
229   dpms_mode_ = dpms_mode;
230   type_ = DRM_COMPOSITION_TYPE_DPMS;
231   return 0;
232 }
233
234 int DrmDisplayComposition::SetDisplayMode(const DrmMode &display_mode) {
235   if (!validate_composition_type(DRM_COMPOSITION_TYPE_MODESET))
236     return -EINVAL;
237   display_mode_ = display_mode;
238   dpms_mode_ = DRM_MODE_DPMS_ON;
239   type_ = DRM_COMPOSITION_TYPE_MODESET;
240   return 0;
241 }
242
243 int DrmDisplayComposition::AddPlaneDisable(DrmPlane *plane) {
244   layers_.emplace_back();
245   DrmCompositionLayer &c_layer = layers_.back();
246   c_layer.crtc = NULL;
247   c_layer.plane = plane;
248   return 0;
249 }
250
251 void DrmDisplayComposition::RemoveNoPlaneLayers() {
252   layers_.erase(
253       std::remove_if(layers_.begin(), layers_.end(),
254                      [](DrmCompositionLayer &l) { return l.plane == NULL; }),
255       layers_.end());
256 }
257
258 int DrmDisplayComposition::SignalPreCompositionDone() {
259   return IncreaseTimelineToPoint(timeline_pre_comp_done_);
260 }
261
262 int DrmDisplayComposition::FinishComposition() {
263   return IncreaseTimelineToPoint(timeline_);
264 }
265
266 std::vector<DrmCompositionLayer>
267     *DrmDisplayComposition::GetCompositionLayers() {
268   return &layers_;
269 }
270
271 int DrmDisplayComposition::pre_composition_layer_index() const {
272   return pre_composition_layer_index_;
273 }
274
275 uint32_t DrmDisplayComposition::dpms_mode() const {
276   return dpms_mode_;
277 }
278
279 uint64_t DrmDisplayComposition::frame_no() const {
280   return frame_no_;
281 }
282
283 const DrmMode &DrmDisplayComposition::display_mode() const {
284   return display_mode_;
285 }
286
287 Importer *DrmDisplayComposition::importer() const {
288   return importer_;
289 }
290 }