GraphicBuffer.cpp revision e9e9fe40fb702ab1390a32c61981bc927177258a
1/*
2 * Copyright (C) 2007 The Android Open Source Project
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#define LOG_TAG "GraphicBuffer"
18
19#include <cutils/atomic.h>
20
21#include <ui/GraphicBuffer.h>
22
23#include <cutils/atomic.h>
24
25#include <ui/GrallocMapper.h>
26#include <ui/GraphicBufferAllocator.h>
27#include <ui/GraphicBufferMapper.h>
28
29namespace android {
30
31// ===========================================================================
32// Buffer and implementation of ANativeWindowBuffer
33// ===========================================================================
34
35static uint64_t getUniqueId() {
36    static volatile int32_t nextId = 0;
37    uint64_t id = static_cast<uint64_t>(getpid()) << 32;
38    id |= static_cast<uint32_t>(android_atomic_inc(&nextId));
39    return id;
40}
41
42GraphicBuffer::GraphicBuffer()
43    : BASE(), mOwner(ownData), mBufferMapper(GraphicBufferMapper::get()),
44      mInitCheck(NO_ERROR), mId(getUniqueId()), mGenerationNumber(0)
45{
46    width  =
47    height =
48    stride =
49    format =
50    usage  = 0;
51    layerCount = 0;
52    handle = NULL;
53}
54
55GraphicBuffer::GraphicBuffer(uint32_t inWidth, uint32_t inHeight,
56        PixelFormat inFormat, uint32_t inUsage, std::string requestorName)
57    : BASE(), mOwner(ownData), mBufferMapper(GraphicBufferMapper::get()),
58      mInitCheck(NO_ERROR), mId(getUniqueId()), mGenerationNumber(0)
59{
60    width  =
61    height =
62    stride =
63    format =
64    usage  = 0;
65    layerCount = 0;
66    handle = NULL;
67    mInitCheck = initSize(inWidth, inHeight, inFormat, 1, inUsage, inUsage,
68            std::move(requestorName));
69}
70
71GraphicBuffer::GraphicBuffer(uint32_t inWidth, uint32_t inHeight,
72        PixelFormat inFormat, uint32_t inLayerCount, uint64_t producerUsage,
73        uint64_t consumerUsage, std::string requestorName)
74    : BASE(), mOwner(ownData), mBufferMapper(GraphicBufferMapper::get()),
75      mInitCheck(NO_ERROR), mId(getUniqueId()), mGenerationNumber(0)
76{
77    width  =
78    height =
79    stride =
80    format =
81    usage  = 0;
82    layerCount = 0;
83    handle = NULL;
84    mInitCheck = initSize(inWidth, inHeight, inFormat, inLayerCount,
85            producerUsage, consumerUsage, std::move(requestorName));
86}
87
88GraphicBuffer::GraphicBuffer(uint32_t inWidth, uint32_t inHeight,
89        PixelFormat inFormat, uint32_t inLayerCount, uint32_t inUsage,
90        uint32_t inStride, native_handle_t* inHandle, bool keepOwnership)
91    : BASE(), mOwner(keepOwnership ? ownHandle : ownNone),
92      mBufferMapper(GraphicBufferMapper::get()),
93      mInitCheck(NO_ERROR), mId(getUniqueId()), mGenerationNumber(0)
94{
95    width  = static_cast<int>(inWidth);
96    height = static_cast<int>(inHeight);
97    stride = static_cast<int>(inStride);
98    format = inFormat;
99    layerCount = inLayerCount;
100    usage  = static_cast<int>(inUsage);
101    handle = inHandle;
102}
103
104GraphicBuffer::GraphicBuffer(uint32_t inWidth, uint32_t inHeight,
105        PixelFormat inFormat, uint32_t inLayerCount, uint32_t inProducerUsage,
106        uint32_t inConsumerUsage, uint32_t inStride,
107        native_handle_t* inHandle, bool keepOwnership)
108    : BASE(), mOwner(keepOwnership ? ownHandle : ownNone),
109      mBufferMapper(GraphicBufferMapper::get()),
110      mInitCheck(NO_ERROR), mId(getUniqueId()), mGenerationNumber(0)
111{
112    width  = static_cast<int>(inWidth);
113    height = static_cast<int>(inHeight);
114    stride = static_cast<int>(inStride);
115    format = inFormat;
116    layerCount = inLayerCount;
117    usage  = static_cast<int>(inConsumerUsage | inProducerUsage);
118    handle = inHandle;
119}
120
121
122GraphicBuffer::GraphicBuffer(ANativeWindowBuffer* buffer, bool keepOwnership)
123    : BASE(), mOwner(keepOwnership ? ownHandle : ownNone),
124      mBufferMapper(GraphicBufferMapper::get()),
125      mInitCheck(NO_ERROR), mWrappedBuffer(buffer), mId(getUniqueId()),
126      mGenerationNumber(0)
127{
128    width  = buffer->width;
129    height = buffer->height;
130    stride = buffer->stride;
131    format = buffer->format;
132    layerCount = buffer->layerCount;
133    usage  = buffer->usage;
134    handle = buffer->handle;
135}
136
137GraphicBuffer::~GraphicBuffer()
138{
139    if (handle) {
140        free_handle();
141    }
142}
143
144void GraphicBuffer::free_handle()
145{
146    if (mOwner == ownHandle) {
147        mBufferMapper.unregisterBuffer(handle);
148        if (!mBufferMapper.getGrallocMapper().valid()) {
149            native_handle_close(handle);
150            native_handle_delete(const_cast<native_handle*>(handle));
151        }
152    } else if (mOwner == ownData) {
153        GraphicBufferAllocator& allocator(GraphicBufferAllocator::get());
154        allocator.free(handle);
155    }
156    handle = NULL;
157    mWrappedBuffer = 0;
158}
159
160status_t GraphicBuffer::initCheck() const {
161    return static_cast<status_t>(mInitCheck);
162}
163
164void GraphicBuffer::dumpAllocationsToSystemLog()
165{
166    GraphicBufferAllocator::dumpToSystemLog();
167}
168
169ANativeWindowBuffer* GraphicBuffer::getNativeBuffer() const
170{
171    LOG_ALWAYS_FATAL_IF(this == NULL, "getNativeBuffer() called on NULL GraphicBuffer");
172    return static_cast<ANativeWindowBuffer*>(
173            const_cast<GraphicBuffer*>(this));
174}
175
176status_t GraphicBuffer::reallocate(uint32_t inWidth, uint32_t inHeight,
177        PixelFormat inFormat, uint32_t inLayerCount, uint32_t inUsage)
178{
179    if (mOwner != ownData)
180        return INVALID_OPERATION;
181
182    if (handle &&
183            static_cast<int>(inWidth) == width &&
184            static_cast<int>(inHeight) == height &&
185            inFormat == format &&
186            inLayerCount == layerCount &&
187            static_cast<int>(inUsage) == usage)
188        return NO_ERROR;
189
190    if (handle) {
191        GraphicBufferAllocator& allocator(GraphicBufferAllocator::get());
192        allocator.free(handle);
193        handle = 0;
194    }
195    return initSize(inWidth, inHeight, inFormat, inLayerCount, inUsage, inUsage,
196            "[Reallocation]");
197}
198
199bool GraphicBuffer::needsReallocation(uint32_t inWidth, uint32_t inHeight,
200        PixelFormat inFormat, uint32_t inLayerCount, uint32_t inUsage)
201{
202    if (static_cast<int>(inWidth) != width) return true;
203    if (static_cast<int>(inHeight) != height) return true;
204    if (inFormat != format) return true;
205    if (inLayerCount != layerCount) return true;
206    if ((static_cast<uint32_t>(usage) & inUsage) != inUsage) return true;
207    return false;
208}
209
210status_t GraphicBuffer::initSize(uint32_t inWidth, uint32_t inHeight,
211        PixelFormat inFormat, uint32_t inLayerCount, uint64_t inProducerUsage,
212        uint64_t inConsumerUsage, std::string requestorName)
213{
214    GraphicBufferAllocator& allocator = GraphicBufferAllocator::get();
215    uint32_t outStride = 0;
216    status_t err = allocator.allocate(inWidth, inHeight, inFormat, inLayerCount,
217            inProducerUsage, inConsumerUsage, &handle, &outStride, mId,
218            std::move(requestorName));
219    if (err == NO_ERROR) {
220        width = static_cast<int>(inWidth);
221        height = static_cast<int>(inHeight);
222        format = inFormat;
223        layerCount = inLayerCount;
224        usage = static_cast<int>(inProducerUsage | inConsumerUsage);
225        stride = static_cast<int>(outStride);
226    }
227    return err;
228}
229
230status_t GraphicBuffer::lock(uint32_t inUsage, void** vaddr)
231{
232    const Rect lockBounds(width, height);
233    status_t res = lock(inUsage, lockBounds, vaddr);
234    return res;
235}
236
237status_t GraphicBuffer::lock(uint32_t inUsage, const Rect& rect, void** vaddr)
238{
239    if (rect.left < 0 || rect.right  > width ||
240        rect.top  < 0 || rect.bottom > height) {
241        ALOGE("locking pixels (%d,%d,%d,%d) outside of buffer (w=%d, h=%d)",
242                rect.left, rect.top, rect.right, rect.bottom,
243                width, height);
244        return BAD_VALUE;
245    }
246    status_t res = getBufferMapper().lock(handle, inUsage, rect, vaddr);
247    return res;
248}
249
250status_t GraphicBuffer::lockYCbCr(uint32_t inUsage, android_ycbcr* ycbcr)
251{
252    const Rect lockBounds(width, height);
253    status_t res = lockYCbCr(inUsage, lockBounds, ycbcr);
254    return res;
255}
256
257status_t GraphicBuffer::lockYCbCr(uint32_t inUsage, const Rect& rect,
258        android_ycbcr* ycbcr)
259{
260    if (rect.left < 0 || rect.right  > width ||
261        rect.top  < 0 || rect.bottom > height) {
262        ALOGE("locking pixels (%d,%d,%d,%d) outside of buffer (w=%d, h=%d)",
263                rect.left, rect.top, rect.right, rect.bottom,
264                width, height);
265        return BAD_VALUE;
266    }
267    status_t res = getBufferMapper().lockYCbCr(handle, inUsage, rect, ycbcr);
268    return res;
269}
270
271status_t GraphicBuffer::unlock()
272{
273    status_t res = getBufferMapper().unlock(handle);
274    return res;
275}
276
277status_t GraphicBuffer::lockAsync(uint32_t inUsage, void** vaddr, int fenceFd)
278{
279    const Rect lockBounds(width, height);
280    status_t res = lockAsync(inUsage, lockBounds, vaddr, fenceFd);
281    return res;
282}
283
284status_t GraphicBuffer::lockAsync(uint32_t inUsage, const Rect& rect,
285        void** vaddr, int fenceFd)
286{
287    return lockAsync(inUsage, inUsage, rect, vaddr, fenceFd);
288}
289
290status_t GraphicBuffer::lockAsync(uint64_t inProducerUsage,
291        uint64_t inConsumerUsage, const Rect& rect, void** vaddr, int fenceFd)
292{
293    if (rect.left < 0 || rect.right  > width ||
294        rect.top  < 0 || rect.bottom > height) {
295        ALOGE("locking pixels (%d,%d,%d,%d) outside of buffer (w=%d, h=%d)",
296                rect.left, rect.top, rect.right, rect.bottom,
297                width, height);
298        return BAD_VALUE;
299    }
300    status_t res = getBufferMapper().lockAsync(handle, inProducerUsage,
301            inConsumerUsage, rect, vaddr, fenceFd);
302    return res;
303}
304
305status_t GraphicBuffer::lockAsyncYCbCr(uint32_t inUsage, android_ycbcr* ycbcr,
306        int fenceFd)
307{
308    const Rect lockBounds(width, height);
309    status_t res = lockAsyncYCbCr(inUsage, lockBounds, ycbcr, fenceFd);
310    return res;
311}
312
313status_t GraphicBuffer::lockAsyncYCbCr(uint32_t inUsage, const Rect& rect,
314        android_ycbcr* ycbcr, int fenceFd)
315{
316    if (rect.left < 0 || rect.right  > width ||
317        rect.top  < 0 || rect.bottom > height) {
318        ALOGE("locking pixels (%d,%d,%d,%d) outside of buffer (w=%d, h=%d)",
319                rect.left, rect.top, rect.right, rect.bottom,
320                width, height);
321        return BAD_VALUE;
322    }
323    status_t res = getBufferMapper().lockAsyncYCbCr(handle, inUsage, rect,
324            ycbcr, fenceFd);
325    return res;
326}
327
328status_t GraphicBuffer::unlockAsync(int *fenceFd)
329{
330    status_t res = getBufferMapper().unlockAsync(handle, fenceFd);
331    return res;
332}
333
334size_t GraphicBuffer::getFlattenedSize() const {
335    return static_cast<size_t>(12 + (handle ? handle->numInts : 0)) * sizeof(int);
336}
337
338size_t GraphicBuffer::getFdCount() const {
339    return static_cast<size_t>(handle ? handle->numFds : 0);
340}
341
342status_t GraphicBuffer::flatten(void*& buffer, size_t& size, int*& fds, size_t& count) const {
343    size_t sizeNeeded = GraphicBuffer::getFlattenedSize();
344    if (size < sizeNeeded) return NO_MEMORY;
345
346    size_t fdCountNeeded = GraphicBuffer::getFdCount();
347    if (count < fdCountNeeded) return NO_MEMORY;
348
349    int32_t* buf = static_cast<int32_t*>(buffer);
350    buf[0] = 'GBFR';
351    buf[1] = width;
352    buf[2] = height;
353    buf[3] = stride;
354    buf[4] = format;
355    buf[5] = static_cast<int32_t>(layerCount);
356    buf[6] = usage;
357    buf[7] = static_cast<int32_t>(mId >> 32);
358    buf[8] = static_cast<int32_t>(mId & 0xFFFFFFFFull);
359    buf[9] = static_cast<int32_t>(mGenerationNumber);
360    buf[10] = 0;
361    buf[11] = 0;
362
363    if (handle) {
364        buf[10] = handle->numFds;
365        buf[11] = handle->numInts;
366        memcpy(fds, handle->data,
367                static_cast<size_t>(handle->numFds) * sizeof(int));
368        memcpy(&buf[12], handle->data + handle->numFds,
369                static_cast<size_t>(handle->numInts) * sizeof(int));
370    }
371
372    buffer = static_cast<void*>(static_cast<uint8_t*>(buffer) + sizeNeeded);
373    size -= sizeNeeded;
374    if (handle) {
375        fds += handle->numFds;
376        count -= static_cast<size_t>(handle->numFds);
377    }
378
379    return NO_ERROR;
380}
381
382status_t GraphicBuffer::unflatten(
383        void const*& buffer, size_t& size, int const*& fds, size_t& count) {
384    if (size < 12 * sizeof(int)) return NO_MEMORY;
385
386    int const* buf = static_cast<int const*>(buffer);
387    if (buf[0] != 'GBFR') return BAD_TYPE;
388
389    const size_t numFds  = static_cast<size_t>(buf[10]);
390    const size_t numInts = static_cast<size_t>(buf[11]);
391
392    // Limit the maxNumber to be relatively small. The number of fds or ints
393    // should not come close to this number, and the number itself was simply
394    // chosen to be high enough to not cause issues and low enough to prevent
395    // overflow problems.
396    const size_t maxNumber = 4096;
397    if (numFds >= maxNumber || numInts >= (maxNumber - 12)) {
398        width = height = stride = format = layerCount = usage = 0;
399        handle = NULL;
400        ALOGE("unflatten: numFds or numInts is too large: %zd, %zd",
401                numFds, numInts);
402        return BAD_VALUE;
403    }
404
405    const size_t sizeNeeded = (12 + numInts) * sizeof(int);
406    if (size < sizeNeeded) return NO_MEMORY;
407
408    size_t fdCountNeeded = numFds;
409    if (count < fdCountNeeded) return NO_MEMORY;
410
411    if (handle) {
412        // free previous handle if any
413        free_handle();
414    }
415
416    if (numFds || numInts) {
417        width  = buf[1];
418        height = buf[2];
419        stride = buf[3];
420        format = buf[4];
421        layerCount = static_cast<uintptr_t>(buf[5]);
422        usage  = buf[6];
423        native_handle* h = native_handle_create(
424                static_cast<int>(numFds), static_cast<int>(numInts));
425        if (!h) {
426            width = height = stride = format = layerCount = usage = 0;
427            handle = NULL;
428            ALOGE("unflatten: native_handle_create failed");
429            return NO_MEMORY;
430        }
431        memcpy(h->data, fds, numFds * sizeof(int));
432        memcpy(h->data + numFds, &buf[12], numInts * sizeof(int));
433        handle = h;
434    } else {
435        width = height = stride = format = layerCount = usage = 0;
436        handle = NULL;
437    }
438
439    mId = static_cast<uint64_t>(buf[7]) << 32;
440    mId |= static_cast<uint32_t>(buf[8]);
441
442    mGenerationNumber = static_cast<uint32_t>(buf[9]);
443
444    mOwner = ownHandle;
445
446    if (handle != 0) {
447        status_t err = mBufferMapper.registerBuffer(this);
448        if (err != NO_ERROR) {
449            width = height = stride = format = layerCount = usage = 0;
450            handle = NULL;
451            ALOGE("unflatten: registerBuffer failed: %s (%d)",
452                    strerror(-err), err);
453            return err;
454        }
455    }
456
457    buffer = static_cast<void const*>(static_cast<uint8_t const*>(buffer) + sizeNeeded);
458    size -= sizeNeeded;
459    fds += numFds;
460    count -= numFds;
461
462    return NO_ERROR;
463}
464
465// ---------------------------------------------------------------------------
466
467}; // namespace android
468