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 = GetImplDefinedFormat(info.usage, info.format);
89 int ret = GetBufferSizeAndDimensions(info, &size, &alignedw, &alignedh);
90 if (ret < 0) {
91 return Error::BAD_BUFFER;
92 }
93 auto ion_fd_size = static_cast<unsigned int>(lseek(hnd->fd, 0, SEEK_END));
94 if (size != ion_fd_size) {
95 return Error::BAD_VALUE;
96 }
97 return Error::NONE;
98 }
99
RegisterHandleLocked(const private_handle_t * hnd,int ion_handle,int ion_handle_meta)100 void BufferManager::RegisterHandleLocked(const private_handle_t *hnd, int ion_handle,
101 int ion_handle_meta) {
102 auto buffer = std::make_shared<Buffer>(hnd, ion_handle, ion_handle_meta);
103 handles_map_.emplace(std::make_pair(hnd, buffer));
104 }
105
ImportHandleLocked(private_handle_t * hnd)106 Error BufferManager::ImportHandleLocked(private_handle_t *hnd) {
107 if (private_handle_t::validate(hnd) != 0) {
108 ALOGE("ImportHandleLocked: Invalid handle: %p", hnd);
109 return Error::BAD_BUFFER;
110 }
111 ALOGD_IF(DEBUG, "Importing handle:%p id: %" PRIu64, hnd, hnd->id);
112 int ion_handle = allocator_->ImportBuffer(hnd->fd);
113 if (ion_handle < 0) {
114 ALOGE("Failed to import ion buffer: hnd: %p, fd:%d, id:%" PRIu64, hnd, hnd->fd, hnd->id);
115 return Error::BAD_BUFFER;
116 }
117 int ion_handle_meta = allocator_->ImportBuffer(hnd->fd_metadata);
118 if (ion_handle_meta < 0) {
119 ALOGE("Failed to import ion metadata buffer: hnd: %p, fd:%d, id:%" PRIu64, hnd, hnd->fd,
120 hnd->id);
121 return Error::BAD_BUFFER;
122 }
123 // Initialize members that aren't transported
124 hnd->size = static_cast<unsigned int>(lseek(hnd->fd, 0, SEEK_END));
125 hnd->offset = 0;
126 hnd->offset_metadata = 0;
127 hnd->base = 0;
128 hnd->base_metadata = 0;
129 hnd->gpuaddr = 0;
130 RegisterHandleLocked(hnd, ion_handle, ion_handle_meta);
131 return Error::NONE;
132 }
133
GetBufferFromHandleLocked(const private_handle_t * hnd)134 std::shared_ptr<BufferManager::Buffer> BufferManager::GetBufferFromHandleLocked(
135 const private_handle_t *hnd) {
136 auto it = handles_map_.find(hnd);
137 if (it != handles_map_.end()) {
138 return it->second;
139 } else {
140 return nullptr;
141 }
142 }
143
MapBuffer(private_handle_t const * handle)144 Error BufferManager::MapBuffer(private_handle_t const *handle) {
145 private_handle_t *hnd = const_cast<private_handle_t *>(handle);
146 ALOGD_IF(DEBUG, "Map buffer handle:%p id: %" PRIu64, hnd, hnd->id);
147
148 hnd->base = 0;
149 if (allocator_->MapBuffer(reinterpret_cast<void **>(&hnd->base), hnd->size, hnd->offset,
150 hnd->fd) != 0) {
151 return Error::BAD_BUFFER;
152 }
153 return Error::NONE;
154 }
155
IsBufferImported(const private_handle_t * hnd)156 Error BufferManager::IsBufferImported(const private_handle_t *hnd) {
157 std::lock_guard<std::mutex> lock(buffer_lock_);
158 auto buf = GetBufferFromHandleLocked(hnd);
159 if (buf != nullptr) {
160 return Error::NONE;
161 }
162 return Error::BAD_BUFFER;
163 }
164
RetainBuffer(private_handle_t const * hnd)165 Error BufferManager::RetainBuffer(private_handle_t const *hnd) {
166 ALOGD_IF(DEBUG, "Retain buffer handle:%p id: %" PRIu64, hnd, hnd->id);
167 auto err = Error::NONE;
168 std::lock_guard<std::mutex> lock(buffer_lock_);
169 auto buf = GetBufferFromHandleLocked(hnd);
170 if (buf != nullptr) {
171 buf->IncRef();
172 } else {
173 private_handle_t *handle = const_cast<private_handle_t *>(hnd);
174 err = ImportHandleLocked(handle);
175 }
176 return err;
177 }
178
ReleaseBuffer(private_handle_t const * hnd)179 Error BufferManager::ReleaseBuffer(private_handle_t const *hnd) {
180 ALOGD_IF(DEBUG, "Release buffer handle:%p", hnd);
181 std::lock_guard<std::mutex> lock(buffer_lock_);
182 auto buf = GetBufferFromHandleLocked(hnd);
183 if (buf == nullptr) {
184 ALOGE("Could not find handle: %p id: %" PRIu64, hnd, hnd->id);
185 return Error::BAD_BUFFER;
186 } else {
187 if (buf->DecRef()) {
188 handles_map_.erase(hnd);
189 // Unmap, close ion handle and close fd
190 FreeBuffer(buf);
191 }
192 }
193 return Error::NONE;
194 }
195
LockBuffer(const private_handle_t * hnd,uint64_t usage)196 Error BufferManager::LockBuffer(const private_handle_t *hnd, uint64_t usage) {
197 std::lock_guard<std::mutex> lock(buffer_lock_);
198 auto err = Error::NONE;
199 ALOGD_IF(DEBUG, "LockBuffer buffer handle:%p id: %" PRIu64, hnd, hnd->id);
200
201 // If buffer is not meant for CPU return err
202 if (!CpuCanAccess(usage)) {
203 return Error::BAD_VALUE;
204 }
205
206 auto buf = GetBufferFromHandleLocked(hnd);
207 if (buf == nullptr) {
208 return Error::BAD_BUFFER;
209 }
210
211 if (hnd->base == 0) {
212 // we need to map for real
213 err = MapBuffer(hnd);
214 }
215
216 // Invalidate if CPU reads in software and there are non-CPU
217 // writers. No need to do this for the metadata buffer as it is
218 // only read/written in software.
219
220 // todo use handle here
221 if (err == Error::NONE && (hnd->flags & private_handle_t::PRIV_FLAGS_USES_ION) &&
222 (hnd->flags & private_handle_t::PRIV_FLAGS_CACHED)) {
223 if (allocator_->CleanBuffer(reinterpret_cast<void *>(hnd->base), hnd->size, hnd->offset,
224 buf->ion_handle_main, CACHE_INVALIDATE, hnd->fd)) {
225 return Error::BAD_BUFFER;
226 }
227 }
228
229 // Mark the buffer to be flushed after CPU write.
230 if (err == Error::NONE && CpuCanWrite(usage)) {
231 private_handle_t *handle = const_cast<private_handle_t *>(hnd);
232 handle->flags |= private_handle_t::PRIV_FLAGS_NEEDS_FLUSH;
233 }
234
235 return err;
236 }
237
UnlockBuffer(const private_handle_t * handle)238 Error BufferManager::UnlockBuffer(const private_handle_t *handle) {
239 std::lock_guard<std::mutex> lock(buffer_lock_);
240 auto status = Error::NONE;
241
242 private_handle_t *hnd = const_cast<private_handle_t *>(handle);
243 auto buf = GetBufferFromHandleLocked(hnd);
244 if (buf == nullptr) {
245 return Error::BAD_BUFFER;
246 }
247
248 if (hnd->flags & private_handle_t::PRIV_FLAGS_NEEDS_FLUSH) {
249 if (allocator_->CleanBuffer(reinterpret_cast<void *>(hnd->base), hnd->size, hnd->offset,
250 buf->ion_handle_main, CACHE_CLEAN, hnd->fd) != 0) {
251 status = Error::BAD_BUFFER;
252 }
253 hnd->flags &= ~private_handle_t::PRIV_FLAGS_NEEDS_FLUSH;
254 } else {
255 if (allocator_->CleanBuffer(reinterpret_cast<void *>(hnd->base), hnd->size, hnd->offset,
256 buf->ion_handle_main, CACHE_READ_DONE, hnd->fd) != 0) {
257 status = Error::BAD_BUFFER;
258 }
259 }
260
261 return status;
262 }
263
AllocateBuffer(const BufferDescriptor & descriptor,buffer_handle_t * handle,unsigned int bufferSize,bool testAlloc)264 Error BufferManager::AllocateBuffer(const BufferDescriptor &descriptor, buffer_handle_t *handle,
265 unsigned int bufferSize, bool testAlloc) {
266 if (!handle)
267 return Error::BAD_BUFFER;
268 std::lock_guard<std::mutex> buffer_lock(buffer_lock_);
269
270 uint64_t usage = descriptor.GetUsage();
271 int format = GetImplDefinedFormat(usage, descriptor.GetFormat());
272 uint32_t layer_count = descriptor.GetLayerCount();
273
274 unsigned int size;
275 unsigned int alignedw, alignedh;
276 int err = 0;
277
278 int buffer_type = GetBufferType(format);
279 BufferInfo info = GetBufferInfo(descriptor);
280 info.format = format;
281 info.layer_count = layer_count;
282
283 GraphicsMetadata graphics_metadata = {};
284 err = GetBufferSizeAndDimensions(info, &size, &alignedw, &alignedh, &graphics_metadata);
285 if (err < 0) {
286 return Error::BAD_DESCRIPTOR;
287 }
288
289 if (testAlloc) {
290 return Error::NONE;
291 }
292
293 size = (bufferSize >= size) ? bufferSize : size;
294 uint64_t flags = 0;
295 auto page_size = UINT(getpagesize());
296 AllocData data;
297 data.align = GetDataAlignment(format, usage);
298 data.size = size;
299 data.handle = (uintptr_t)handle;
300 data.uncached = UseUncached(format, usage);
301
302 // Allocate buffer memory
303 err = allocator_->AllocateMem(&data, usage, format);
304 if (err) {
305 ALOGE("gralloc failed to allocate err=%s format %d size %d WxH %dx%d usage %" PRIu64,
306 strerror(-err), format, size, alignedw, alignedh, usage);
307 return Error::NO_RESOURCES;
308 }
309
310 // Allocate memory for MetaData
311 AllocData e_data;
312 e_data.size = ALIGN(UINT(sizeof(MetaData_t)), page_size);
313 e_data.handle = data.handle;
314 e_data.align = page_size;
315
316 err = allocator_->AllocateMem(&e_data, 0, 0);
317 if (err) {
318 ALOGE("gralloc failed to allocate metadata error=%s", strerror(-err));
319 return Error::NO_RESOURCES;
320 }
321
322 flags = GetHandleFlags(format, usage);
323 flags |= data.alloc_type;
324
325 // Create handle
326 private_handle_t *hnd = new private_handle_t(
327 data.fd, e_data.fd, INT(flags), INT(alignedw), INT(alignedh), descriptor.GetWidth(),
328 descriptor.GetHeight(), format, buffer_type, data.size, usage);
329
330 hnd->id = ++next_id_;
331 hnd->base = 0;
332 hnd->base_metadata = 0;
333 hnd->layer_count = layer_count;
334 // set default csc as 709, but for video(yuv) its 601L
335 ColorSpace_t colorSpace = (buffer_type == BUFFER_TYPE_VIDEO) ? ITU_R_601 : ITU_R_709;
336 setMetaDataAndUnmap(hnd, UPDATE_COLOR_SPACE, reinterpret_cast<void *>(&colorSpace));
337
338 bool use_adreno_for_size = CanUseAdrenoForSize(buffer_type, usage);
339 if (use_adreno_for_size) {
340 setMetaDataAndUnmap(hnd, SET_GRAPHICS_METADATA, reinterpret_cast<void *>(&graphics_metadata));
341 }
342
343 *handle = hnd;
344 RegisterHandleLocked(hnd, data.ion_handle, e_data.ion_handle);
345 ALOGD_IF(DEBUG, "Allocated buffer handle: %p id: %" PRIu64, hnd, hnd->id);
346 if (DEBUG) {
347 private_handle_t::Dump(hnd);
348 }
349 return Error::NONE;
350 }
351
Dump(std::ostringstream * os)352 Error BufferManager::Dump(std::ostringstream *os) {
353 std::lock_guard<std::mutex> buffer_lock(buffer_lock_);
354 for (auto it : handles_map_) {
355 auto buf = it.second;
356 auto hnd = buf->handle;
357 *os << "handle id: " << std::setw(4) << hnd->id;
358 *os << " fd: " << std::setw(3) << hnd->fd;
359 *os << " fd_meta: " << std::setw(3) << hnd->fd_metadata;
360 *os << " wxh: " << std::setw(4) << hnd->width << " x " << std::setw(4) << hnd->height;
361 *os << " uwxuh: " << std::setw(4) << hnd->unaligned_width << " x ";
362 *os << std::setw(4) << hnd->unaligned_height;
363 *os << " size: " << std::setw(9) << hnd->size;
364 *os << std::hex << std::setfill('0');
365 *os << " priv_flags: "
366 << "0x" << std::setw(8) << hnd->flags;
367 *os << " usage: "
368 << "0x" << std::setw(8) << hnd->usage;
369 // TODO(user): get format string from qdutils
370 *os << " format: "
371 << "0x" << std::setw(8) << hnd->format;
372 *os << std::dec << std::setfill(' ') << std::endl;
373 }
374 return Error::NONE;
375 }
376 } // namespace gralloc
377