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 drv_log("Failed to create cros_gralloc_buffer: failed to clone handle.\n");
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 drv_log("Failed to create cros_gralloc_buffer: failed to allocate.\n");
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_height() const68 uint32_t cros_gralloc_buffer::get_height() const
69 {
70 return hnd_->height;
71 }
72
get_format() const73 uint32_t cros_gralloc_buffer::get_format() const
74 {
75 return hnd_->format;
76 }
77
get_format_modifier() const78 uint64_t cros_gralloc_buffer::get_format_modifier() const
79 {
80 return hnd_->format_modifier;
81 }
82
get_total_size() const83 uint64_t cros_gralloc_buffer::get_total_size() const
84 {
85 return hnd_->total_size;
86 }
87
get_num_planes() const88 uint32_t cros_gralloc_buffer::get_num_planes() const
89 {
90 return hnd_->num_planes;
91 }
92
get_plane_offset(uint32_t plane) const93 uint32_t cros_gralloc_buffer::get_plane_offset(uint32_t plane) const
94 {
95 return hnd_->offsets[plane];
96 }
97
get_plane_stride(uint32_t plane) const98 uint32_t cros_gralloc_buffer::get_plane_stride(uint32_t plane) const
99 {
100 return hnd_->strides[plane];
101 }
102
get_plane_size(uint32_t plane) const103 uint32_t cros_gralloc_buffer::get_plane_size(uint32_t plane) const
104 {
105 return hnd_->sizes[plane];
106 }
107
get_android_format() const108 int32_t cros_gralloc_buffer::get_android_format() const
109 {
110 return hnd_->droid_format;
111 }
112
get_android_usage() const113 uint64_t cros_gralloc_buffer::get_android_usage() const
114 {
115 return static_cast<uint64_t>(hnd_->usage);
116 }
117
increase_refcount()118 int32_t cros_gralloc_buffer::increase_refcount()
119 {
120 return ++refcount_;
121 }
122
decrease_refcount()123 int32_t cros_gralloc_buffer::decrease_refcount()
124 {
125 assert(refcount_ > 0);
126 return --refcount_;
127 }
128
lock(const struct rectangle * rect,uint32_t map_flags,uint8_t * addr[DRV_MAX_PLANES])129 int32_t cros_gralloc_buffer::lock(const struct rectangle *rect, uint32_t map_flags,
130 uint8_t *addr[DRV_MAX_PLANES])
131 {
132 void *vaddr = nullptr;
133
134 memset(addr, 0, DRV_MAX_PLANES * sizeof(*addr));
135
136 /*
137 * Gralloc consumers don't support more than one kernel buffer per buffer object yet, so
138 * just use the first kernel buffer.
139 */
140 if (drv_num_buffers_per_bo(bo_) != 1) {
141 drv_log("Can only support one buffer per bo.\n");
142 return -EINVAL;
143 }
144
145 if (map_flags) {
146 if (lock_data_[0]) {
147 drv_bo_invalidate(bo_, lock_data_[0]);
148 vaddr = lock_data_[0]->vma->addr;
149 } else {
150 struct rectangle r = *rect;
151
152 if (!r.width && !r.height && !r.x && !r.y) {
153 /*
154 * Android IMapper.hal: An accessRegion of all-zeros means the
155 * entire buffer.
156 */
157 r.width = drv_bo_get_width(bo_);
158 r.height = drv_bo_get_height(bo_);
159 }
160
161 vaddr = drv_bo_map(bo_, &r, map_flags, &lock_data_[0], 0);
162 }
163
164 if (vaddr == MAP_FAILED) {
165 drv_log("Mapping failed.\n");
166 return -EFAULT;
167 }
168 }
169
170 for (uint32_t plane = 0; plane < hnd_->num_planes; plane++)
171 addr[plane] = static_cast<uint8_t *>(vaddr) + drv_bo_get_plane_offset(bo_, plane);
172
173 lockcount_++;
174 return 0;
175 }
176
unlock()177 int32_t cros_gralloc_buffer::unlock()
178 {
179 if (lockcount_ <= 0) {
180 drv_log("Buffer was not locked.\n");
181 return -EINVAL;
182 }
183
184 if (!--lockcount_) {
185 if (lock_data_[0]) {
186 drv_bo_flush_or_unmap(bo_, lock_data_[0]);
187 lock_data_[0] = nullptr;
188 }
189 }
190
191 return 0;
192 }
193
resource_info(uint32_t strides[DRV_MAX_PLANES],uint32_t offsets[DRV_MAX_PLANES],uint64_t * format_modifier)194 int32_t cros_gralloc_buffer::resource_info(uint32_t strides[DRV_MAX_PLANES],
195 uint32_t offsets[DRV_MAX_PLANES],
196 uint64_t *format_modifier)
197 {
198 return drv_resource_info(bo_, strides, offsets, format_modifier);
199 }
200
invalidate()201 int32_t cros_gralloc_buffer::invalidate()
202 {
203 if (lockcount_ <= 0) {
204 drv_log("Buffer was not locked.\n");
205 return -EINVAL;
206 }
207
208 if (lock_data_[0])
209 return drv_bo_invalidate(bo_, lock_data_[0]);
210
211 return 0;
212 }
213
flush()214 int32_t cros_gralloc_buffer::flush()
215 {
216 if (lockcount_ <= 0) {
217 drv_log("Buffer was not locked.\n");
218 return -EINVAL;
219 }
220
221 if (lock_data_[0])
222 return drv_bo_flush(bo_, lock_data_[0]);
223
224 return 0;
225 }
226
get_reserved_region(void ** addr,uint64_t * size) const227 int32_t cros_gralloc_buffer::get_reserved_region(void **addr, uint64_t *size) const
228 {
229 int32_t reserved_region_fd = hnd_->fds[hnd_->num_planes];
230 if (reserved_region_fd < 0) {
231 drv_log("Buffer does not have reserved region.\n");
232 return -EINVAL;
233 }
234
235 if (!reserved_region_addr_) {
236 reserved_region_addr_ =
237 mmap(nullptr, hnd_->reserved_region_size, PROT_WRITE | PROT_READ, MAP_SHARED,
238 reserved_region_fd, 0);
239 if (reserved_region_addr_ == MAP_FAILED) {
240 drv_log("Failed to mmap reserved region: %s.\n", strerror(errno));
241 return -errno;
242 }
243 }
244
245 *addr = reserved_region_addr_;
246 *size = hnd_->reserved_region_size;
247 return 0;
248 }
249