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