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 #include <pixelflinger/pixelflinger.h>
     32 
     33 namespace android {
     34 
     35 // ===========================================================================
     36 // Buffer and implementation of android_native_buffer_t
     37 // ===========================================================================
     38 
     39 GraphicBuffer::GraphicBuffer()
     40     : BASE(), mOwner(ownData), mBufferMapper(GraphicBufferMapper::get()),
     41       mInitCheck(NO_ERROR),  mVStride(0), mIndex(-1)
     42 {
     43     width  =
     44     height =
     45     stride =
     46     format =
     47     usage  = 0;
     48     handle = NULL;
     49 }
     50 
     51 GraphicBuffer::GraphicBuffer(uint32_t w, uint32_t h,
     52         PixelFormat reqFormat, uint32_t reqUsage)
     53     : BASE(), mOwner(ownData), mBufferMapper(GraphicBufferMapper::get()),
     54       mInitCheck(NO_ERROR),  mVStride(0), mIndex(-1)
     55 {
     56     width  =
     57     height =
     58     stride =
     59     format =
     60     usage  = 0;
     61     handle = NULL;
     62     mInitCheck = initSize(w, h, reqFormat, reqUsage);
     63 }
     64 
     65 GraphicBuffer::GraphicBuffer(uint32_t w, uint32_t h,
     66         PixelFormat inFormat, uint32_t inUsage,
     67         uint32_t inStride, native_handle_t* inHandle, bool keepOwnership)
     68     : BASE(), mOwner(keepOwnership ? ownHandle : ownNone),
     69       mBufferMapper(GraphicBufferMapper::get()),
     70       mInitCheck(NO_ERROR),  mVStride(0), mIndex(-1)
     71 {
     72     width  = w;
     73     height = h;
     74     stride = inStride;
     75     format = inFormat;
     76     usage  = inUsage;
     77     handle = inHandle;
     78 }
     79 
     80 GraphicBuffer::~GraphicBuffer()
     81 {
     82     if (handle) {
     83         free_handle();
     84     }
     85 }
     86 
     87 void GraphicBuffer::free_handle()
     88 {
     89     if (mOwner == ownHandle) {
     90         native_handle_close(handle);
     91         native_handle_delete(const_cast<native_handle*>(handle));
     92     } else if (mOwner == ownData) {
     93         GraphicBufferAllocator& allocator(GraphicBufferAllocator::get());
     94         allocator.free(handle);
     95     }
     96 }
     97 
     98 status_t GraphicBuffer::initCheck() const {
     99     return mInitCheck;
    100 }
    101 
    102 android_native_buffer_t* GraphicBuffer::getNativeBuffer() const
    103 {
    104     return static_cast<android_native_buffer_t*>(
    105             const_cast<GraphicBuffer*>(this));
    106 }
    107 
    108 status_t GraphicBuffer::reallocate(uint32_t w, uint32_t h, PixelFormat f,
    109         uint32_t reqUsage)
    110 {
    111     if (mOwner != ownData)
    112         return INVALID_OPERATION;
    113 
    114     if (handle) {
    115         GraphicBufferAllocator& allocator(GraphicBufferAllocator::get());
    116         allocator.free(handle);
    117         handle = 0;
    118     }
    119     return initSize(w, h, f, reqUsage);
    120 }
    121 
    122 status_t GraphicBuffer::initSize(uint32_t w, uint32_t h, PixelFormat format,
    123         uint32_t reqUsage)
    124 {
    125     if (format == PIXEL_FORMAT_RGBX_8888)
    126         format = PIXEL_FORMAT_RGBA_8888;
    127 
    128     GraphicBufferAllocator& allocator = GraphicBufferAllocator::get();
    129     status_t err = allocator.alloc(w, h, format, reqUsage, &handle, &stride);
    130     if (err == NO_ERROR) {
    131         this->width  = w;
    132         this->height = h;
    133         this->format = format;
    134         this->usage  = reqUsage;
    135         mVStride = 0;
    136     }
    137     return err;
    138 }
    139 
    140 status_t GraphicBuffer::lock(uint32_t usage, void** vaddr)
    141 {
    142     const Rect lockBounds(width, height);
    143     status_t res = lock(usage, lockBounds, vaddr);
    144     return res;
    145 }
    146 
    147 status_t GraphicBuffer::lock(uint32_t usage, const Rect& rect, void** vaddr)
    148 {
    149     if (rect.left < 0 || rect.right  > this->width ||
    150         rect.top  < 0 || rect.bottom > this->height) {
    151         LOGE("locking pixels (%d,%d,%d,%d) outside of buffer (w=%d, h=%d)",
    152                 rect.left, rect.top, rect.right, rect.bottom,
    153                 this->width, this->height);
    154         return BAD_VALUE;
    155     }
    156     status_t res = getBufferMapper().lock(handle, usage, rect, vaddr);
    157     return res;
    158 }
    159 
    160 status_t GraphicBuffer::unlock()
    161 {
    162     status_t res = getBufferMapper().unlock(handle);
    163     return res;
    164 }
    165 
    166 status_t GraphicBuffer::lock(GGLSurface* sur, uint32_t usage)
    167 {
    168     void* vaddr;
    169     status_t res = GraphicBuffer::lock(usage, &vaddr);
    170     if (res == NO_ERROR && sur) {
    171         sur->version = sizeof(GGLSurface);
    172         sur->width = width;
    173         sur->height = height;
    174         sur->stride = stride;
    175         sur->format = format;
    176         sur->vstride = mVStride;
    177         sur->data = static_cast<GGLubyte*>(vaddr);
    178     }
    179     return res;
    180 }
    181 
    182 size_t GraphicBuffer::getFlattenedSize() const {
    183     return (8 + (handle ? handle->numInts : 0))*sizeof(int);
    184 }
    185 
    186 size_t GraphicBuffer::getFdCount() const {
    187     return handle ? handle->numFds : 0;
    188 }
    189 
    190 status_t GraphicBuffer::flatten(void* buffer, size_t size,
    191         int fds[], size_t count) const
    192 {
    193     size_t sizeNeeded = GraphicBuffer::getFlattenedSize();
    194     if (size < sizeNeeded) return NO_MEMORY;
    195 
    196     size_t fdCountNeeded = GraphicBuffer::getFdCount();
    197     if (count < fdCountNeeded) return NO_MEMORY;
    198 
    199     int* buf = static_cast<int*>(buffer);
    200     buf[0] = 'GBFR';
    201     buf[1] = width;
    202     buf[2] = height;
    203     buf[3] = stride;
    204     buf[4] = format;
    205     buf[5] = usage;
    206     buf[6] = 0;
    207     buf[7] = 0;
    208 
    209     if (handle) {
    210         buf[6] = handle->numFds;
    211         buf[7] = handle->numInts;
    212         native_handle_t const* const h = handle;
    213         memcpy(fds,     h->data,             h->numFds*sizeof(int));
    214         memcpy(&buf[8], h->data + h->numFds, h->numInts*sizeof(int));
    215     }
    216 
    217     return NO_ERROR;
    218 }
    219 
    220 status_t GraphicBuffer::unflatten(void const* buffer, size_t size,
    221         int fds[], size_t count)
    222 {
    223     if (size < 8*sizeof(int)) return NO_MEMORY;
    224 
    225     int const* buf = static_cast<int const*>(buffer);
    226     if (buf[0] != 'GBFR') return BAD_TYPE;
    227 
    228     const size_t numFds  = buf[6];
    229     const size_t numInts = buf[7];
    230 
    231     const size_t sizeNeeded = (8 + numInts) * sizeof(int);
    232     if (size < sizeNeeded) return NO_MEMORY;
    233 
    234     size_t fdCountNeeded = 0;
    235     if (count < fdCountNeeded) return NO_MEMORY;
    236 
    237     if (handle) {
    238         // free previous handle if any
    239         free_handle();
    240     }
    241 
    242     if (numFds || numInts) {
    243         width  = buf[1];
    244         height = buf[2];
    245         stride = buf[3];
    246         format = buf[4];
    247         usage  = buf[5];
    248         native_handle* h = native_handle_create(numFds, numInts);
    249         memcpy(h->data,          fds,     numFds*sizeof(int));
    250         memcpy(h->data + numFds, &buf[8], numInts*sizeof(int));
    251         handle = h;
    252     } else {
    253         width = height = stride = format = usage = 0;
    254         handle = NULL;
    255     }
    256 
    257     mOwner = ownHandle;
    258     return NO_ERROR;
    259 }
    260 
    261 
    262 void GraphicBuffer::setIndex(int index) {
    263     mIndex = index;
    264 }
    265 
    266 int GraphicBuffer::getIndex() const {
    267     return mIndex;
    268 }
    269 
    270 void GraphicBuffer::setVerticalStride(uint32_t vstride) {
    271     mVStride = vstride;
    272 }
    273 
    274 uint32_t GraphicBuffer::getVerticalStride() const {
    275     return mVStride;
    276 }
    277 
    278 // ---------------------------------------------------------------------------
    279 
    280 }; // namespace android
    281