1 /*
2 // Copyright (c) 2014 Intel Corporation 
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //      http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 */
16 
17 #include <common/utils/HwcTrace.h>
18 #include <hardware/hwcomposer.h>
19 #include <BufferManager.h>
20 #include <DrmConfig.h>
21 
22 namespace android {
23 namespace intel {
24 
BufferManager()25 BufferManager::BufferManager()
26     : mGrallocModule(NULL),
27       mAllocDev(NULL),
28       mFrameBuffers(),
29       mBufferPool(NULL),
30       mDataBuffer(NULL),
31       mDataBufferLock(),
32       mInitialized(false)
33 {
34     CTRACE();
35 }
36 
~BufferManager()37 BufferManager::~BufferManager()
38 {
39     WARN_IF_NOT_DEINIT();
40 }
41 
initCheck() const42 bool BufferManager::initCheck() const
43 {
44     return mInitialized;
45 }
46 
initialize()47 bool BufferManager::initialize()
48 {
49     CTRACE();
50 
51     // create buffer pool
52     mBufferPool = new BufferCache(DEFAULT_BUFFER_POOL_SIZE);
53     if (!mBufferPool) {
54         ELOGTRACE("failed to create gralloc buffer cache");
55         return false;
56     }
57 
58     // init gralloc module
59     hw_module_t const* module;
60     if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module)) {
61         DEINIT_AND_RETURN_FALSE("failed to get gralloc module");
62     }
63     mGrallocModule = (gralloc_module_t const*)module;
64 
65     gralloc_open(module, &mAllocDev);
66     if (!mAllocDev) {
67         WLOGTRACE("failed to open alloc device");
68     }
69 
70     // create a dummy data buffer
71     mDataBuffer = createDataBuffer(0);
72     if (!mDataBuffer) {
73         DEINIT_AND_RETURN_FALSE("failed to create data buffer");
74     }
75 
76     mInitialized = true;
77     return true;
78 }
79 
deinitialize()80 void BufferManager::deinitialize()
81 {
82     mInitialized = false;
83 
84     if (mBufferPool) {
85         // unmap & delete all cached buffer mappers
86         for (size_t i = 0; i < mBufferPool->getCacheSize(); i++) {
87             BufferMapper *mapper = mBufferPool->getMapper(i);
88             mapper->unmap();
89             delete mapper;
90         }
91 
92         delete mBufferPool;
93         mBufferPool = NULL;
94     }
95 
96     for (size_t j = 0; j < mFrameBuffers.size(); j++) {
97         BufferMapper *mapper = mFrameBuffers.valueAt(j);
98         mapper->unmap();
99         delete mapper;
100     }
101     mFrameBuffers.clear();
102 
103     if (mAllocDev) {
104         gralloc_close(mAllocDev);
105         mAllocDev = NULL;
106     }
107 
108     if (mDataBuffer) {
109         delete mDataBuffer;
110         mDataBuffer = NULL;
111     }
112 }
113 
dump(Dump & d)114 void BufferManager::dump(Dump& d)
115 {
116     d.append("Buffer Manager status: pool size %d\n", mBufferPool->getCacheSize());
117     d.append("-------------------------------------------------------------\n");
118     for (size_t i = 0; i < mBufferPool->getCacheSize(); i++) {
119         BufferMapper *mapper = mBufferPool->getMapper(i);
120         d.append("Buffer %d: handle %#x, (%dx%d), format %d, refCount %d\n",
121                  i,
122                  mapper->getHandle(),
123                  mapper->getWidth(),
124                  mapper->getHeight(),
125                  mapper->getFormat(),
126                  mapper->getRef());
127     }
128     return;
129 }
130 
lockDataBuffer(uint32_t handle)131 DataBuffer* BufferManager::lockDataBuffer(uint32_t handle)
132 {
133     mDataBufferLock.lock();
134     mDataBuffer->resetBuffer(handle);
135     return mDataBuffer;
136 }
137 
unlockDataBuffer(DataBuffer *)138 void BufferManager::unlockDataBuffer(DataBuffer * /* buffer */)
139 {
140     mDataBufferLock.unlock();
141 }
142 
get(uint32_t handle)143 DataBuffer* BufferManager::get(uint32_t handle)
144 {
145     return createDataBuffer(handle);
146 }
147 
put(DataBuffer * buffer)148 void BufferManager::put(DataBuffer *buffer)
149 {
150     delete buffer;
151 }
152 
map(DataBuffer & buffer)153 BufferMapper* BufferManager::map(DataBuffer& buffer)
154 {
155     bool ret;
156     BufferMapper* mapper;
157 
158     CTRACE();
159     Mutex::Autolock _l(mLock);
160     //try to get mapper from pool
161     mapper = mBufferPool->getMapper(buffer.getKey());
162     if (mapper) {
163         // increase mapper ref count
164         mapper->incRef();
165         return mapper;
166     }
167 
168     // create a new buffer mapper and add it to pool
169     do {
170         VLOGTRACE("new buffer, will add it");
171         mapper = createBufferMapper(buffer);
172         if (!mapper) {
173             ELOGTRACE("failed to allocate mapper");
174             break;
175         }
176         ret = mapper->map();
177         if (!ret) {
178             ELOGTRACE("failed to map");
179             delete mapper;
180             mapper = NULL;
181             break;
182         }
183         ret = mBufferPool->addMapper(buffer.getKey(), mapper);
184         if (!ret) {
185             ELOGTRACE("failed to add mapper");
186             break;
187         }
188         // increase mapper ref count
189         mapper->incRef();
190         return mapper;
191     } while (0);
192 
193     // error handling
194     if (mapper) {
195         mapper->unmap();
196         delete mapper;
197     }
198     return NULL;
199 }
200 
unmap(BufferMapper * mapper)201 void BufferManager::unmap(BufferMapper *mapper)
202 {
203     Mutex::Autolock _l(mLock);
204     if (!mapper) {
205         ELOGTRACE("invalid mapper");
206         return;
207     }
208 
209     // unmap & remove this mapper from buffer when refCount = 0
210     int refCount = mapper->decRef();
211     if (refCount < 0) {
212         ELOGTRACE("invalid ref count");
213     } else if (!refCount) {
214         // remove mapper from buffer pool
215         mBufferPool->removeMapper(mapper);
216         mapper->unmap();
217         delete mapper;
218     }
219 }
220 
allocFrameBuffer(int width,int height,int * stride)221 uint32_t BufferManager::allocFrameBuffer(int width, int height, int *stride)
222 {
223     RETURN_NULL_IF_NOT_INIT();
224 
225     if (!mAllocDev) {
226         WLOGTRACE("Alloc device is not available");
227         return 0;
228     }
229 
230     if (!width || !height || !stride) {
231         ELOGTRACE("invalid input parameter");
232         return 0;
233     }
234 
235     ILOGTRACE("size of frame buffer to create: %dx%d", width, height);
236     uint32_t handle = 0;
237     status_t err  = mAllocDev->alloc(
238             mAllocDev,
239             width,
240             height,
241             DrmConfig::getFrameBufferFormat(),
242             0, // GRALLOC_USAGE_HW_FB
243             (buffer_handle_t *)&handle,
244             stride);
245 
246     if (err != 0) {
247         ELOGTRACE("failed to allocate frame buffer, error = %d", err);
248         return 0;
249     }
250 
251     DataBuffer *buffer = NULL;
252     BufferMapper *mapper = NULL;
253 
254     do {
255         buffer = lockDataBuffer(handle);
256         if (!buffer) {
257             ELOGTRACE("failed to get data buffer, handle = %#x", handle);
258             break;
259         }
260 
261         mapper = createBufferMapper(*buffer);
262         if (!mapper) {
263             ELOGTRACE("failed to create buffer mapper");
264             break;
265         }
266 
267         uint32_t fbHandle;
268          if (!(fbHandle = mapper->getFbHandle(0))) {
269              ELOGTRACE("failed to get Fb handle");
270              break;
271          }
272 
273         mFrameBuffers.add(fbHandle, mapper);
274         unlockDataBuffer(buffer);
275         return fbHandle;
276     } while (0);
277 
278     // error handling, release all allocated resources
279     if (buffer) {
280         unlockDataBuffer(buffer);
281     }
282     if (mapper) {
283         delete mapper;
284     }
285     mAllocDev->free(mAllocDev, (buffer_handle_t)handle);
286     return 0;
287 }
288 
freeFrameBuffer(uint32_t fbHandle)289 void BufferManager::freeFrameBuffer(uint32_t fbHandle)
290 {
291     RETURN_VOID_IF_NOT_INIT();
292 
293     if (!mAllocDev) {
294         WLOGTRACE("Alloc device is not available");
295         return;
296     }
297 
298     ssize_t index = mFrameBuffers.indexOfKey(fbHandle);
299     if (index < 0) {
300         ELOGTRACE("invalid kernel handle");
301         return;
302     }
303 
304     BufferMapper *mapper = mFrameBuffers.valueAt(index);
305     uint32_t handle = mapper->getHandle();
306     mapper->putFbHandle();
307     delete mapper;
308     mFrameBuffers.removeItem(fbHandle);
309     mAllocDev->free(mAllocDev, (buffer_handle_t)handle);
310 }
311 
allocGrallocBuffer(uint32_t width,uint32_t height,uint32_t format,uint32_t usage)312 uint32_t BufferManager::allocGrallocBuffer(uint32_t width, uint32_t height, uint32_t format, uint32_t usage)
313 {
314     RETURN_NULL_IF_NOT_INIT();
315 
316     if (!mAllocDev) {
317         WLOGTRACE("Alloc device is not available");
318         return 0;
319     }
320 
321     if (!width || !height) {
322         ELOGTRACE("invalid input parameter");
323         return 0;
324     }
325 
326     ILOGTRACE("size of graphic buffer to create: %dx%d", width, height);
327     uint32_t handle = 0;
328     int stride;
329     status_t err  = mAllocDev->alloc(
330                 mAllocDev,
331                 width,
332                 height,
333                 format,
334                 usage,
335                 (buffer_handle_t *)&handle,
336                 &stride);
337     if (err != 0) {
338         ELOGTRACE("failed to allocate gralloc buffer, error = %d", err);
339         return 0;
340     }
341 
342     return handle;
343 }
344 
freeGrallocBuffer(uint32_t handle)345 void BufferManager::freeGrallocBuffer(uint32_t handle)
346 {
347     RETURN_VOID_IF_NOT_INIT();
348     if (!mAllocDev) {
349         WLOGTRACE("Alloc device is not available");
350         return;
351     }
352 
353     if (handle)
354         mAllocDev->free(mAllocDev, (buffer_handle_t)handle);
355 }
356 
357 } // namespace intel
358 } // namespace android
359