OSDN Git Service

drm_hwcomposer: duplicate buffer_handles before hwc_set returns
[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.acquireFenceFd = -1;
64   memset(&bo, 0, sizeof(bo));
65 }
66
67 DrmCompositionLayer::~DrmCompositionLayer() {
68 }
69
70 DrmDisplayComposition::DrmDisplayComposition()
71     : drm_(NULL),
72       importer_(NULL),
73       type_(DRM_COMPOSITION_TYPE_EMPTY),
74       timeline_fd_(-1),
75       timeline_(0),
76       timeline_current_(0),
77       dpms_mode_(DRM_MODE_DPMS_ON) {
78 }
79
80 DrmDisplayComposition::~DrmDisplayComposition() {
81   for (DrmCompositionLayerVector_t::iterator iter = layers_.begin();
82        iter != layers_.end(); ++iter) {
83     if (importer_ && iter->bo.fb_id)
84       importer_->ReleaseBuffer(&iter->bo);
85
86     if (iter->handle) {
87       gralloc_->unregisterBuffer(gralloc_, iter->handle);
88       free_buffer_handle(iter->handle);
89     }
90
91     if (iter->layer.acquireFenceFd >= 0)
92       close(iter->layer.acquireFenceFd);
93   }
94
95   if (timeline_fd_ >= 0) {
96     FinishComposition();
97     close(timeline_fd_);
98     timeline_fd_ = -1;
99   }
100 }
101
102 int DrmDisplayComposition::Init(DrmResources *drm, Importer *importer) {
103   drm_ = drm;
104   importer_ = importer;
105
106   int ret = hw_get_module(GRALLOC_HARDWARE_MODULE_ID,
107                           (const hw_module_t **)&gralloc_);
108   if (ret) {
109     ALOGE("Failed to open gralloc module %d", ret);
110     return ret;
111   }
112
113   ret = sw_sync_timeline_create();
114   if (ret < 0) {
115     ALOGE("Failed to create sw sync timeline %d", ret);
116     return ret;
117   }
118   timeline_fd_ = ret;
119   return 0;
120 }
121
122 DrmCompositionType DrmDisplayComposition::type() const {
123   return type_;
124 }
125
126 bool DrmDisplayComposition::validate_composition_type(DrmCompositionType des) {
127   return type_ == DRM_COMPOSITION_TYPE_EMPTY || type_ == des;
128 }
129
130 int DrmDisplayComposition::AddLayer(hwc_layer_1_t *layer, hwc_drm_bo_t *bo,
131                                     DrmCrtc *crtc, DrmPlane *plane) {
132   if (!validate_composition_type(DRM_COMPOSITION_TYPE_FRAME))
133     return -EINVAL;
134
135   native_handle_t *handle_copy = dup_buffer_handle(layer->handle);
136   if (handle_copy == NULL) {
137     ALOGE("Failed to duplicate handle");
138     return -ENOMEM;
139   }
140
141   int ret = gralloc_->registerBuffer(gralloc_, handle_copy);
142   if (ret) {
143     ALOGE("Failed to register buffer handle %d", ret);
144     free_buffer_handle(handle_copy);
145     return ret;
146   }
147
148   ++timeline_;
149   layer->releaseFenceFd =
150       sw_sync_fence_create(timeline_fd_, "drm_fence", timeline_);
151   if (layer->releaseFenceFd < 0) {
152     free_buffer_handle(handle_copy);
153     ALOGE("Could not create release fence %d", layer->releaseFenceFd);
154     return layer->releaseFenceFd;
155   }
156
157   DrmCompositionLayer_t c_layer;
158   c_layer.layer = *layer;
159   c_layer.bo = *bo;
160   c_layer.crtc = crtc;
161   c_layer.plane = plane;
162   c_layer.handle = handle_copy;
163
164   layer->acquireFenceFd = -1;  // We own this now
165   layers_.push_back(c_layer);
166   type_ = DRM_COMPOSITION_TYPE_FRAME;
167   return 0;
168 }
169
170 int DrmDisplayComposition::AddLayer(hwc_layer_1_t *layer, DrmCrtc *crtc,
171                                     DrmPlane *plane) {
172   if (layer->transform != 0)
173     return -EINVAL;
174
175   if (!validate_composition_type(DRM_COMPOSITION_TYPE_FRAME))
176     return -EINVAL;
177
178   hwc_drm_bo_t bo;
179   int ret = importer_->ImportBuffer(layer->handle, &bo);
180   if (ret) {
181     ALOGE("Failed to import handle of layer %d", ret);
182     return ret;
183   }
184
185   ret = AddLayer(layer, &bo, crtc, plane);
186   if (ret)
187     importer_->ReleaseBuffer(&bo);
188
189   return ret;
190 }
191
192 int DrmDisplayComposition::AddDpmsMode(uint32_t dpms_mode) {
193   if (!validate_composition_type(DRM_COMPOSITION_TYPE_DPMS))
194     return -EINVAL;
195   dpms_mode_ = dpms_mode;
196   type_ = DRM_COMPOSITION_TYPE_DPMS;
197   return 0;
198 }
199
200 int DrmDisplayComposition::AddPlaneDisable(DrmPlane *plane) {
201   DrmCompositionLayer_t c_layer;
202   c_layer.crtc = NULL;
203   c_layer.plane = plane;
204   layers_.push_back(c_layer);
205   return 0;
206 }
207
208 void DrmDisplayComposition::RemoveNoPlaneLayers() {
209   for (auto &comp_layer : layers_) {
210     if (comp_layer.plane != NULL)
211       continue;
212
213     if (importer_ && comp_layer.bo.fb_id) {
214       importer_->ReleaseBuffer(&comp_layer.bo);
215     }
216
217     if (comp_layer.handle) {
218       gralloc_->unregisterBuffer(gralloc_, comp_layer.handle);
219       free_buffer_handle(comp_layer.handle);
220     }
221
222     if (comp_layer.layer.acquireFenceFd >= 0) {
223       close(comp_layer.layer.acquireFenceFd);
224       comp_layer.layer.acquireFenceFd = -1;
225     }
226   }
227
228   layers_.erase(
229       std::remove_if(layers_.begin(), layers_.end(),
230                      [](DrmCompositionLayer_t &l) { return l.plane == NULL; }),
231       layers_.end());
232 }
233
234 int DrmDisplayComposition::FinishComposition() {
235   int timeline_increase = timeline_ - timeline_current_;
236   if (timeline_increase <= 0)
237     return 0;
238
239   int ret = sw_sync_timeline_inc(timeline_fd_, timeline_increase);
240   if (ret)
241     ALOGE("Failed to increment sync timeline %d", ret);
242   else
243     timeline_current_ = timeline_;
244
245   return ret;
246 }
247
248 DrmCompositionLayerVector_t *DrmDisplayComposition::GetCompositionLayers() {
249   return &layers_;
250 }
251
252 uint32_t DrmDisplayComposition::dpms_mode() const {
253   return dpms_mode_;
254 }
255
256 Importer *DrmDisplayComposition::importer() const {
257   return importer_;
258 }
259 }