Home | History | Annotate | Download | only in surfaceflinger
      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 #include <stdlib.h>
     18 #include <stdint.h>
     19 #include <sys/types.h>
     20 
     21 #include <cutils/properties.h>
     22 #include <cutils/native_handle.h>
     23 
     24 #include <utils/Errors.h>
     25 #include <utils/Log.h>
     26 #include <utils/StopWatch.h>
     27 
     28 #include <ui/GraphicBuffer.h>
     29 #include <ui/PixelFormat.h>
     30 
     31 #include <surfaceflinger/Surface.h>
     32 
     33 #include "clz.h"
     34 #include "Layer.h"
     35 #include "SurfaceFlinger.h"
     36 #include "DisplayHardware/DisplayHardware.h"
     37 
     38 
     39 #define DEBUG_RESIZE    0
     40 
     41 
     42 namespace android {
     43 
     44 template <typename T> inline T min(T a, T b) {
     45     return a<b ? a : b;
     46 }
     47 
     48 // ---------------------------------------------------------------------------
     49 
     50 const uint32_t Layer::typeInfo = LayerBaseClient::typeInfo | 4;
     51 const char* const Layer::typeID = "Layer";
     52 
     53 // ---------------------------------------------------------------------------
     54 
     55 Layer::Layer(SurfaceFlinger* flinger, DisplayID display,
     56         const sp<Client>& c, int32_t i)
     57     :   LayerBaseClient(flinger, display, c, i),
     58         mSecure(false),
     59         mNoEGLImageForSwBuffers(false),
     60         mNeedsBlending(true),
     61         mNeedsDithering(false)
     62 {
     63     // no OpenGL operation is possible here, since we might not be
     64     // in the OpenGL thread.
     65     mFrontBufferIndex = lcblk->getFrontBuffer();
     66 }
     67 
     68 Layer::~Layer()
     69 {
     70     destroy();
     71     // the actual buffers will be destroyed here
     72 }
     73 
     74 void Layer::destroy()
     75 {
     76     for (size_t i=0 ; i<NUM_BUFFERS ; i++) {
     77         if (mTextures[i].name != -1U) {
     78             glDeleteTextures(1, &mTextures[i].name);
     79             mTextures[i].name = -1U;
     80         }
     81         if (mTextures[i].image != EGL_NO_IMAGE_KHR) {
     82             EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay());
     83             eglDestroyImageKHR(dpy, mTextures[i].image);
     84             mTextures[i].image = EGL_NO_IMAGE_KHR;
     85         }
     86         Mutex::Autolock _l(mLock);
     87         mBuffers[i].clear();
     88         mWidth = mHeight = 0;
     89     }
     90     mSurface.clear();
     91 }
     92 
     93 sp<LayerBaseClient::Surface> Layer::createSurface() const
     94 {
     95     return mSurface;
     96 }
     97 
     98 status_t Layer::ditch()
     99 {
    100     // the layer is not on screen anymore. free as much resources as possible
    101     mFreezeLock.clear();
    102     destroy();
    103     return NO_ERROR;
    104 }
    105 
    106 status_t Layer::setBuffers( uint32_t w, uint32_t h,
    107                             PixelFormat format, uint32_t flags)
    108 {
    109     // this surfaces pixel format
    110     PixelFormatInfo info;
    111     status_t err = getPixelFormatInfo(format, &info);
    112     if (err) return err;
    113 
    114     // the display's pixel format
    115     const DisplayHardware& hw(graphicPlane(0).displayHardware());
    116     uint32_t const maxSurfaceDims = min(
    117             hw.getMaxTextureSize(), hw.getMaxViewportDims());
    118 
    119     // never allow a surface larger than what our underlying GL implementation
    120     // can handle.
    121     if ((uint32_t(w)>maxSurfaceDims) || (uint32_t(h)>maxSurfaceDims)) {
    122         return BAD_VALUE;
    123     }
    124 
    125     PixelFormatInfo displayInfo;
    126     getPixelFormatInfo(hw.getFormat(), &displayInfo);
    127     const uint32_t hwFlags = hw.getFlags();
    128 
    129     mFormat = format;
    130     mWidth  = w;
    131     mHeight = h;
    132     mSecure = (flags & ISurfaceComposer::eSecure) ? true : false;
    133     mNeedsBlending = (info.h_alpha - info.l_alpha) > 0;
    134     mNoEGLImageForSwBuffers = !(hwFlags & DisplayHardware::CACHED_BUFFERS);
    135 
    136     // we use the red index
    137     int displayRedSize = displayInfo.getSize(PixelFormatInfo::INDEX_RED);
    138     int layerRedsize = info.getSize(PixelFormatInfo::INDEX_RED);
    139     mNeedsDithering = layerRedsize > displayRedSize;
    140 
    141     for (size_t i=0 ; i<NUM_BUFFERS ; i++) {
    142         mBuffers[i] = new GraphicBuffer();
    143     }
    144     mSurface = new SurfaceLayer(mFlinger, clientIndex(), this);
    145     return NO_ERROR;
    146 }
    147 
    148 void Layer::reloadTexture(const Region& dirty)
    149 {
    150     Mutex::Autolock _l(mLock);
    151     sp<GraphicBuffer> buffer(getFrontBufferLocked());
    152     if (buffer == NULL) {
    153         // this situation can happen if we ran out of memory for instance.
    154         // not much we can do. continue to use whatever texture was bound
    155         // to this context.
    156         return;
    157     }
    158 
    159     const int index = mFrontBufferIndex;
    160 
    161     // create the new texture name if needed
    162     if (UNLIKELY(mTextures[index].name == -1U)) {
    163         mTextures[index].name = createTexture();
    164         mTextures[index].width = 0;
    165         mTextures[index].height = 0;
    166     }
    167 
    168 #ifdef EGL_ANDROID_image_native_buffer
    169     if (mFlags & DisplayHardware::DIRECT_TEXTURE) {
    170         if (buffer->usage & GraphicBuffer::USAGE_HW_TEXTURE) {
    171             if (mTextures[index].dirty) {
    172                 if (initializeEglImage(buffer, &mTextures[index]) != NO_ERROR) {
    173                     // not sure what we can do here...
    174                     mFlags &= ~DisplayHardware::DIRECT_TEXTURE;
    175                     goto slowpath;
    176                 }
    177             }
    178         } else {
    179             if (mHybridBuffer==0 || (mHybridBuffer->width != buffer->width ||
    180                     mHybridBuffer->height != buffer->height)) {
    181                 mHybridBuffer.clear();
    182                 mHybridBuffer = new GraphicBuffer(
    183                         buffer->width, buffer->height, buffer->format,
    184                         GraphicBuffer::USAGE_SW_WRITE_OFTEN |
    185                         GraphicBuffer::USAGE_HW_TEXTURE);
    186                 if (initializeEglImage(
    187                         mHybridBuffer, &mTextures[0]) != NO_ERROR) {
    188                     // not sure what we can do here...
    189                     mFlags &= ~DisplayHardware::DIRECT_TEXTURE;
    190                     mHybridBuffer.clear();
    191                     goto slowpath;
    192                 }
    193             }
    194 
    195             GGLSurface t;
    196             status_t res = buffer->lock(&t, GRALLOC_USAGE_SW_READ_OFTEN);
    197             LOGE_IF(res, "error %d (%s) locking buffer %p",
    198                     res, strerror(res), buffer.get());
    199             if (res == NO_ERROR) {
    200                 Texture* const texture(&mTextures[0]);
    201 
    202                 glBindTexture(GL_TEXTURE_2D, texture->name);
    203 
    204                 sp<GraphicBuffer> buf(mHybridBuffer);
    205                 void* vaddr;
    206                 res = buf->lock(GraphicBuffer::USAGE_SW_WRITE_OFTEN, &vaddr);
    207                 if (res == NO_ERROR) {
    208                     int bpp = 0;
    209                     switch (t.format) {
    210                     case HAL_PIXEL_FORMAT_RGB_565:
    211                     case HAL_PIXEL_FORMAT_RGBA_4444:
    212                         bpp = 2;
    213                         break;
    214                     case HAL_PIXEL_FORMAT_RGBA_8888:
    215                     case HAL_PIXEL_FORMAT_RGBX_8888:
    216                         bpp = 4;
    217                         break;
    218                     default:
    219                         if (isSupportedYuvFormat(t.format)) {
    220                             // just show the Y plane of YUV buffers
    221                             bpp = 1;
    222                             break;
    223                         }
    224                         // oops, we don't handle this format!
    225                         LOGE("layer %p, texture=%d, using format %d, which is not "
    226                                 "supported by the GL", this, texture->name, t.format);
    227                     }
    228                     if (bpp) {
    229                         const Rect bounds(dirty.getBounds());
    230                         size_t src_stride = t.stride;
    231                         size_t dst_stride = buf->stride;
    232                         if (src_stride == dst_stride &&
    233                             bounds.width() == t.width &&
    234                             bounds.height() == t.height)
    235                         {
    236                             memcpy(vaddr, t.data, t.height * t.stride * bpp);
    237                         } else {
    238                             GLubyte const * src = t.data +
    239                                 (bounds.left + bounds.top * src_stride) * bpp;
    240                             GLubyte * dst = (GLubyte *)vaddr +
    241                                 (bounds.left + bounds.top * dst_stride) * bpp;
    242                             const size_t length = bounds.width() * bpp;
    243                             size_t h = bounds.height();
    244                             src_stride *= bpp;
    245                             dst_stride *= bpp;
    246                             while (h--) {
    247                                 memcpy(dst, src, length);
    248                                 dst += dst_stride;
    249                                 src += src_stride;
    250                             }
    251                         }
    252                     }
    253                     buf->unlock();
    254                 }
    255                 buffer->unlock();
    256             }
    257         }
    258     } else
    259 #endif
    260     {
    261 slowpath:
    262         for (size_t i=0 ; i<NUM_BUFFERS ; i++) {
    263             mTextures[i].image = EGL_NO_IMAGE_KHR;
    264         }
    265         GGLSurface t;
    266         status_t res = buffer->lock(&t, GRALLOC_USAGE_SW_READ_OFTEN);
    267         LOGE_IF(res, "error %d (%s) locking buffer %p",
    268                 res, strerror(res), buffer.get());
    269         if (res == NO_ERROR) {
    270             loadTexture(&mTextures[0], dirty, t);
    271             buffer->unlock();
    272         }
    273     }
    274 }
    275 
    276 void Layer::onDraw(const Region& clip) const
    277 {
    278     int index = mFrontBufferIndex;
    279     if (mTextures[index].image == EGL_NO_IMAGE_KHR)
    280         index = 0;
    281     GLuint textureName = mTextures[index].name;
    282     if (UNLIKELY(textureName == -1LU)) {
    283         // the texture has not been created yet, this Layer has
    284         // in fact never been drawn into. This happens frequently with
    285         // SurfaceView because the WindowManager can't know when the client
    286         // has drawn the first time.
    287 
    288         // If there is nothing under us, we paint the screen in black, otherwise
    289         // we just skip this update.
    290 
    291         // figure out if there is something below us
    292         Region under;
    293         const SurfaceFlinger::LayerVector& drawingLayers(mFlinger->mDrawingState.layersSortedByZ);
    294         const size_t count = drawingLayers.size();
    295         for (size_t i=0 ; i<count ; ++i) {
    296             const sp<LayerBase>& layer(drawingLayers[i]);
    297             if (layer.get() == static_cast<LayerBase const*>(this))
    298                 break;
    299             under.orSelf(layer->visibleRegionScreen);
    300         }
    301         // if not everything below us is covered, we plug the holes!
    302         Region holes(clip.subtract(under));
    303         if (!holes.isEmpty()) {
    304             clearWithOpenGL(holes);
    305         }
    306         return;
    307     }
    308     drawWithOpenGL(clip, mTextures[index]);
    309 }
    310 
    311 sp<GraphicBuffer> Layer::requestBuffer(int index, int usage)
    312 {
    313     sp<GraphicBuffer> buffer;
    314 
    315     // this ensures our client doesn't go away while we're accessing
    316     // the shared area.
    317     sp<Client> ourClient(client.promote());
    318     if (ourClient == 0) {
    319         // oops, the client is already gone
    320         return buffer;
    321     }
    322 
    323     /*
    324      * This is called from the client's Surface::dequeue(). This can happen
    325      * at any time, especially while we're in the middle of using the
    326      * buffer 'index' as our front buffer.
    327      *
    328      * Make sure the buffer we're resizing is not the front buffer and has been
    329      * dequeued. Once this condition is asserted, we are guaranteed that this
    330      * buffer cannot become the front buffer under our feet, since we're called
    331      * from Surface::dequeue()
    332      */
    333     status_t err = lcblk->assertReallocate(index);
    334     LOGE_IF(err, "assertReallocate(%d) failed (%s)", index, strerror(-err));
    335     if (err != NO_ERROR) {
    336         // the surface may have died
    337         return buffer;
    338     }
    339 
    340     uint32_t w, h;
    341     { // scope for the lock
    342         Mutex::Autolock _l(mLock);
    343         w = mWidth;
    344         h = mHeight;
    345         buffer = mBuffers[index];
    346 
    347         // destroy() could have been called before we get here, we log it
    348         // because it's uncommon, and the code below should handle it
    349         LOGW_IF(buffer==0,
    350                 "mBuffers[%d] is null (mWidth=%d, mHeight=%d)",
    351                 index, w, h);
    352 
    353         mBuffers[index].clear();
    354     }
    355 
    356     const uint32_t effectiveUsage = getEffectiveUsage(usage);
    357     if (buffer!=0 && buffer->getStrongCount() == 1) {
    358         err = buffer->reallocate(w, h, mFormat, effectiveUsage);
    359     } else {
    360         // here we have to reallocate a new buffer because we could have a
    361         // client in our process with a reference to it (eg: status bar),
    362         // and we can't release the handle under its feet.
    363         buffer.clear();
    364         buffer = new GraphicBuffer(w, h, mFormat, effectiveUsage);
    365         err = buffer->initCheck();
    366     }
    367 
    368     if (err || buffer->handle == 0) {
    369         LOGE_IF(err || buffer->handle == 0,
    370                 "Layer::requestBuffer(this=%p), index=%d, w=%d, h=%d failed (%s)",
    371                 this, index, w, h, strerror(-err));
    372     } else {
    373         LOGD_IF(DEBUG_RESIZE,
    374                 "Layer::requestBuffer(this=%p), index=%d, w=%d, h=%d, handle=%p",
    375                 this, index, w, h, buffer->handle);
    376     }
    377 
    378     if (err == NO_ERROR && buffer->handle != 0) {
    379         Mutex::Autolock _l(mLock);
    380         if (mWidth && mHeight) {
    381             // and we have new buffer
    382             mBuffers[index] = buffer;
    383             // texture is now dirty...
    384             mTextures[index].dirty = true;
    385         } else {
    386             // oops we got killed while we were allocating the buffer
    387             buffer.clear();
    388         }
    389     }
    390     return buffer;
    391 }
    392 
    393 uint32_t Layer::getEffectiveUsage(uint32_t usage) const
    394 {
    395     /*
    396      *  buffers used for software rendering, but h/w composition
    397      *  are allocated with SW_READ_OFTEN | SW_WRITE_OFTEN | HW_TEXTURE
    398      *
    399      *  buffers used for h/w rendering and h/w composition
    400      *  are allocated with  HW_RENDER | HW_TEXTURE
    401      *
    402      *  buffers used with h/w rendering and either NPOT or no egl_image_ext
    403      *  are allocated with SW_READ_RARELY | HW_RENDER
    404      *
    405      */
    406 
    407     if (mSecure) {
    408         // secure buffer, don't store it into the GPU
    409         usage = GraphicBuffer::USAGE_SW_READ_OFTEN |
    410                 GraphicBuffer::USAGE_SW_WRITE_OFTEN;
    411     } else {
    412         // it's allowed to modify the usage flags here, but generally
    413         // the requested flags should be honored.
    414         if (mNoEGLImageForSwBuffers) {
    415             if (usage & GraphicBuffer::USAGE_HW_MASK) {
    416                 // request EGLImage for h/w buffers only
    417                 usage |= GraphicBuffer::USAGE_HW_TEXTURE;
    418             }
    419         } else {
    420             // request EGLImage for all buffers
    421             usage |= GraphicBuffer::USAGE_HW_TEXTURE;
    422         }
    423     }
    424     return usage;
    425 }
    426 
    427 uint32_t Layer::doTransaction(uint32_t flags)
    428 {
    429     const Layer::State& front(drawingState());
    430     const Layer::State& temp(currentState());
    431 
    432     if ((front.requested_w != temp.requested_w) ||
    433         (front.requested_h != temp.requested_h)) {
    434         // the size changed, we need to ask our client to request a new buffer
    435         LOGD_IF(DEBUG_RESIZE,
    436                     "resize (layer=%p), requested (%dx%d), "
    437                     "drawing (%d,%d), (%dx%d), (%dx%d)",
    438                     this,
    439                     int(temp.requested_w), int(temp.requested_h),
    440                     int(front.requested_w), int(front.requested_h),
    441                     int(mBuffers[0]->getWidth()), int(mBuffers[0]->getHeight()),
    442                     int(mBuffers[1]->getWidth()), int(mBuffers[1]->getHeight()));
    443 
    444         // we're being resized and there is a freeze display request,
    445         // acquire a freeze lock, so that the screen stays put
    446         // until we've redrawn at the new size; this is to avoid
    447         // glitches upon orientation changes.
    448         if (mFlinger->hasFreezeRequest()) {
    449             // if the surface is hidden, don't try to acquire the
    450             // freeze lock, since hidden surfaces may never redraw
    451             if (!(front.flags & ISurfaceComposer::eLayerHidden)) {
    452                 mFreezeLock = mFlinger->getFreezeLock();
    453             }
    454         }
    455 
    456         // this will make sure LayerBase::doTransaction doesn't update
    457         // the drawing state's size
    458         Layer::State& editDraw(mDrawingState);
    459         editDraw.requested_w = temp.requested_w;
    460         editDraw.requested_h = temp.requested_h;
    461 
    462         // record the new size, form this point on, when the client request a
    463         // buffer, it'll get the new size.
    464         setDrawingSize(temp.requested_w, temp.requested_h);
    465 
    466         // all buffers need reallocation
    467         lcblk->reallocate();
    468     }
    469 
    470     if (temp.sequence != front.sequence) {
    471         if (temp.flags & ISurfaceComposer::eLayerHidden || temp.alpha == 0) {
    472             // this surface is now hidden, so it shouldn't hold a freeze lock
    473             // (it may never redraw, which is fine if it is hidden)
    474             mFreezeLock.clear();
    475         }
    476     }
    477 
    478     return LayerBase::doTransaction(flags);
    479 }
    480 
    481 void Layer::setDrawingSize(uint32_t w, uint32_t h) {
    482     Mutex::Autolock _l(mLock);
    483     mWidth = w;
    484     mHeight = h;
    485 }
    486 
    487 // ----------------------------------------------------------------------------
    488 // pageflip handling...
    489 // ----------------------------------------------------------------------------
    490 
    491 void Layer::lockPageFlip(bool& recomputeVisibleRegions)
    492 {
    493     ssize_t buf = lcblk->retireAndLock();
    494     if (buf < NO_ERROR) {
    495         //LOGW("nothing to retire (%s)", strerror(-buf));
    496         // NOTE: here the buffer is locked because we will used
    497         // for composition later in the loop
    498         return;
    499     }
    500 
    501     // ouch, this really should never happen
    502     if (uint32_t(buf)>=NUM_BUFFERS) {
    503         LOGE("retireAndLock() buffer index (%d) out of range", buf);
    504         mPostedDirtyRegion.clear();
    505         return;
    506     }
    507 
    508     // we retired a buffer, which becomes the new front buffer
    509     mFrontBufferIndex = buf;
    510 
    511     // get the dirty region
    512     sp<GraphicBuffer> newFrontBuffer(getBuffer(buf));
    513     if (newFrontBuffer != NULL) {
    514         // compute the posted region
    515         const Region dirty(lcblk->getDirtyRegion(buf));
    516         mPostedDirtyRegion = dirty.intersect( newFrontBuffer->getBounds() );
    517 
    518         // update the layer size and release freeze-lock
    519         const Layer::State& front(drawingState());
    520         if (newFrontBuffer->getWidth()  == front.requested_w &&
    521             newFrontBuffer->getHeight() == front.requested_h)
    522         {
    523             if ((front.w != front.requested_w) ||
    524                 (front.h != front.requested_h))
    525             {
    526                 // Here we pretend the transaction happened by updating the
    527                 // current and drawing states. Drawing state is only accessed
    528                 // in this thread, no need to have it locked
    529                 Layer::State& editDraw(mDrawingState);
    530                 editDraw.w = editDraw.requested_w;
    531                 editDraw.h = editDraw.requested_h;
    532 
    533                 // We also need to update the current state so that we don't
    534                 // end-up doing too much work during the next transaction.
    535                 // NOTE: We actually don't need hold the transaction lock here
    536                 // because State::w and State::h are only accessed from
    537                 // this thread
    538                 Layer::State& editTemp(currentState());
    539                 editTemp.w = editDraw.w;
    540                 editTemp.h = editDraw.h;
    541 
    542                 // recompute visible region
    543                 recomputeVisibleRegions = true;
    544             }
    545 
    546             // we now have the correct size, unfreeze the screen
    547             mFreezeLock.clear();
    548         }
    549     } else {
    550         // this should not happen unless we ran out of memory while
    551         // allocating the buffer. we're hoping that things will get back
    552         // to normal the next time the app tries to draw into this buffer.
    553         // meanwhile, pretend the screen didn't update.
    554         mPostedDirtyRegion.clear();
    555     }
    556 
    557     if (lcblk->getQueuedCount()) {
    558         // signal an event if we have more buffers waiting
    559         mFlinger->signalEvent();
    560     }
    561 
    562     if (!mPostedDirtyRegion.isEmpty()) {
    563         reloadTexture( mPostedDirtyRegion );
    564     }
    565 }
    566 
    567 void Layer::unlockPageFlip(
    568         const Transform& planeTransform, Region& outDirtyRegion)
    569 {
    570     Region dirtyRegion(mPostedDirtyRegion);
    571     if (!dirtyRegion.isEmpty()) {
    572         mPostedDirtyRegion.clear();
    573         // The dirty region is given in the layer's coordinate space
    574         // transform the dirty region by the surface's transformation
    575         // and the global transformation.
    576         const Layer::State& s(drawingState());
    577         const Transform tr(planeTransform * s.transform);
    578         dirtyRegion = tr.transform(dirtyRegion);
    579 
    580         // At this point, the dirty region is in screen space.
    581         // Make sure it's constrained by the visible region (which
    582         // is in screen space as well).
    583         dirtyRegion.andSelf(visibleRegionScreen);
    584         outDirtyRegion.orSelf(dirtyRegion);
    585     }
    586     if (visibleRegionScreen.isEmpty()) {
    587         // an invisible layer should not hold a freeze-lock
    588         // (because it may never be updated and thereore never release it)
    589         mFreezeLock.clear();
    590     }
    591 }
    592 
    593 void Layer::finishPageFlip()
    594 {
    595     status_t err = lcblk->unlock( mFrontBufferIndex );
    596     LOGE_IF(err!=NO_ERROR,
    597             "layer %p, buffer=%d wasn't locked!",
    598             this, mFrontBufferIndex);
    599 }
    600 
    601 // ---------------------------------------------------------------------------
    602 
    603 Layer::SurfaceLayer::SurfaceLayer(const sp<SurfaceFlinger>& flinger,
    604         SurfaceID id, const sp<Layer>& owner)
    605     : Surface(flinger, id, owner->getIdentity(), owner)
    606 {
    607 }
    608 
    609 Layer::SurfaceLayer::~SurfaceLayer()
    610 {
    611 }
    612 
    613 sp<GraphicBuffer> Layer::SurfaceLayer::requestBuffer(int index, int usage)
    614 {
    615     sp<GraphicBuffer> buffer;
    616     sp<Layer> owner(getOwner());
    617     if (owner != 0) {
    618         LOGE_IF(uint32_t(index)>=NUM_BUFFERS,
    619                 "getBuffer() index (%d) out of range", index);
    620         if (uint32_t(index) < NUM_BUFFERS) {
    621             buffer = owner->requestBuffer(index, usage);
    622         }
    623     }
    624     return buffer;
    625 }
    626 
    627 // ---------------------------------------------------------------------------
    628 
    629 
    630 }; // namespace android
    631