• 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 		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