OSDN Git Service

c1848e0e96e245a7b92e190bacbaed9710e8ab22
[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 static native_handle_t *dup_buffer_handle(buffer_handle_t handle) {
34   native_handle_t *new_handle =
35       native_handle_create(handle->numFds, handle->numInts);
36   if (new_handle == NULL)
37     return NULL;
38
39   const int *old_data = handle->data;
40   int *new_data = new_handle->data;
41   for (int i = 0; i < handle->numFds; i++) {
42     *new_data = dup(*old_data);
43     old_data++;
44     new_data++;
45   }
46   memcpy(new_data, old_data, sizeof(int) * handle->numInts);
47
48   return new_handle;
49 }
50
51 static void free_buffer_handle(native_handle_t *handle) {
52   int ret = native_handle_close(handle);
53   if (ret)
54     ALOGE("Failed to close native handle %d", ret);
55   ret = native_handle_delete(handle);
56   if (ret)
57     ALOGE("Failed to delete native handle %d", ret);
58 }
59
60 DrmCompositionLayer::DrmCompositionLayer()
61     : crtc(NULL), plane(NULL), handle(NULL) {
62   memset(&layer, 0, sizeof(layer));
63   layer.releaseFenceFd = -1;
64   layer.acquireFenceFd = -1;
65   memset(&bo, 0, sizeof(bo));
66 }
67
68 DrmDisplayComposition::DrmDisplayComposition()
69     : drm_(NULL),
70       importer_(NULL),
71       type_(DRM_COMPOSITION_TYPE_EMPTY),
72       timeline_fd_(-1),
73       timeline_(0),
74       timeline_current_(0),
75       timeline_pre_comp_done_(0),
76       pre_composition_layer_index_(-1),
77       dpms_mode_(DRM_MODE_DPMS_ON),
78       frame_no_(0) {
79 }
80
81 DrmDisplayComposition::~DrmDisplayComposition() {
82   for (DrmCompositionLayerVector_t::iterator iter = layers_.begin();
83        iter != layers_.end(); ++iter) {
84     if (importer_ && iter->bo.fb_id)
85       importer_->ReleaseBuffer(&iter->bo);
86
87     if (iter->handle) {
88       gralloc_->unregisterBuffer(gralloc_, iter->handle);
89       free_buffer_handle(iter->handle);
90     }
91
92     if (iter->layer.acquireFenceFd >= 0)
93       close(iter->layer.acquireFenceFd);
94   }
95
96   if (timeline_fd_ >= 0) {
97     FinishComposition();
98     close(timeline_fd_);
99     timeline_fd_ = -1;
100   }
101 }
102
103 int DrmDisplayComposition::Init(DrmResources *drm, DrmCrtc *crtc,
104                                 Importer *importer, uint64_t frame_no) {
105   drm_ = drm;
106   crtc_ = crtc; // Can be NULL if we haven't modeset yet
107   importer_ = importer;
108   frame_no_ = frame_no;
109
110   int ret = hw_get_module(GRALLOC_HARDWARE_MODULE_ID,
111                           (const hw_module_t **)&gralloc_);
112   if (ret) {
113     ALOGE("Failed to open gralloc module %d", ret);
114     return ret;
115   }
116
117   ret = sw_sync_timeline_create();
118   if (ret < 0) {
119     ALOGE("Failed to create sw sync timeline %d", ret);
120     return ret;
121   }
122   timeline_fd_ = ret;
123   return 0;
124 }
125
126 DrmCompositionType DrmDisplayComposition::type() const {
127   return type_;
128 }
129
130 bool DrmDisplayComposition::validate_composition_type(DrmCompositionType des) {
131   return type_ == DRM_COMPOSITION_TYPE_EMPTY || type_ == des;
132 }
133
134 static DrmPlane *TakePlane(DrmCrtc *crtc, std::vector<DrmPlane *> *planes) {
135   for (auto iter = planes->begin(); iter != planes->end(); ++iter) {
136     if ((*iter)->GetCrtcSupported(*crtc)) {
137       DrmPlane *plane = *iter;
138       planes->erase(iter);
139       return plane;
140     }
141   }
142   return NULL;
143 }
144
145 static DrmPlane *TakePlane(DrmCrtc *crtc,
146                            std::vector<DrmPlane *> *primary_planes,
147                            std::vector<DrmPlane *> *overlay_planes) {
148   DrmPlane *plane = TakePlane(crtc, primary_planes);
149   if (plane)
150     return plane;
151   return TakePlane(crtc, overlay_planes);
152 }
153
154 int DrmDisplayComposition::CreateNextTimelineFence() {
155   ++timeline_;
156   return sw_sync_fence_create(timeline_fd_, "drm_fence", timeline_);
157 }
158
159 int DrmDisplayComposition::IncreaseTimelineToPoint(int point) {
160   int timeline_increase = point - timeline_current_;
161   if (timeline_increase <= 0)
162     return 0;
163
164   int ret = sw_sync_timeline_inc(timeline_fd_, timeline_increase);
165   if (ret)
166     ALOGE("Failed to increment sync timeline %d", ret);
167   else
168     timeline_current_ = point;
169
170   return ret;
171 }
172
173 int DrmDisplayComposition::SetLayers(hwc_layer_1_t *layers, size_t num_layers,
174                                      size_t *layer_indices,
175                                      std::vector<DrmPlane *> *primary_planes,
176                                      std::vector<DrmPlane *> *overlay_planes) {
177   int ret = 0;
178   if (!validate_composition_type(DRM_COMPOSITION_TYPE_FRAME))
179     return -EINVAL;
180
181   for (size_t layer_index = 0; layer_index < num_layers; layer_index++) {
182     hwc_layer_1_t *layer = &layers[layer_indices[layer_index]];
183
184     native_handle_t *handle_copy = dup_buffer_handle(layer->handle);
185     if (handle_copy == NULL) {
186       ALOGE("Failed to duplicate handle");
187       return -ENOMEM;
188     }
189
190     int ret = gralloc_->registerBuffer(gralloc_, handle_copy);
191     if (ret) {
192       ALOGE("Failed to register buffer handle %d", ret);
193       free_buffer_handle(handle_copy);
194       return ret;
195     }
196
197     layers_.emplace_back();
198     DrmCompositionLayer_t *c_layer = &layers_.back();
199     c_layer->layer = *layer;
200     c_layer->handle = handle_copy;
201     c_layer->crtc = crtc_;
202
203     ret = importer_->ImportBuffer(layer->handle, &c_layer->bo);
204     if (ret) {
205       ALOGE("Failed to import handle of layer %d", ret);
206       goto fail;
207     }
208
209     if (pre_composition_layer_index_ == -1) {
210       c_layer->plane = TakePlane(crtc_, primary_planes, overlay_planes);
211       if (c_layer->plane == NULL) {
212         if (layers_.size() <= 1) {
213           ALOGE("Failed to match any planes to the crtc of this display");
214           ret = -ENODEV;
215           goto fail;
216         }
217
218         layers_.emplace_back();
219         // c_layer's address might have changed when we resized the vector
220         c_layer = &layers_[layers_.size() - 2];
221         DrmCompositionLayer_t &pre_comp_layer = layers_.back();
222         pre_comp_layer.crtc = crtc_;
223         hwc_layer_1_t &pre_comp_output_layer = pre_comp_layer.layer;
224         memset(&pre_comp_output_layer, 0, sizeof(pre_comp_output_layer));
225         pre_comp_output_layer.compositionType = HWC_OVERLAY;
226         pre_comp_output_layer.acquireFenceFd = -1;
227         pre_comp_output_layer.releaseFenceFd = -1;
228         pre_comp_output_layer.planeAlpha = 0xff;
229         pre_comp_output_layer.visibleRegionScreen.numRects = 1;
230         pre_comp_output_layer.visibleRegionScreen.rects =
231             &pre_comp_output_layer.displayFrame;
232
233         pre_composition_layer_index_ = layers_.size() - 1;
234
235         // This is all to fix up the previous layer, which has now become part
236         // of the set of pre-composition layers because we are stealing its
237         // plane.
238         DrmCompositionLayer_t &last_c_layer = layers_[layers_.size() - 3];
239         std::swap(pre_comp_layer.plane, last_c_layer.plane);
240         hwc_layer_1_t *last_layer = &layers[layer_indices[layer_index - 1]];
241         ret = last_layer->releaseFenceFd = CreateNextTimelineFence();
242         if (ret < 0) {
243           ALOGE("Could not create release fence %d", ret);
244           goto fail;
245         }
246       }
247     }
248
249     if (c_layer->plane == NULL) {
250       // Layers to be pre composited all get the earliest release fences as they
251       // will get released soonest.
252       ret = layer->releaseFenceFd = CreateNextTimelineFence();
253       if (ret < 0) {
254         ALOGE("Could not create release fence %d", ret);
255         goto fail;
256       }
257     }
258   }
259
260   timeline_pre_comp_done_ = timeline_;
261
262   for (size_t layer_index = 0; layer_index < num_layers; layer_index++) {
263     hwc_layer_1_t *layer = &layers[layer_indices[layer_index]];
264     if (layer->releaseFenceFd >= 0)
265       continue;
266
267     ret = layer->releaseFenceFd = CreateNextTimelineFence();
268     if (ret < 0) {
269       ALOGE("Could not create release fence %d", ret);
270       goto fail;
271     }
272   }
273
274   for (size_t layer_index = 0; layer_index < num_layers; layer_index++) {
275     hwc_layer_1_t *layer = &layers[layer_indices[layer_index]];
276     layer->acquireFenceFd = -1;  // We own this now
277   }
278
279   type_ = DRM_COMPOSITION_TYPE_FRAME;
280   return 0;
281
282 fail:
283
284   for (size_t c_layer_index = 0; c_layer_index < layers_.size();
285        c_layer_index++) {
286     DrmCompositionLayer_t &c_layer = layers_[c_layer_index];
287     if (c_layer.handle) {
288       gralloc_->unregisterBuffer(gralloc_, c_layer.handle);
289       free_buffer_handle(c_layer.handle);
290     }
291     if (c_layer.bo.fb_id)
292       importer_->ReleaseBuffer(&c_layer.bo);
293     if (c_layer.plane != NULL) {
294       std::vector<DrmPlane *> *return_to =
295           (c_layer.plane->type() == DRM_PLANE_TYPE_PRIMARY) ? primary_planes
296                                                             : overlay_planes;
297       return_to->insert(return_to->begin() + c_layer_index, c_layer.plane);
298     }
299   }
300   layers_.clear();
301
302   for (size_t layer_index = 0; layer_index < num_layers; layer_index++) {
303     hwc_layer_1_t *layer = &layers[layer_indices[layer_index]];
304     if (layer->releaseFenceFd >= 0) {
305       close(layer->releaseFenceFd);
306       layer->releaseFenceFd = -1;
307     }
308   }
309   sw_sync_timeline_inc(timeline_fd_, timeline_ - timeline_current_);
310
311   timeline_ = timeline_current_;
312   return ret;
313 }
314
315 int DrmDisplayComposition::SetDpmsMode(uint32_t dpms_mode) {
316   if (!validate_composition_type(DRM_COMPOSITION_TYPE_DPMS))
317     return -EINVAL;
318   dpms_mode_ = dpms_mode;
319   type_ = DRM_COMPOSITION_TYPE_DPMS;
320   return 0;
321 }
322
323 int DrmDisplayComposition::AddPlaneDisable(DrmPlane *plane) {
324   layers_.emplace_back();
325   DrmCompositionLayer_t &c_layer = layers_.back();
326   c_layer.crtc = NULL;
327   c_layer.plane = plane;
328   return 0;
329 }
330
331 void DrmDisplayComposition::RemoveNoPlaneLayers() {
332   for (auto &comp_layer : layers_) {
333     if (comp_layer.plane != NULL)
334       continue;
335
336     if (importer_ && comp_layer.bo.fb_id) {
337       importer_->ReleaseBuffer(&comp_layer.bo);
338     }
339
340     if (comp_layer.handle) {
341       gralloc_->unregisterBuffer(gralloc_, comp_layer.handle);
342       free_buffer_handle(comp_layer.handle);
343     }
344
345     if (comp_layer.layer.acquireFenceFd >= 0) {
346       close(comp_layer.layer.acquireFenceFd);
347       comp_layer.layer.acquireFenceFd = -1;
348     }
349   }
350
351   layers_.erase(
352       std::remove_if(layers_.begin(), layers_.end(),
353                      [](DrmCompositionLayer_t &l) { return l.plane == NULL; }),
354       layers_.end());
355 }
356
357 int DrmDisplayComposition::SignalPreCompositionDone() {
358   return IncreaseTimelineToPoint(timeline_pre_comp_done_);
359 }
360
361 int DrmDisplayComposition::FinishComposition() {
362   return IncreaseTimelineToPoint(timeline_);
363 }
364
365 DrmCompositionLayerVector_t *DrmDisplayComposition::GetCompositionLayers() {
366   return &layers_;
367 }
368
369 int DrmDisplayComposition::pre_composition_layer_index() const {
370   return pre_composition_layer_index_;
371 }
372
373 uint32_t DrmDisplayComposition::dpms_mode() const {
374   return dpms_mode_;
375 }
376
377 uint64_t DrmDisplayComposition::frame_no() const {
378   return frame_no_;
379 }
380
381 Importer *DrmDisplayComposition::importer() const {
382   return importer_;
383 }
384 }