1 /*
2 * Copyright (C) 2016-2020 ARM Limited. All rights reserved.
3 *
4 * Copyright (C) 2008 The Android Open Source Project
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * You may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18 #include <errno.h>
19 #include <inttypes.h>
20 #include <inttypes.h>
21 /* For error codes. */
22 #include <hardware/gralloc1.h>
23
24 #include "mali_gralloc_buffer.h"
25 #include "mali_gralloc_formats.h"
26 #include "mali_gralloc_usages.h"
27 #include "mali_gralloc_reference.h"
28 #include "allocator/mali_gralloc_ion.h"
29 #include "gralloc_helper.h"
30 #include "format_info.h"
31
32
33 enum tx_direction
34 {
35 TX_NONE = 0,
36 TX_TO_DEVICE,
37 TX_FROM_DEVICE,
38 TX_BOTH,
39 };
40
41
get_tx_direction(const uint64_t usage)42 static enum tx_direction get_tx_direction(const uint64_t usage)
43 {
44 const bool read = (usage & GRALLOC_USAGE_SW_READ_MASK) ? true : false;
45 const bool write = (usage & GRALLOC_USAGE_SW_WRITE_MASK) ? true : false;
46 enum tx_direction dir = TX_NONE;
47
48 if (read && write)
49 {
50 dir = TX_BOTH;
51 }
52 else if (write)
53 {
54 dir = TX_TO_DEVICE;
55 }
56 else if (read)
57 {
58 dir = TX_FROM_DEVICE;
59 }
60
61 return dir;
62 }
63
buffer_sync(private_handle_t * const hnd,const enum tx_direction direction)64 static void buffer_sync(private_handle_t * const hnd,
65 const enum tx_direction direction)
66 {
67 if (direction != TX_NONE)
68 {
69 hnd->cpu_read = (direction == TX_FROM_DEVICE || direction == TX_BOTH) ? 1 : 0;
70 hnd->cpu_write = (direction == TX_TO_DEVICE || direction == TX_BOTH) ? 1 : 0;
71
72 #if defined(GRALLOC_ION_SYNC_ON_LOCK) && GRALLOC_ION_SYNC_ON_LOCK == 1
73 const int status = mali_gralloc_ion_sync_start(hnd,
74 hnd->cpu_read ? true : false,
75 hnd->cpu_write ? true : false);
76 if (status < 0)
77 {
78 return;
79 }
80 #endif
81 }
82 else if (hnd->cpu_read || hnd->cpu_write)
83 {
84 #if defined(GRALLOC_ION_SYNC_ON_LOCK) && GRALLOC_ION_SYNC_ON_LOCK == 1
85 const int status = mali_gralloc_ion_sync_end(hnd,
86 hnd->cpu_read ? true : false,
87 hnd->cpu_write ? true : false);
88 if (status < 0)
89 {
90 return;
91 }
92 #endif
93 hnd->cpu_read = 0;
94 hnd->cpu_write = 0;
95 }
96 }
97
98
99 /*
100 * Validates input parameters of lock request.
101 *
102 * @param buffer [in] The buffer to lock.
103 * @param l [in] Access region left offset (in pixels).
104 * @param t [in] Access region top offset (in pixels).
105 * @param w [in] Access region requested width (in pixels).
106 * @param h [in] Access region requested height (in pixels).
107 * @param usage [in] Lock request (producer and consumer combined) usage.
108 *
109 * @return 0,for valid input parameters;
110 * -EINVAL, for erroneous input parameters
111 */
validate_lock_input_parameters(const buffer_handle_t buffer,const int l,const int t,const int w,const int h,uint64_t usage)112 int validate_lock_input_parameters(const buffer_handle_t buffer, const int l,
113 const int t, const int w, const int h,
114 uint64_t usage)
115 {
116 const private_handle_t * const hnd = (private_handle_t *)buffer;
117
118 /* TODO: do not check access region for blob formats.
119 * This is because codec2 attempts to lock with wrong access region.
120 * Ask Google to fix codec2
121 */
122 if (hnd->get_alloc_format() != HAL_PIXEL_FORMAT_BLOB)
123 {
124 if ((l < 0) || (t < 0) || (w < 0) || (h < 0))
125 {
126 MALI_GRALLOC_LOGW("Negative values for access region (l = %d t = %d w = %d and "
127 "h = %d) in buffer lock request are invalid.", l, t, w, h);
128 return -EINVAL;
129 }
130
131 /* Test overflow conditions on access region parameters */
132 if (((l + w) < 0) || ((t + h) < 0))
133 {
134 MALI_GRALLOC_LOGW("Encountered overflow with access region (l = %d t = %d w = %d and"
135 " h = %d) in buffer lock request.", l, t, w, h);
136 return -EINVAL;
137 }
138
139 /* Region of interest shall be inside the allocated buffer */
140 if (((t + h) > hnd->height) || ((l + w) > hnd->width))
141 {
142 MALI_GRALLOC_LOGW("Buffer lock access region (l = %d t = %d w = %d "
143 "and h = %d) is outside allocated buffer (width = %d and height = %d)",
144 l, t, w, h, hnd->width, hnd->height);
145 return -EINVAL;
146 }
147 }
148
149 /* Reject lock requests for AFBC (compressed format) enabled buffers */
150 if ((hnd->alloc_format & MALI_GRALLOC_INTFMT_EXT_MASK) != 0)
151 {
152 MALI_GRALLOC_LOGE("Lock is not supported for AFBC enabled buffers."
153 "Internal Format:0x%" PRIx64, hnd->alloc_format);
154
155 return GRALLOC1_ERROR_UNSUPPORTED;
156 }
157
158 /* Producer and consumer usage is verified in gralloc1 specific code. */
159 GRALLOC_UNUSED(usage);
160
161 return 0;
162 }
163
164
165 /*
166 * Locks the given buffer for the specified CPU usage.
167 *
168 * @param m [in] Gralloc module.
169 * @param buffer [in] The buffer to lock.
170 * @param usage [in] Producer and consumer combined usage.
171 * @param l [in] Access region left offset (in pixels).
172 * @param t [in] Access region top offset (in pixels).
173 * @param w [in] Access region requested width (in pixels).
174 * @param h [in] Access region requested height (in pixels).
175 * @param vaddr [out] To be filled with a CPU-accessible pointer to
176 * the buffer data for CPU usage.
177 *
178 * @return 0, when the locking is successful;
179 * Appropriate error, otherwise
180 *
181 * @Note: There is no way to ascertain whether buffer data is valid or not (for
182 * example, establishing if the h/w needs to finish rendering or if CPU
183 * caches need to be synchronized).
184 *
185 * @Note: Locking a buffer simultaneously for write or read/write leaves the
186 * buffer's content in an indeterminate state.
187 */
mali_gralloc_lock(buffer_handle_t buffer,uint64_t usage,int l,int t,int w,int h,void ** vaddr)188 int mali_gralloc_lock(buffer_handle_t buffer,
189 uint64_t usage, int l, int t, int w, int h, void **vaddr)
190 {
191 int status;
192
193 if (mali_gralloc_reference_validate(buffer))
194 {
195 MALI_GRALLOC_LOGE("Locking invalid buffer %p, returning error", buffer);
196 return -EINVAL;
197 }
198
199 /* Validate input parameters for lock request */
200 status = validate_lock_input_parameters(buffer, l, t, w, h, usage);
201 if (status != 0)
202 {
203 return status;
204 }
205
206 private_handle_t *hnd = (private_handle_t *)buffer;
207
208 const int32_t format_idx = get_format_index(hnd->alloc_format & MALI_GRALLOC_INTFMT_FMT_MASK);
209 if (format_idx == -1)
210 {
211 MALI_GRALLOC_LOGE("Corrupted buffer format (%s 0x%" PRIx64 ") of buffer %p",
212 format_name(hnd->alloc_format), hnd->alloc_format, hnd);
213 return -EINVAL;
214 }
215
216 /* Populate CPU-accessible pointer when requested for CPU usage */
217 if ((usage & (GRALLOC_USAGE_SW_READ_MASK | GRALLOC_USAGE_SW_WRITE_MASK)) != 0)
218 {
219 if (vaddr == NULL)
220 {
221 return -EINVAL;
222 }
223
224 if (mali_gralloc_reference_map(buffer) != 0) {
225 return -EINVAL;
226 }
227
228 std::optional<void*> buf_addr = mali_gralloc_reference_get_buf_addr(buffer);
229 if (!buf_addr.has_value()) {
230 MALI_GRALLOC_LOGE("BUG: Invalid buffer address on a just mapped buffer");
231 return -EINVAL;
232 }
233 *vaddr = buf_addr.value();
234
235 buffer_sync(hnd, get_tx_direction(usage));
236 return mali_gralloc_reference_lock_retain(buffer);
237 }
238
239 return 0;
240
241 }
242
243
244 /*
245 * Unlocks the given buffer.
246 *
247 * @param buffer [in] The buffer to unlock.
248 *
249 * @return 0, when the locking is successful;
250 * Appropriate error, otherwise
251 */
mali_gralloc_unlock(buffer_handle_t buffer)252 int mali_gralloc_unlock(buffer_handle_t buffer)
253 {
254 if (private_handle_t::validate(buffer) < 0)
255 {
256 MALI_GRALLOC_LOGE("Unlocking invalid buffer %p, returning error", buffer);
257 return -EINVAL;
258 }
259
260 private_handle_t *hnd = (private_handle_t *)buffer;
261 buffer_sync(hnd, TX_NONE);
262
263 return mali_gralloc_reference_lock_release(buffer);
264 }
265