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