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
22namespace android {
23namespace intel {
24
25BufferManager::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
37BufferManager::~BufferManager()
38{
39    WARN_IF_NOT_DEINIT();
40}
41
42bool BufferManager::initCheck() const
43{
44    return mInitialized;
45}
46
47bool 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*)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(mGrallocModule, 0);
72    if (!mDataBuffer) {
73        DEINIT_AND_RETURN_FALSE("failed to create data buffer");
74    }
75
76    mInitialized = true;
77    return true;
78}
79
80void 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
114void 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
131DataBuffer* BufferManager::lockDataBuffer(uint32_t handle)
132{
133    mDataBufferLock.lock();
134    mDataBuffer->resetBuffer(handle);
135    return mDataBuffer;
136}
137
138void BufferManager::unlockDataBuffer(DataBuffer * /* buffer */)
139{
140    mDataBufferLock.unlock();
141}
142
143DataBuffer* BufferManager::get(uint32_t handle)
144{
145    return createDataBuffer(mGrallocModule, handle);
146}
147
148void BufferManager::put(DataBuffer *buffer)
149{
150    delete buffer;
151}
152
153BufferMapper* 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(mGrallocModule, 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
201void 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
221uint32_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(mGrallocModule, *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
289void 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
312uint32_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
345void 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