• 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 
cros_gralloc_buffer(uint32_t id,struct bo * acquire_bo,struct cros_gralloc_handle * acquire_handle,int32_t reserved_region_fd,uint64_t reserved_region_size)12 cros_gralloc_buffer::cros_gralloc_buffer(uint32_t id, struct bo *acquire_bo,
13 					 struct cros_gralloc_handle *acquire_handle,
14 					 int32_t reserved_region_fd, uint64_t reserved_region_size)
15     : id_(id), bo_(acquire_bo), hnd_(acquire_handle), refcount_(1), lockcount_(0),
16       reserved_region_fd_(reserved_region_fd), reserved_region_size_(reserved_region_size),
17       reserved_region_addr_(nullptr)
18 {
19 	assert(bo_);
20 	num_planes_ = drv_bo_get_num_planes(bo_);
21 	for (uint32_t plane = 0; plane < num_planes_; plane++)
22 		lock_data_[plane] = nullptr;
23 }
24 
~cros_gralloc_buffer()25 cros_gralloc_buffer::~cros_gralloc_buffer()
26 {
27 	drv_bo_destroy(bo_);
28 	if (hnd_) {
29 		native_handle_close(hnd_);
30 		native_handle_delete(hnd_);
31 	}
32 	if (reserved_region_addr_) {
33 		munmap(reserved_region_addr_, reserved_region_size_);
34 	}
35 }
36 
get_id() const37 uint32_t cros_gralloc_buffer::get_id() const
38 {
39 	return id_;
40 }
41 
increase_refcount()42 int32_t cros_gralloc_buffer::increase_refcount()
43 {
44 	return ++refcount_;
45 }
46 
decrease_refcount()47 int32_t cros_gralloc_buffer::decrease_refcount()
48 {
49 	assert(refcount_ > 0);
50 	return --refcount_;
51 }
52 
lock(const struct rectangle * rect,uint32_t map_flags,uint8_t * addr[DRV_MAX_PLANES])53 int32_t cros_gralloc_buffer::lock(const struct rectangle *rect, uint32_t map_flags,
54 				  uint8_t *addr[DRV_MAX_PLANES])
55 {
56 	void *vaddr = nullptr;
57 
58 	memset(addr, 0, DRV_MAX_PLANES * sizeof(*addr));
59 
60 	/*
61 	 * Gralloc consumers don't support more than one kernel buffer per buffer object yet, so
62 	 * just use the first kernel buffer.
63 	 */
64 	if (drv_num_buffers_per_bo(bo_) != 1) {
65 		drv_log("Can only support one buffer per bo.\n");
66 		return -EINVAL;
67 	}
68 
69 	if (map_flags) {
70 		if (lock_data_[0]) {
71 			drv_bo_invalidate(bo_, lock_data_[0]);
72 			vaddr = lock_data_[0]->vma->addr;
73 		} else {
74 			struct rectangle r = *rect;
75 
76 			if (!r.width && !r.height && !r.x && !r.y) {
77 				/*
78 				 * Android IMapper.hal: An accessRegion of all-zeros means the
79 				 * entire buffer.
80 				 */
81 				r.width = drv_bo_get_width(bo_);
82 				r.height = drv_bo_get_height(bo_);
83 			}
84 
85 			vaddr = drv_bo_map(bo_, &r, map_flags, &lock_data_[0], 0);
86 		}
87 
88 		if (vaddr == MAP_FAILED) {
89 			drv_log("Mapping failed.\n");
90 			return -EFAULT;
91 		}
92 	}
93 
94 	for (uint32_t plane = 0; plane < num_planes_; plane++)
95 		addr[plane] = static_cast<uint8_t *>(vaddr) + drv_bo_get_plane_offset(bo_, plane);
96 
97 	lockcount_++;
98 	return 0;
99 }
100 
unlock()101 int32_t cros_gralloc_buffer::unlock()
102 {
103 	if (lockcount_ <= 0) {
104 		drv_log("Buffer was not locked.\n");
105 		return -EINVAL;
106 	}
107 
108 	if (!--lockcount_) {
109 		if (lock_data_[0]) {
110 			drv_bo_flush_or_unmap(bo_, lock_data_[0]);
111 			lock_data_[0] = nullptr;
112 		}
113 	}
114 
115 	return 0;
116 }
117 
resource_info(uint32_t strides[DRV_MAX_PLANES],uint32_t offsets[DRV_MAX_PLANES],uint64_t * format_modifier)118 int32_t cros_gralloc_buffer::resource_info(uint32_t strides[DRV_MAX_PLANES],
119 					   uint32_t offsets[DRV_MAX_PLANES],
120 					   uint64_t *format_modifier)
121 {
122 	return drv_resource_info(bo_, strides, offsets, format_modifier);
123 }
124 
invalidate()125 int32_t cros_gralloc_buffer::invalidate()
126 {
127 	if (lockcount_ <= 0) {
128 		drv_log("Buffer was not locked.\n");
129 		return -EINVAL;
130 	}
131 
132 	if (lock_data_[0])
133 		return drv_bo_invalidate(bo_, lock_data_[0]);
134 
135 	return 0;
136 }
137 
flush()138 int32_t cros_gralloc_buffer::flush()
139 {
140 	if (lockcount_ <= 0) {
141 		drv_log("Buffer was not locked.\n");
142 		return -EINVAL;
143 	}
144 
145 	if (lock_data_[0])
146 		return drv_bo_flush(bo_, lock_data_[0]);
147 
148 	return 0;
149 }
150 
get_reserved_region(void ** addr,uint64_t * size)151 int32_t cros_gralloc_buffer::get_reserved_region(void **addr, uint64_t *size)
152 {
153 	if (reserved_region_fd_ <= 0) {
154 		drv_log("Buffer does not have reserved region.\n");
155 		return -EINVAL;
156 	}
157 
158 	if (!reserved_region_addr_) {
159 		reserved_region_addr_ = mmap(nullptr, reserved_region_size_, PROT_WRITE | PROT_READ,
160 					     MAP_SHARED, reserved_region_fd_, 0);
161 		if (reserved_region_addr_ == MAP_FAILED) {
162 			drv_log("Failed to mmap reserved region: %s.\n", strerror(errno));
163 			return -errno;
164 		}
165 	}
166 
167 	*addr = reserved_region_addr_;
168 	*size = reserved_region_size_;
169 	return 0;
170 }
171