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