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