• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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