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 <HwcTrace.h>
18#include <hardware/hwcomposer.h>
19#include <BufferManager.h>
20#include <hal_public.h>
21#include <DrmConfig.h>
22
23namespace android {
24namespace intel {
25
26BufferManager::BufferManager()
27    : mGralloc(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        ETRACE("failed to create gralloc buffer cache");
55        return false;
56    }
57
58    // init gralloc module
59    if (gralloc_open_img(&mGralloc)) {
60        DEINIT_AND_RETURN_FALSE("failed to get gralloc module");
61    }
62
63    // create a dummy data buffer
64    mDataBuffer = createDataBuffer(0);
65    if (!mDataBuffer) {
66        DEINIT_AND_RETURN_FALSE("failed to create data buffer");
67    }
68
69    mInitialized = true;
70    return true;
71}
72
73void BufferManager::deinitialize()
74{
75    mInitialized = false;
76
77    if (mBufferPool) {
78        // unmap & delete all cached buffer mappers
79        for (size_t i = 0; i < mBufferPool->getCacheSize(); i++) {
80            BufferMapper *mapper = mBufferPool->getMapper(i);
81            mapper->unmap();
82            delete mapper;
83        }
84
85        delete mBufferPool;
86        mBufferPool = NULL;
87    }
88
89    for (size_t j = 0; j < mFrameBuffers.size(); j++) {
90        BufferMapper *mapper = mFrameBuffers.valueAt(j);
91        mapper->unmap();
92        delete mapper;
93    }
94    mFrameBuffers.clear();
95
96    if (mGralloc) {
97        gralloc_close_img(mGralloc);
98        mGralloc = NULL;
99    }
100
101    if (mDataBuffer) {
102        delete mDataBuffer;
103        mDataBuffer = NULL;
104    }
105}
106
107void BufferManager::dump(Dump& d)
108{
109    d.append("Buffer Manager status: pool size %d\n", mBufferPool->getCacheSize());
110    d.append("-------------------------------------------------------------\n");
111    for (uint32_t i = 0; i < mBufferPool->getCacheSize(); i++) {
112        BufferMapper *mapper = mBufferPool->getMapper(i);
113        d.append("Buffer %d: handle %#x, (%dx%d), format %d, refCount %d\n",
114                 i,
115                 mapper->getHandle(),
116                 mapper->getWidth(),
117                 mapper->getHeight(),
118                 mapper->getFormat(),
119                 mapper->getRef());
120    }
121    return;
122}
123
124DataBuffer* BufferManager::lockDataBuffer(buffer_handle_t handle)
125{
126    mDataBufferLock.lock();
127    mDataBuffer->resetBuffer(handle);
128    return mDataBuffer;
129}
130
131void BufferManager::unlockDataBuffer(DataBuffer *buffer)
132{
133    mDataBufferLock.unlock();
134}
135
136DataBuffer* BufferManager::get(buffer_handle_t handle)
137{
138    return createDataBuffer(handle);
139}
140
141void BufferManager::put(DataBuffer *buffer)
142{
143    delete buffer;
144}
145
146BufferMapper* BufferManager::map(DataBuffer& buffer)
147{
148    bool ret;
149    BufferMapper* mapper;
150
151    CTRACE();
152    Mutex::Autolock _l(mLock);
153    //try to get mapper from pool
154    mapper = mBufferPool->getMapper(buffer.getKey());
155    if (mapper) {
156        // increase mapper ref count
157        mapper->incRef();
158        return mapper;
159    }
160
161    // create a new buffer mapper and add it to pool
162    do {
163        VTRACE("new buffer, will add it");
164        mapper = createBufferMapper(buffer);
165        if (!mapper) {
166            ETRACE("failed to allocate mapper");
167            break;
168        }
169        ret = mapper->map();
170        if (!ret) {
171            ETRACE("failed to map");
172            delete mapper;
173            mapper = NULL;
174            break;
175        }
176        ret = mBufferPool->addMapper(buffer.getKey(), mapper);
177        if (!ret) {
178            ETRACE("failed to add mapper");
179            break;
180        }
181        // increase mapper ref count
182        mapper->incRef();
183        return mapper;
184    } while (0);
185
186    // error handling
187    if (mapper) {
188        mapper->unmap();
189        delete mapper;
190    }
191    return NULL;
192}
193
194void BufferManager::unmap(BufferMapper *mapper)
195{
196    Mutex::Autolock _l(mLock);
197    if (!mapper) {
198        ETRACE("invalid mapper");
199        return;
200    }
201
202    // unmap & remove this mapper from buffer when refCount = 0
203    int refCount = mapper->decRef();
204    if (refCount < 0) {
205        ETRACE("invalid ref count");
206    } else if (!refCount) {
207        // remove mapper from buffer pool
208        mBufferPool->removeMapper(mapper);
209        mapper->unmap();
210        delete mapper;
211    }
212}
213
214buffer_handle_t BufferManager::allocFrameBuffer(int width, int height, int *stride)
215{
216    RETURN_NULL_IF_NOT_INIT();
217
218    if (!mGralloc) {
219        WTRACE("Alloc device is not available");
220        return 0;
221    }
222
223    if (!width || !height || !stride) {
224        ETRACE("invalid input parameter");
225        return 0;
226    }
227
228    ITRACE("size of frame buffer to create: %dx%d", width, height);
229    buffer_handle_t handle = 0;
230    status_t err = gralloc_device_alloc_img(
231            mGralloc,
232            width,
233            height,
234            DrmConfig::getFrameBufferFormat(),
235            0, // GRALLOC_USAGE_HW_FB
236            &handle,
237            stride);
238
239    if (err != 0) {
240        ETRACE("failed to allocate frame buffer, error = %d", err);
241        return 0;
242    }
243
244    DataBuffer *buffer = NULL;
245    BufferMapper *mapper = NULL;
246
247    do {
248        buffer = lockDataBuffer(handle);
249        if (!buffer) {
250            ETRACE("failed to get data buffer, handle = %p", handle);
251            break;
252        }
253
254        mapper = createBufferMapper(*buffer);
255        if (!mapper) {
256            ETRACE("failed to create buffer mapper");
257            break;
258        }
259
260        buffer_handle_t fbHandle;
261         if (!(fbHandle = mapper->getFbHandle(0))) {
262             ETRACE("failed to get Fb handle");
263             break;
264         }
265
266        mFrameBuffers.add(fbHandle, mapper);
267        unlockDataBuffer(buffer);
268        return fbHandle;
269    } while (0);
270
271    // error handling, release all allocated resources
272    if (buffer) {
273        unlockDataBuffer(buffer);
274    }
275    if (mapper) {
276        delete mapper;
277    }
278    gralloc_device_free_img(mGralloc, handle);
279    return 0;
280}
281
282void BufferManager::freeFrameBuffer(buffer_handle_t fbHandle)
283{
284    RETURN_VOID_IF_NOT_INIT();
285
286    if (!mGralloc) {
287        WTRACE("Alloc device is not available");
288        return;
289    }
290
291    ssize_t index = mFrameBuffers.indexOfKey(fbHandle);
292    if (index < 0) {
293        ETRACE("invalid kernel handle");
294        return;
295    }
296
297    BufferMapper *mapper = mFrameBuffers.valueAt(index);
298    buffer_handle_t handle = mapper->getHandle();
299    mapper->putFbHandle();
300    delete mapper;
301    mFrameBuffers.removeItem(fbHandle);
302    gralloc_device_free_img(mGralloc, handle);
303}
304
305buffer_handle_t BufferManager::allocGrallocBuffer(uint32_t width, uint32_t height, uint32_t format, uint32_t usage)
306{
307    RETURN_NULL_IF_NOT_INIT();
308
309    if (!mGralloc) {
310        WTRACE("Alloc device is not available");
311        return 0;
312    }
313
314    if (!width || !height) {
315        ETRACE("invalid input parameter");
316        return 0;
317    }
318
319    ITRACE("size of graphic buffer to create: %dx%d", width, height);
320    buffer_handle_t handle = 0;
321    int stride;
322    status_t err = gralloc_device_alloc_img(
323                mGralloc,
324                width,
325                height,
326                format,
327                usage,
328                &handle,
329                &stride);
330    if (err != 0) {
331        ETRACE("failed to allocate gralloc buffer, error = %d", err);
332        return 0;
333    }
334
335    return handle;
336}
337
338void BufferManager::freeGrallocBuffer(buffer_handle_t handle)
339{
340    RETURN_VOID_IF_NOT_INIT();
341    if (!mGralloc) {
342        WTRACE("Alloc device is not available");
343        return;
344    }
345
346    if (handle)
347        gralloc_device_free_img(mGralloc, handle);
348}
349
350} // namespace intel
351} // namespace android
352