1 /*
2 * Copyright (c) 2011-2018 The Linux Foundation. All rights reserved.
3 * Not a Contribution
4 *
5 * Copyright (C) 2010 The Android Open Source Project
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 */
19
20 #define DEBUG 0
21
22 #include <iomanip>
23 #include <sstream>
24 #include <utility>
25 #include <vector>
26
27 #include "gr_buf_descriptor.h"
28 #include "gr_buf_mgr.h"
29 #include "gr_priv_handle.h"
30 #include "qdMetaData.h"
31 #include "qd_utils.h"
32
33 namespace gralloc {
34
GetBufferInfo(const BufferDescriptor & descriptor)35 static BufferInfo GetBufferInfo(const BufferDescriptor &descriptor) {
36 return BufferInfo(descriptor.GetWidth(), descriptor.GetHeight(), descriptor.GetFormat(),
37 descriptor.GetUsage());
38 }
39
BufferManager()40 BufferManager::BufferManager() : next_id_(0) {
41 handles_map_.clear();
42 allocator_ = new Allocator();
43 allocator_->Init();
44 }
45
GetInstance()46 BufferManager *BufferManager::GetInstance() {
47 static BufferManager *instance = new BufferManager();
48 return instance;
49 }
50
~BufferManager()51 BufferManager::~BufferManager() {
52 if (allocator_) {
53 delete allocator_;
54 }
55 }
56
FreeBuffer(std::shared_ptr<Buffer> buf)57 Error BufferManager::FreeBuffer(std::shared_ptr<Buffer> buf) {
58 auto hnd = buf->handle;
59 ALOGD_IF(DEBUG, "FreeBuffer handle:%p", hnd);
60
61 if (private_handle_t::validate(hnd) != 0) {
62 ALOGE("FreeBuffer: Invalid handle: %p", hnd);
63 return Error::BAD_BUFFER;
64 }
65
66 if (allocator_->FreeBuffer(reinterpret_cast<void *>(hnd->base), hnd->size, hnd->offset, hnd->fd,
67 buf->ion_handle_main) != 0) {
68 return Error::BAD_BUFFER;
69 }
70
71 unsigned int meta_size = ALIGN((unsigned int)sizeof(MetaData_t), PAGE_SIZE);
72 if (allocator_->FreeBuffer(reinterpret_cast<void *>(hnd->base_metadata), meta_size,
73 hnd->offset_metadata, hnd->fd_metadata, buf->ion_handle_meta) != 0) {
74 return Error::BAD_BUFFER;
75 }
76
77 private_handle_t *handle = const_cast<private_handle_t *>(hnd);
78 handle->fd = -1;
79 handle->fd_metadata = -1;
80 if (!(handle->flags & private_handle_t::PRIV_FLAGS_CLIENT_ALLOCATED)) {
81 delete handle;
82 }
83 return Error::NONE;
84 }
85
ValidateBufferSize(private_handle_t const * hnd,BufferInfo info)86 Error BufferManager::ValidateBufferSize(private_handle_t const *hnd, BufferInfo info) {
87 unsigned int size, alignedw, alignedh;
88 info.format = allocator_->GetImplDefinedFormat(info.usage, info.format);
89 GetBufferSizeAndDimensions(info, &size, &alignedw, &alignedh);
90 auto ion_fd_size = static_cast<unsigned int>(lseek(hnd->fd, 0, SEEK_END));
91 if (size != ion_fd_size) {
92 return Error::BAD_VALUE;
93 }
94 return Error::NONE;
95 }
96
RegisterHandleLocked(const private_handle_t * hnd,int ion_handle,int ion_handle_meta)97 void BufferManager::RegisterHandleLocked(const private_handle_t *hnd, int ion_handle,
98 int ion_handle_meta) {
99 auto buffer = std::make_shared<Buffer>(hnd, ion_handle, ion_handle_meta);
100 handles_map_.emplace(std::make_pair(hnd, buffer));
101 }
102
ImportHandleLocked(private_handle_t * hnd)103 Error BufferManager::ImportHandleLocked(private_handle_t *hnd) {
104 if (private_handle_t::validate(hnd) != 0) {
105 ALOGE("ImportHandleLocked: Invalid handle: %p", hnd);
106 return Error::BAD_BUFFER;
107 }
108 ALOGD_IF(DEBUG, "Importing handle:%p id: %" PRIu64, hnd, hnd->id);
109 int ion_handle = allocator_->ImportBuffer(hnd->fd);
110 if (ion_handle < 0) {
111 ALOGE("Failed to import ion buffer: hnd: %p, fd:%d, id:%" PRIu64, hnd, hnd->fd, hnd->id);
112 return Error::BAD_BUFFER;
113 }
114 int ion_handle_meta = allocator_->ImportBuffer(hnd->fd_metadata);
115 if (ion_handle_meta < 0) {
116 ALOGE("Failed to import ion metadata buffer: hnd: %p, fd:%d, id:%" PRIu64, hnd, hnd->fd,
117 hnd->id);
118 return Error::BAD_BUFFER;
119 }
120 // Initialize members that aren't transported
121 hnd->size = static_cast<unsigned int>(lseek(hnd->fd, 0, SEEK_END));
122 hnd->offset = 0;
123 hnd->offset_metadata = 0;
124 hnd->base = 0;
125 hnd->base_metadata = 0;
126 hnd->gpuaddr = 0;
127 RegisterHandleLocked(hnd, ion_handle, ion_handle_meta);
128 return Error::NONE;
129 }
130
GetBufferFromHandleLocked(const private_handle_t * hnd)131 std::shared_ptr<BufferManager::Buffer> BufferManager::GetBufferFromHandleLocked(
132 const private_handle_t *hnd) {
133 auto it = handles_map_.find(hnd);
134 if (it != handles_map_.end()) {
135 return it->second;
136 } else {
137 return nullptr;
138 }
139 }
140
MapBuffer(private_handle_t const * handle)141 Error BufferManager::MapBuffer(private_handle_t const *handle) {
142 private_handle_t *hnd = const_cast<private_handle_t *>(handle);
143 ALOGD_IF(DEBUG, "Map buffer handle:%p id: %" PRIu64, hnd, hnd->id);
144
145 hnd->base = 0;
146 if (allocator_->MapBuffer(reinterpret_cast<void **>(&hnd->base), hnd->size, hnd->offset,
147 hnd->fd) != 0) {
148 return Error::BAD_BUFFER;
149 }
150 return Error::NONE;
151 }
152
IsBufferImported(const private_handle_t * hnd)153 Error BufferManager::IsBufferImported(const private_handle_t *hnd) {
154 std::lock_guard<std::mutex> lock(buffer_lock_);
155 auto buf = GetBufferFromHandleLocked(hnd);
156 if (buf != nullptr) {
157 return Error::NONE;
158 }
159 return Error::BAD_BUFFER;
160 }
161
RetainBuffer(private_handle_t const * hnd)162 Error BufferManager::RetainBuffer(private_handle_t const *hnd) {
163 ALOGD_IF(DEBUG, "Retain buffer handle:%p id: %" PRIu64, hnd, hnd->id);
164 auto err = Error::NONE;
165 std::lock_guard<std::mutex> lock(buffer_lock_);
166 auto buf = GetBufferFromHandleLocked(hnd);
167 if (buf != nullptr) {
168 buf->IncRef();
169 } else {
170 private_handle_t *handle = const_cast<private_handle_t *>(hnd);
171 err = ImportHandleLocked(handle);
172 }
173 return err;
174 }
175
ReleaseBuffer(private_handle_t const * hnd)176 Error BufferManager::ReleaseBuffer(private_handle_t const *hnd) {
177 ALOGD_IF(DEBUG, "Release buffer handle:%p", hnd);
178 std::lock_guard<std::mutex> lock(buffer_lock_);
179 auto buf = GetBufferFromHandleLocked(hnd);
180 if (buf == nullptr) {
181 ALOGE("Could not find handle: %p id: %" PRIu64, hnd, hnd->id);
182 return Error::BAD_BUFFER;
183 } else {
184 if (buf->DecRef()) {
185 handles_map_.erase(hnd);
186 // Unmap, close ion handle and close fd
187 FreeBuffer(buf);
188 }
189 }
190 return Error::NONE;
191 }
192
LockBuffer(const private_handle_t * hnd,uint64_t usage)193 Error BufferManager::LockBuffer(const private_handle_t *hnd, uint64_t usage) {
194 std::lock_guard<std::mutex> lock(buffer_lock_);
195 auto err = Error::NONE;
196 ALOGD_IF(DEBUG, "LockBuffer buffer handle:%p id: %" PRIu64, hnd, hnd->id);
197
198 // If buffer is not meant for CPU return err
199 if (!CpuCanAccess(usage)) {
200 return Error::BAD_VALUE;
201 }
202
203 auto buf = GetBufferFromHandleLocked(hnd);
204 if (buf == nullptr) {
205 return Error::BAD_BUFFER;
206 }
207
208 if (hnd->base == 0) {
209 // we need to map for real
210 err = MapBuffer(hnd);
211 }
212
213 // Invalidate if CPU reads in software and there are non-CPU
214 // writers. No need to do this for the metadata buffer as it is
215 // only read/written in software.
216
217 // todo use handle here
218 if (err == Error::NONE && (hnd->flags & private_handle_t::PRIV_FLAGS_USES_ION) &&
219 (hnd->flags & private_handle_t::PRIV_FLAGS_CACHED)) {
220 if (allocator_->CleanBuffer(reinterpret_cast<void *>(hnd->base), hnd->size, hnd->offset,
221 buf->ion_handle_main, CACHE_INVALIDATE)) {
222 return Error::BAD_BUFFER;
223 }
224 }
225
226 // Mark the buffer to be flushed after CPU write.
227 if (err == Error::NONE && CpuCanWrite(usage)) {
228 private_handle_t *handle = const_cast<private_handle_t *>(hnd);
229 handle->flags |= private_handle_t::PRIV_FLAGS_NEEDS_FLUSH;
230 }
231
232 return err;
233 }
234
UnlockBuffer(const private_handle_t * handle)235 Error BufferManager::UnlockBuffer(const private_handle_t *handle) {
236 std::lock_guard<std::mutex> lock(buffer_lock_);
237 auto status = Error::NONE;
238
239 private_handle_t *hnd = const_cast<private_handle_t *>(handle);
240 auto buf = GetBufferFromHandleLocked(hnd);
241 if (buf == nullptr) {
242 return Error::BAD_BUFFER;
243 }
244
245 if (hnd->flags & private_handle_t::PRIV_FLAGS_NEEDS_FLUSH) {
246 if (allocator_->CleanBuffer(reinterpret_cast<void *>(hnd->base), hnd->size, hnd->offset,
247 buf->ion_handle_main, CACHE_CLEAN) != 0) {
248 status = Error::BAD_BUFFER;
249 }
250 hnd->flags &= ~private_handle_t::PRIV_FLAGS_NEEDS_FLUSH;
251 }
252
253 return status;
254 }
255
GetHandleFlags(int format,uint64_t usage)256 int BufferManager::GetHandleFlags(int format, uint64_t usage) {
257 int flags = 0;
258 if (usage & BufferUsage::VIDEO_ENCODER) {
259 flags |= private_handle_t::PRIV_FLAGS_VIDEO_ENCODER;
260 }
261
262 if (usage & BufferUsage::CAMERA_OUTPUT) {
263 flags |= private_handle_t::PRIV_FLAGS_CAMERA_WRITE;
264 }
265
266 if (usage & BufferUsage::CAMERA_INPUT) {
267 flags |= private_handle_t::PRIV_FLAGS_CAMERA_READ;
268 }
269
270 if (usage & BufferUsage::COMPOSER_OVERLAY) {
271 flags |= private_handle_t::PRIV_FLAGS_DISP_CONSUMER;
272 }
273
274 if (usage & BufferUsage::GPU_TEXTURE) {
275 flags |= private_handle_t::PRIV_FLAGS_HW_TEXTURE;
276 }
277
278 if (usage & GRALLOC_USAGE_PRIVATE_SECURE_DISPLAY) {
279 flags |= private_handle_t::PRIV_FLAGS_SECURE_DISPLAY;
280 }
281
282 if (IsUBwcEnabled(format, usage)) {
283 flags |= private_handle_t::PRIV_FLAGS_UBWC_ALIGNED;
284 }
285
286 if (usage & (BufferUsage::CPU_READ_MASK | BufferUsage::CPU_WRITE_MASK)) {
287 flags |= private_handle_t::PRIV_FLAGS_CPU_RENDERED;
288 }
289
290 if ((usage & (BufferUsage::VIDEO_ENCODER | BufferUsage::VIDEO_DECODER |
291 BufferUsage::CAMERA_OUTPUT | BufferUsage::GPU_RENDER_TARGET))) {
292 flags |= private_handle_t::PRIV_FLAGS_NON_CPU_WRITER;
293 }
294
295 if (!allocator_->UseUncached(usage)) {
296 flags |= private_handle_t::PRIV_FLAGS_CACHED;
297 }
298
299 return flags;
300 }
301
AllocateBuffer(const BufferDescriptor & descriptor,buffer_handle_t * handle,unsigned int bufferSize)302 Error BufferManager::AllocateBuffer(const BufferDescriptor &descriptor, buffer_handle_t *handle,
303 unsigned int bufferSize) {
304 if (!handle)
305 return Error::BAD_BUFFER;
306 std::lock_guard<std::mutex> buffer_lock(buffer_lock_);
307
308 uint64_t usage = descriptor.GetUsage();
309 int format = allocator_->GetImplDefinedFormat(usage, descriptor.GetFormat());
310 uint32_t layer_count = descriptor.GetLayerCount();
311
312 unsigned int size;
313 unsigned int alignedw, alignedh;
314
315 int buffer_type = GetBufferType(format);
316 BufferInfo info = GetBufferInfo(descriptor);
317 info.format = format;
318 info.layer_count = layer_count;
319
320 GraphicsMetadata graphics_metadata = {};
321 GetBufferSizeAndDimensions(info, &size, &alignedw, &alignedh, &graphics_metadata);
322
323 size = (bufferSize >= size) ? bufferSize : size;
324 int err = 0;
325 int flags = 0;
326 auto page_size = UINT(getpagesize());
327 AllocData data;
328 data.align = GetDataAlignment(format, usage);
329 data.size = size;
330 data.handle = (uintptr_t)handle;
331 data.uncached = allocator_->UseUncached(usage);
332
333 // Allocate buffer memory
334 err = allocator_->AllocateMem(&data, usage);
335 if (err) {
336 ALOGE("gralloc failed to allocate err=%s", strerror(-err));
337 return Error::NO_RESOURCES;
338 }
339
340 // Allocate memory for MetaData
341 AllocData e_data;
342 e_data.size = ALIGN(UINT(sizeof(MetaData_t)), page_size);
343 e_data.handle = data.handle;
344 e_data.align = page_size;
345
346 err = allocator_->AllocateMem(&e_data, 0);
347 if (err) {
348 ALOGE("gralloc failed to allocate metadata error=%s", strerror(-err));
349 return Error::NO_RESOURCES;
350 }
351
352 flags = GetHandleFlags(format, usage);
353 flags |= data.alloc_type;
354
355 // Create handle
356 private_handle_t *hnd = new private_handle_t(
357 data.fd, e_data.fd, flags, INT(alignedw), INT(alignedh), descriptor.GetWidth(),
358 descriptor.GetHeight(), format, buffer_type, data.size, usage);
359
360 hnd->id = ++next_id_;
361 hnd->base = 0;
362 hnd->base_metadata = 0;
363 hnd->layer_count = layer_count;
364
365 ColorSpace_t colorSpace = ITU_R_601;
366 setMetaDataAndUnmap(hnd, UPDATE_COLOR_SPACE, reinterpret_cast<void *>(&colorSpace));
367
368 bool use_adreno_for_size = CanUseAdrenoForSize(buffer_type, usage);
369 if (use_adreno_for_size) {
370 setMetaDataAndUnmap(hnd, SET_GRAPHICS_METADATA, reinterpret_cast<void *>(&graphics_metadata));
371 }
372
373 *handle = hnd;
374 RegisterHandleLocked(hnd, data.ion_handle, e_data.ion_handle);
375 ALOGD_IF(DEBUG, "Allocated buffer handle: %p id: %" PRIu64, hnd, hnd->id);
376 if (DEBUG) {
377 private_handle_t::Dump(hnd);
378 }
379 return Error::NONE;
380 }
381
Dump(std::ostringstream * os)382 Error BufferManager::Dump(std::ostringstream *os) {
383 std::lock_guard<std::mutex> buffer_lock(buffer_lock_);
384 for (auto it : handles_map_) {
385 auto buf = it.second;
386 auto hnd = buf->handle;
387 *os << "handle id: " << std::setw(4) << hnd->id;
388 *os << " fd: " << std::setw(3) << hnd->fd;
389 *os << " fd_meta: " << std::setw(3) << hnd->fd_metadata;
390 *os << " wxh: " << std::setw(4) << hnd->width << " x " << std::setw(4) << hnd->height;
391 *os << " uwxuh: " << std::setw(4) << hnd->unaligned_width << " x ";
392 *os << std::setw(4) << hnd->unaligned_height;
393 *os << " size: " << std::setw(9) << hnd->size;
394 *os << std::hex << std::setfill('0');
395 *os << " priv_flags: "
396 << "0x" << std::setw(8) << hnd->flags;
397 *os << " usage: "
398 << "0x" << std::setw(8) << hnd->usage;
399 // TODO(user): get format string from qdutils
400 *os << " format: "
401 << "0x" << std::setw(8) << hnd->format;
402 *os << std::dec << std::setfill(' ') << std::endl;
403 }
404 return Error::NONE;
405 }
406 } // namespace gralloc
407