1 /*
2 * Copyright 2017 The Chromium OS Authors. All rights reserved.
3 * Use of this source code is governed by a BSD-style license that can be
4 * found in the LICENSE file.
5 */
6
7 #include "cros_gralloc_buffer.h"
8
9 #include <assert.h>
10 #include <sys/mman.h>
11
12 #include <cutils/native_handle.h>
13
14 /*static*/
15 std::unique_ptr<cros_gralloc_buffer>
create(struct bo * acquire_bo,const struct cros_gralloc_handle * borrowed_handle)16 cros_gralloc_buffer::create(struct bo *acquire_bo,
17 const struct cros_gralloc_handle *borrowed_handle)
18 {
19 auto acquire_hnd =
20 reinterpret_cast<struct cros_gralloc_handle *>(native_handle_clone(borrowed_handle));
21 if (!acquire_hnd) {
22 ALOGE("Failed to create cros_gralloc_buffer: failed to clone handle.");
23 return {};
24 }
25
26 std::unique_ptr<cros_gralloc_buffer> buffer(
27 new cros_gralloc_buffer(acquire_bo, acquire_hnd));
28 if (!buffer) {
29 ALOGE("Failed to create cros_gralloc_buffer: failed to allocate.");
30 native_handle_close(acquire_hnd);
31 native_handle_delete(acquire_hnd);
32 return {};
33 }
34
35 return buffer;
36 }
37
cros_gralloc_buffer(struct bo * acquire_bo,struct cros_gralloc_handle * acquire_handle)38 cros_gralloc_buffer::cros_gralloc_buffer(struct bo *acquire_bo,
39 struct cros_gralloc_handle *acquire_handle)
40 : bo_(acquire_bo), hnd_(acquire_handle)
41 {
42 assert(bo_);
43 assert(hnd_);
44 for (uint32_t plane = 0; plane < DRV_MAX_PLANES; plane++)
45 lock_data_[plane] = nullptr;
46 }
47
~cros_gralloc_buffer()48 cros_gralloc_buffer::~cros_gralloc_buffer()
49 {
50 drv_bo_destroy(bo_);
51 if (reserved_region_addr_) {
52 munmap(reserved_region_addr_, hnd_->reserved_region_size);
53 }
54 native_handle_close(hnd_);
55 native_handle_delete(hnd_);
56 }
57
get_id() const58 uint32_t cros_gralloc_buffer::get_id() const
59 {
60 return hnd_->id;
61 }
62
get_width() const63 uint32_t cros_gralloc_buffer::get_width() const
64 {
65 return hnd_->width;
66 }
67
get_pixel_stride() const68 uint32_t cros_gralloc_buffer::get_pixel_stride() const
69 {
70 return hnd_->pixel_stride;
71 }
72
get_height() const73 uint32_t cros_gralloc_buffer::get_height() const
74 {
75 return hnd_->height;
76 }
77
get_format() const78 uint32_t cros_gralloc_buffer::get_format() const
79 {
80 return hnd_->format;
81 }
82
get_format_modifier() const83 uint64_t cros_gralloc_buffer::get_format_modifier() const
84 {
85 return hnd_->format_modifier;
86 }
87
get_total_size() const88 uint64_t cros_gralloc_buffer::get_total_size() const
89 {
90 return hnd_->total_size;
91 }
92
get_num_planes() const93 uint32_t cros_gralloc_buffer::get_num_planes() const
94 {
95 return hnd_->num_planes;
96 }
97
get_plane_offset(uint32_t plane) const98 uint32_t cros_gralloc_buffer::get_plane_offset(uint32_t plane) const
99 {
100 return hnd_->offsets[plane];
101 }
102
get_plane_stride(uint32_t plane) const103 uint32_t cros_gralloc_buffer::get_plane_stride(uint32_t plane) const
104 {
105 return hnd_->strides[plane];
106 }
107
get_plane_size(uint32_t plane) const108 uint32_t cros_gralloc_buffer::get_plane_size(uint32_t plane) const
109 {
110 return hnd_->sizes[plane];
111 }
112
get_android_format() const113 int32_t cros_gralloc_buffer::get_android_format() const
114 {
115 return hnd_->droid_format;
116 }
117
get_android_usage() const118 uint64_t cros_gralloc_buffer::get_android_usage() const
119 {
120 return static_cast<uint64_t>(hnd_->usage);
121 }
122
increase_refcount()123 int32_t cros_gralloc_buffer::increase_refcount()
124 {
125 return ++refcount_;
126 }
127
decrease_refcount()128 int32_t cros_gralloc_buffer::decrease_refcount()
129 {
130 assert(refcount_ > 0);
131 return --refcount_;
132 }
133
lock(const struct rectangle * rect,uint32_t map_flags,uint8_t * addr[DRV_MAX_PLANES])134 int32_t cros_gralloc_buffer::lock(const struct rectangle *rect, uint32_t map_flags,
135 uint8_t *addr[DRV_MAX_PLANES])
136 {
137 void *vaddr = nullptr;
138
139 memset(addr, 0, DRV_MAX_PLANES * sizeof(*addr));
140
141 /*
142 * Gralloc consumers don't support more than one kernel buffer per buffer object yet, so
143 * just use the first kernel buffer.
144 */
145 if (drv_num_buffers_per_bo(bo_) != 1) {
146 ALOGE("Can only support one buffer per bo.");
147 return -EINVAL;
148 }
149
150 if (map_flags) {
151 if (lock_data_[0]) {
152 drv_bo_invalidate(bo_, lock_data_[0]);
153 vaddr = lock_data_[0]->vma->addr;
154 } else {
155 struct rectangle r = *rect;
156
157 if (!r.width && !r.height && !r.x && !r.y) {
158 /*
159 * Android IMapper.hal: An accessRegion of all-zeros means the
160 * entire buffer.
161 */
162 r.width = drv_bo_get_width(bo_);
163 r.height = drv_bo_get_height(bo_);
164 }
165
166 vaddr = drv_bo_map(bo_, &r, map_flags, &lock_data_[0], 0);
167 }
168
169 if (vaddr == MAP_FAILED) {
170 ALOGE("Mapping failed.");
171 return -EFAULT;
172 }
173 }
174
175 for (uint32_t plane = 0; plane < hnd_->num_planes; plane++)
176 addr[plane] = static_cast<uint8_t *>(vaddr) + drv_bo_get_plane_offset(bo_, plane);
177
178 lockcount_++;
179 return 0;
180 }
181
unlock()182 int32_t cros_gralloc_buffer::unlock()
183 {
184 if (lockcount_ <= 0) {
185 ALOGE("Buffer was not locked.");
186 return -EINVAL;
187 }
188
189 if (!--lockcount_) {
190 if (lock_data_[0]) {
191 drv_bo_flush_or_unmap(bo_, lock_data_[0]);
192 lock_data_[0] = nullptr;
193 }
194 }
195
196 return 0;
197 }
198
resource_info(uint32_t strides[DRV_MAX_PLANES],uint32_t offsets[DRV_MAX_PLANES],uint64_t * format_modifier)199 int32_t cros_gralloc_buffer::resource_info(uint32_t strides[DRV_MAX_PLANES],
200 uint32_t offsets[DRV_MAX_PLANES],
201 uint64_t *format_modifier)
202 {
203 return drv_resource_info(bo_, strides, offsets, format_modifier);
204 }
205
invalidate()206 int32_t cros_gralloc_buffer::invalidate()
207 {
208 if (lockcount_ <= 0) {
209 ALOGE("Buffer was not locked.");
210 return -EINVAL;
211 }
212
213 if (lock_data_[0])
214 return drv_bo_invalidate(bo_, lock_data_[0]);
215
216 return 0;
217 }
218
flush()219 int32_t cros_gralloc_buffer::flush()
220 {
221 if (lockcount_ <= 0) {
222 ALOGE("Buffer was not locked.");
223 return -EINVAL;
224 }
225
226 if (lock_data_[0])
227 return drv_bo_flush(bo_, lock_data_[0]);
228
229 return 0;
230 }
231
get_reserved_region(void ** addr,uint64_t * size) const232 int32_t cros_gralloc_buffer::get_reserved_region(void **addr, uint64_t *size) const
233 {
234 int32_t reserved_region_fd = hnd_->fds[hnd_->num_planes];
235 if (reserved_region_fd < 0) {
236 ALOGE("Buffer does not have reserved region.");
237 return -EINVAL;
238 }
239
240 if (!reserved_region_addr_) {
241 reserved_region_addr_ =
242 mmap(nullptr, hnd_->reserved_region_size, PROT_WRITE | PROT_READ, MAP_SHARED,
243 reserved_region_fd, 0);
244 if (reserved_region_addr_ == MAP_FAILED) {
245 ALOGE("Failed to mmap reserved region: %s.", strerror(errno));
246 return -errno;
247 }
248 }
249
250 *addr = reserved_region_addr_;
251 *size = hnd_->reserved_region_size;
252 return 0;
253 }
254