Loading include/gui/BufferQueue.h +13 −1 Original line number Diff line number Diff line Loading @@ -340,6 +340,13 @@ public: // The count must be between 2 and NUM_BUFFER_SLOTS, inclusive. status_t setDefaultMaxBufferCount(int bufferCount); // disableAsyncBuffer disables the extra buffer used in async mode // (when both producer and consumer have set their "isControlledByApp" // flag) and has dequeueBuffer() return WOULD_BLOCK instead. // // This can only be called before consumerConnect(). status_t disableAsyncBuffer(); // setMaxAcquiredBufferCount sets the maximum number of buffers that can // be acquired by the consumer at one time (default 1). This call will // fail if a producer is connected to the BufferQueue. Loading @@ -364,6 +371,7 @@ public: // NATIVE_WINDOW_TRANSFORM_ROT_90. The default is 0 (no transform). status_t setTransformHint(uint32_t hint); private: // freeBufferLocked frees the GraphicBuffer and sync resources for the // given slot. Loading Loading @@ -559,10 +567,14 @@ private: bool mConsumerControlledByApp; // mDequeueBufferCannotBlock whether dequeueBuffer() isn't allowed to block. // this flag is set durring connect() when both consumer and producer are controlled // this flag is set during connect() when both consumer and producer are controlled // by the application. bool mDequeueBufferCannotBlock; // mUseAsyncBuffer whether an extra buffer is used in async mode to prevent // dequeueBuffer() from ever blocking. bool mUseAsyncBuffer; // mConnectedApi indicates the producer API that is currently connected // to this BufferQueue. It defaults to NO_CONNECTED_API (= 0), and gets // updated by the connect and disconnect methods. Loading include/gui/GLConsumer.h +12 −1 Original line number Diff line number Diff line Loading @@ -98,6 +98,13 @@ public: // This calls doGLFenceWait to ensure proper synchronization. status_t updateTexImage(); // releaseTexImage releases the texture acquired in updateTexImage(). // This is intended to be used in single buffer mode. // // This call may only be made while the OpenGL ES context to which the // target texture belongs is bound to the calling thread. status_t releaseTexImage(); // setReleaseFence stores a fence that will signal when the current buffer // is no longer being read. This fence will be returned to the producer // when the current buffer is released by updateTexImage(). Multiple Loading Loading @@ -251,7 +258,7 @@ protected: // This releases the buffer in the slot referenced by mCurrentTexture, // then updates state to refer to the BufferItem, which must be a // newly-acquired buffer. status_t releaseAndUpdateLocked(const BufferQueue::BufferItem& item); status_t updateAndReleaseLocked(const BufferQueue::BufferItem& item); // Binds mTexName and the current buffer to mTexTarget. Uses // mCurrentTexture if it's set, mCurrentTextureBuf if not. If the Loading Loading @@ -416,6 +423,10 @@ private: // It is set to false by detachFromContext, and then set to true again by // attachToContext. bool mAttached; // mReleasedTexImageBuffer is a dummy buffer used when in single buffer // mode and releaseTexImage() has been called sp<GraphicBuffer> mReleasedTexImageBuffer; }; // ---------------------------------------------------------------------------- Loading libs/gui/BufferQueue.cpp +25 −3 Original line number Diff line number Diff line Loading @@ -72,6 +72,7 @@ BufferQueue::BufferQueue(const sp<IGraphicBufferAlloc>& allocator) : mOverrideMaxBufferCount(0), mConsumerControlledByApp(false), mDequeueBufferCannotBlock(false), mUseAsyncBuffer(true), mConnectedApi(NO_CONNECTED_API), mAbandoned(false), mFrameCounter(0), Loading Loading @@ -100,7 +101,8 @@ BufferQueue::~BufferQueue() { } status_t BufferQueue::setDefaultMaxBufferCountLocked(int count) { if (count < 2 || count > NUM_BUFFER_SLOTS) const int minBufferCount = mUseAsyncBuffer ? 2 : 1; if (count < minBufferCount || count > NUM_BUFFER_SLOTS) return BAD_VALUE; mDefaultMaxBufferCount = count; Loading Loading @@ -1033,6 +1035,17 @@ status_t BufferQueue::setDefaultMaxBufferCount(int bufferCount) { return setDefaultMaxBufferCountLocked(bufferCount); } status_t BufferQueue::disableAsyncBuffer() { ATRACE_CALL(); Mutex::Autolock lock(mMutex); if (mConsumerListener != NULL) { ST_LOGE("disableAsyncBuffer: consumer already connected!"); return INVALID_OPERATION; } mUseAsyncBuffer = false; return NO_ERROR; } status_t BufferQueue::setMaxAcquiredBufferCount(int maxAcquiredBuffers) { ATRACE_CALL(); Mutex::Autolock lock(mMutex); Loading @@ -1049,8 +1062,17 @@ status_t BufferQueue::setMaxAcquiredBufferCount(int maxAcquiredBuffers) { } int BufferQueue::getMinUndequeuedBufferCount(bool async) const { return (mDequeueBufferCannotBlock || async) ? mMaxAcquiredBufferCount+1 : mMaxAcquiredBufferCount; // if dequeueBuffer is allowed to error out, we don't have to // add an extra buffer. if (!mUseAsyncBuffer) return mMaxAcquiredBufferCount; // we're in async mode, or we want to prevent the app to // deadlock itself, we throw-in an extra buffer to guarantee it. if (mDequeueBufferCannotBlock || async) return mMaxAcquiredBufferCount+1; return mMaxAcquiredBufferCount; } int BufferQueue::getMinMaxBufferCountLocked(bool async) const { Loading libs/gui/GLConsumer.cpp +88 −7 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ #include <EGL/eglext.h> #include <GLES2/gl2.h> #include <GLES2/gl2ext.h> #include <cutils/compiler.h> #include <hardware/hardware.h> Loading @@ -49,6 +50,12 @@ namespace android { #define ST_LOGW(x, ...) ALOGW("[%s] "x, mName.string(), ##__VA_ARGS__) #define ST_LOGE(x, ...) ALOGE("[%s] "x, mName.string(), ##__VA_ARGS__) static const struct { size_t width, height; char const* bits; } kDebugData = { 11, 8, "__X_____X_____X___X_____XXXXXXX___XX_XXX_XX_XXXXXXXXXXXX_XXXXXXX_XX_X_____X_X___XX_XX___" }; // Transform matrices static float mtxIdentity[16] = { 1, 0, 0, 0, Loading Loading @@ -154,7 +161,7 @@ status_t GLConsumer::updateTexImage() { } // Release the previous buffer. err = releaseAndUpdateLocked(item); err = updateAndReleaseLocked(item); if (err != NO_ERROR) { // We always bind the texture. glBindTexture(mTexTarget, mTexName); Loading @@ -165,6 +172,80 @@ status_t GLConsumer::updateTexImage() { return bindTextureImageLocked(); } status_t GLConsumer::releaseTexImage() { ATRACE_CALL(); ST_LOGV("releaseTexImage"); Mutex::Autolock lock(mMutex); if (mAbandoned) { ST_LOGE("releaseTexImage: GLConsumer is abandoned!"); return NO_INIT; } // Make sure the EGL state is the same as in previous calls. status_t err = checkAndUpdateEglStateLocked(); if (err != NO_ERROR) { return err; } // Update the GLConsumer state. int buf = mCurrentTexture; if (buf != BufferQueue::INVALID_BUFFER_SLOT) { ST_LOGV("releaseTexImage:(slot=%d", buf); // Do whatever sync ops we need to do before releasing the slot. err = syncForReleaseLocked(mEglDisplay); if (err != NO_ERROR) { ST_LOGE("syncForReleaseLocked failed (slot=%d), err=%d", buf, err); return err; } err = releaseBufferLocked(buf, mSlots[buf].mGraphicBuffer, mEglDisplay, EGL_NO_SYNC_KHR); if (err < NO_ERROR) { ST_LOGE("releaseTexImage: failed to release buffer: %s (%d)", strerror(-err), err); return err; } if (CC_UNLIKELY(mReleasedTexImageBuffer == NULL)) { // The first time, create the debug texture in case the application // continues to use it. sp<GraphicBuffer> buffer = new GraphicBuffer(11, 8, PIXEL_FORMAT_RGBA_8888, GraphicBuffer::USAGE_SW_WRITE_RARELY); uint32_t* bits; buffer->lock(GraphicBuffer::USAGE_SW_WRITE_RARELY, reinterpret_cast<void**>(&bits)); size_t w = buffer->getStride(); size_t h = buffer->getHeight(); memset(bits, 0, w*h*4); for (size_t y=0 ; y<kDebugData.height ; y++) { for (size_t x=0 ; x<kDebugData.width ; x++) { bits[x] = (kDebugData.bits[y*11+x] == 'X') ? 0xFF000000 : 0xFFFFFFFF; } bits += w; } buffer->unlock(); mReleasedTexImageBuffer = buffer; } mCurrentTexture = BufferQueue::INVALID_BUFFER_SLOT; mCurrentTextureBuf = mReleasedTexImageBuffer; mCurrentCrop.makeInvalid(); mCurrentTransform = 0; mCurrentScalingMode = NATIVE_WINDOW_SCALING_MODE_FREEZE; mCurrentTimestamp = 0; mCurrentFence = Fence::NO_FENCE; // bind a dummy texture glBindTexture(mTexTarget, mTexName); bindUnslottedBufferLocked(mEglDisplay); } return NO_ERROR; } status_t GLConsumer::acquireBufferLocked(BufferQueue::BufferItem *item, nsecs_t presentWhen) { status_t err = ConsumerBase::acquireBufferLocked(item, presentWhen); Loading Loading @@ -202,12 +283,12 @@ status_t GLConsumer::releaseBufferLocked(int buf, return err; } status_t GLConsumer::releaseAndUpdateLocked(const BufferQueue::BufferItem& item) status_t GLConsumer::updateAndReleaseLocked(const BufferQueue::BufferItem& item) { status_t err = NO_ERROR; if (!mAttached) { ST_LOGE("releaseAndUpdate: GLConsumer is not attached to an OpenGL " ST_LOGE("updateAndRelease: GLConsumer is not attached to an OpenGL " "ES context"); return INVALID_OPERATION; } Loading @@ -230,7 +311,7 @@ status_t GLConsumer::releaseAndUpdateLocked(const BufferQueue::BufferItem& item) if (mEglSlots[buf].mEglImage == EGL_NO_IMAGE_KHR) { EGLImageKHR image = createImage(mEglDisplay, mSlots[buf].mGraphicBuffer); if (image == EGL_NO_IMAGE_KHR) { ST_LOGW("releaseAndUpdate: unable to createImage on display=%p slot=%d", ST_LOGW("updateAndRelease: unable to createImage on display=%p slot=%d", mEglDisplay, buf); return UNKNOWN_ERROR; } Loading @@ -249,7 +330,7 @@ status_t GLConsumer::releaseAndUpdateLocked(const BufferQueue::BufferItem& item) return err; } ST_LOGV("releaseAndUpdate: (slot=%d buf=%p) -> (slot=%d buf=%p)", ST_LOGV("updateAndRelease: (slot=%d buf=%p) -> (slot=%d buf=%p)", mCurrentTexture, mCurrentTextureBuf != NULL ? mCurrentTextureBuf->handle : 0, buf, mSlots[buf].mGraphicBuffer->handle); Loading @@ -259,8 +340,8 @@ status_t GLConsumer::releaseAndUpdateLocked(const BufferQueue::BufferItem& item) status_t status = releaseBufferLocked( mCurrentTexture, mCurrentTextureBuf, mEglDisplay, mEglSlots[mCurrentTexture].mEglFence); if (status != NO_ERROR && status != BufferQueue::STALE_BUFFER_SLOT) { ST_LOGE("releaseAndUpdate: failed to release buffer: %s (%d)", if (status < NO_ERROR) { ST_LOGE("updateAndRelease: failed to release buffer: %s (%d)", strerror(-status), status); err = status; // keep going, with error raised [?] Loading services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -108,7 +108,7 @@ status_t FramebufferSurface::nextBuffer(sp<GraphicBuffer>& outBuffer, sp<Fence>& // Release the previous buffer. err = releaseBufferLocked(mCurrentBufferSlot, mCurrentBuffer, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR); if (err != NO_ERROR && err != BufferQueue::STALE_BUFFER_SLOT) { if (err < NO_ERROR) { ALOGE("error releasing buffer: %s (%d)", strerror(-err), err); return err; } Loading Loading
include/gui/BufferQueue.h +13 −1 Original line number Diff line number Diff line Loading @@ -340,6 +340,13 @@ public: // The count must be between 2 and NUM_BUFFER_SLOTS, inclusive. status_t setDefaultMaxBufferCount(int bufferCount); // disableAsyncBuffer disables the extra buffer used in async mode // (when both producer and consumer have set their "isControlledByApp" // flag) and has dequeueBuffer() return WOULD_BLOCK instead. // // This can only be called before consumerConnect(). status_t disableAsyncBuffer(); // setMaxAcquiredBufferCount sets the maximum number of buffers that can // be acquired by the consumer at one time (default 1). This call will // fail if a producer is connected to the BufferQueue. Loading @@ -364,6 +371,7 @@ public: // NATIVE_WINDOW_TRANSFORM_ROT_90. The default is 0 (no transform). status_t setTransformHint(uint32_t hint); private: // freeBufferLocked frees the GraphicBuffer and sync resources for the // given slot. Loading Loading @@ -559,10 +567,14 @@ private: bool mConsumerControlledByApp; // mDequeueBufferCannotBlock whether dequeueBuffer() isn't allowed to block. // this flag is set durring connect() when both consumer and producer are controlled // this flag is set during connect() when both consumer and producer are controlled // by the application. bool mDequeueBufferCannotBlock; // mUseAsyncBuffer whether an extra buffer is used in async mode to prevent // dequeueBuffer() from ever blocking. bool mUseAsyncBuffer; // mConnectedApi indicates the producer API that is currently connected // to this BufferQueue. It defaults to NO_CONNECTED_API (= 0), and gets // updated by the connect and disconnect methods. Loading
include/gui/GLConsumer.h +12 −1 Original line number Diff line number Diff line Loading @@ -98,6 +98,13 @@ public: // This calls doGLFenceWait to ensure proper synchronization. status_t updateTexImage(); // releaseTexImage releases the texture acquired in updateTexImage(). // This is intended to be used in single buffer mode. // // This call may only be made while the OpenGL ES context to which the // target texture belongs is bound to the calling thread. status_t releaseTexImage(); // setReleaseFence stores a fence that will signal when the current buffer // is no longer being read. This fence will be returned to the producer // when the current buffer is released by updateTexImage(). Multiple Loading Loading @@ -251,7 +258,7 @@ protected: // This releases the buffer in the slot referenced by mCurrentTexture, // then updates state to refer to the BufferItem, which must be a // newly-acquired buffer. status_t releaseAndUpdateLocked(const BufferQueue::BufferItem& item); status_t updateAndReleaseLocked(const BufferQueue::BufferItem& item); // Binds mTexName and the current buffer to mTexTarget. Uses // mCurrentTexture if it's set, mCurrentTextureBuf if not. If the Loading Loading @@ -416,6 +423,10 @@ private: // It is set to false by detachFromContext, and then set to true again by // attachToContext. bool mAttached; // mReleasedTexImageBuffer is a dummy buffer used when in single buffer // mode and releaseTexImage() has been called sp<GraphicBuffer> mReleasedTexImageBuffer; }; // ---------------------------------------------------------------------------- Loading
libs/gui/BufferQueue.cpp +25 −3 Original line number Diff line number Diff line Loading @@ -72,6 +72,7 @@ BufferQueue::BufferQueue(const sp<IGraphicBufferAlloc>& allocator) : mOverrideMaxBufferCount(0), mConsumerControlledByApp(false), mDequeueBufferCannotBlock(false), mUseAsyncBuffer(true), mConnectedApi(NO_CONNECTED_API), mAbandoned(false), mFrameCounter(0), Loading Loading @@ -100,7 +101,8 @@ BufferQueue::~BufferQueue() { } status_t BufferQueue::setDefaultMaxBufferCountLocked(int count) { if (count < 2 || count > NUM_BUFFER_SLOTS) const int minBufferCount = mUseAsyncBuffer ? 2 : 1; if (count < minBufferCount || count > NUM_BUFFER_SLOTS) return BAD_VALUE; mDefaultMaxBufferCount = count; Loading Loading @@ -1033,6 +1035,17 @@ status_t BufferQueue::setDefaultMaxBufferCount(int bufferCount) { return setDefaultMaxBufferCountLocked(bufferCount); } status_t BufferQueue::disableAsyncBuffer() { ATRACE_CALL(); Mutex::Autolock lock(mMutex); if (mConsumerListener != NULL) { ST_LOGE("disableAsyncBuffer: consumer already connected!"); return INVALID_OPERATION; } mUseAsyncBuffer = false; return NO_ERROR; } status_t BufferQueue::setMaxAcquiredBufferCount(int maxAcquiredBuffers) { ATRACE_CALL(); Mutex::Autolock lock(mMutex); Loading @@ -1049,8 +1062,17 @@ status_t BufferQueue::setMaxAcquiredBufferCount(int maxAcquiredBuffers) { } int BufferQueue::getMinUndequeuedBufferCount(bool async) const { return (mDequeueBufferCannotBlock || async) ? mMaxAcquiredBufferCount+1 : mMaxAcquiredBufferCount; // if dequeueBuffer is allowed to error out, we don't have to // add an extra buffer. if (!mUseAsyncBuffer) return mMaxAcquiredBufferCount; // we're in async mode, or we want to prevent the app to // deadlock itself, we throw-in an extra buffer to guarantee it. if (mDequeueBufferCannotBlock || async) return mMaxAcquiredBufferCount+1; return mMaxAcquiredBufferCount; } int BufferQueue::getMinMaxBufferCountLocked(bool async) const { Loading
libs/gui/GLConsumer.cpp +88 −7 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ #include <EGL/eglext.h> #include <GLES2/gl2.h> #include <GLES2/gl2ext.h> #include <cutils/compiler.h> #include <hardware/hardware.h> Loading @@ -49,6 +50,12 @@ namespace android { #define ST_LOGW(x, ...) ALOGW("[%s] "x, mName.string(), ##__VA_ARGS__) #define ST_LOGE(x, ...) ALOGE("[%s] "x, mName.string(), ##__VA_ARGS__) static const struct { size_t width, height; char const* bits; } kDebugData = { 11, 8, "__X_____X_____X___X_____XXXXXXX___XX_XXX_XX_XXXXXXXXXXXX_XXXXXXX_XX_X_____X_X___XX_XX___" }; // Transform matrices static float mtxIdentity[16] = { 1, 0, 0, 0, Loading Loading @@ -154,7 +161,7 @@ status_t GLConsumer::updateTexImage() { } // Release the previous buffer. err = releaseAndUpdateLocked(item); err = updateAndReleaseLocked(item); if (err != NO_ERROR) { // We always bind the texture. glBindTexture(mTexTarget, mTexName); Loading @@ -165,6 +172,80 @@ status_t GLConsumer::updateTexImage() { return bindTextureImageLocked(); } status_t GLConsumer::releaseTexImage() { ATRACE_CALL(); ST_LOGV("releaseTexImage"); Mutex::Autolock lock(mMutex); if (mAbandoned) { ST_LOGE("releaseTexImage: GLConsumer is abandoned!"); return NO_INIT; } // Make sure the EGL state is the same as in previous calls. status_t err = checkAndUpdateEglStateLocked(); if (err != NO_ERROR) { return err; } // Update the GLConsumer state. int buf = mCurrentTexture; if (buf != BufferQueue::INVALID_BUFFER_SLOT) { ST_LOGV("releaseTexImage:(slot=%d", buf); // Do whatever sync ops we need to do before releasing the slot. err = syncForReleaseLocked(mEglDisplay); if (err != NO_ERROR) { ST_LOGE("syncForReleaseLocked failed (slot=%d), err=%d", buf, err); return err; } err = releaseBufferLocked(buf, mSlots[buf].mGraphicBuffer, mEglDisplay, EGL_NO_SYNC_KHR); if (err < NO_ERROR) { ST_LOGE("releaseTexImage: failed to release buffer: %s (%d)", strerror(-err), err); return err; } if (CC_UNLIKELY(mReleasedTexImageBuffer == NULL)) { // The first time, create the debug texture in case the application // continues to use it. sp<GraphicBuffer> buffer = new GraphicBuffer(11, 8, PIXEL_FORMAT_RGBA_8888, GraphicBuffer::USAGE_SW_WRITE_RARELY); uint32_t* bits; buffer->lock(GraphicBuffer::USAGE_SW_WRITE_RARELY, reinterpret_cast<void**>(&bits)); size_t w = buffer->getStride(); size_t h = buffer->getHeight(); memset(bits, 0, w*h*4); for (size_t y=0 ; y<kDebugData.height ; y++) { for (size_t x=0 ; x<kDebugData.width ; x++) { bits[x] = (kDebugData.bits[y*11+x] == 'X') ? 0xFF000000 : 0xFFFFFFFF; } bits += w; } buffer->unlock(); mReleasedTexImageBuffer = buffer; } mCurrentTexture = BufferQueue::INVALID_BUFFER_SLOT; mCurrentTextureBuf = mReleasedTexImageBuffer; mCurrentCrop.makeInvalid(); mCurrentTransform = 0; mCurrentScalingMode = NATIVE_WINDOW_SCALING_MODE_FREEZE; mCurrentTimestamp = 0; mCurrentFence = Fence::NO_FENCE; // bind a dummy texture glBindTexture(mTexTarget, mTexName); bindUnslottedBufferLocked(mEglDisplay); } return NO_ERROR; } status_t GLConsumer::acquireBufferLocked(BufferQueue::BufferItem *item, nsecs_t presentWhen) { status_t err = ConsumerBase::acquireBufferLocked(item, presentWhen); Loading Loading @@ -202,12 +283,12 @@ status_t GLConsumer::releaseBufferLocked(int buf, return err; } status_t GLConsumer::releaseAndUpdateLocked(const BufferQueue::BufferItem& item) status_t GLConsumer::updateAndReleaseLocked(const BufferQueue::BufferItem& item) { status_t err = NO_ERROR; if (!mAttached) { ST_LOGE("releaseAndUpdate: GLConsumer is not attached to an OpenGL " ST_LOGE("updateAndRelease: GLConsumer is not attached to an OpenGL " "ES context"); return INVALID_OPERATION; } Loading @@ -230,7 +311,7 @@ status_t GLConsumer::releaseAndUpdateLocked(const BufferQueue::BufferItem& item) if (mEglSlots[buf].mEglImage == EGL_NO_IMAGE_KHR) { EGLImageKHR image = createImage(mEglDisplay, mSlots[buf].mGraphicBuffer); if (image == EGL_NO_IMAGE_KHR) { ST_LOGW("releaseAndUpdate: unable to createImage on display=%p slot=%d", ST_LOGW("updateAndRelease: unable to createImage on display=%p slot=%d", mEglDisplay, buf); return UNKNOWN_ERROR; } Loading @@ -249,7 +330,7 @@ status_t GLConsumer::releaseAndUpdateLocked(const BufferQueue::BufferItem& item) return err; } ST_LOGV("releaseAndUpdate: (slot=%d buf=%p) -> (slot=%d buf=%p)", ST_LOGV("updateAndRelease: (slot=%d buf=%p) -> (slot=%d buf=%p)", mCurrentTexture, mCurrentTextureBuf != NULL ? mCurrentTextureBuf->handle : 0, buf, mSlots[buf].mGraphicBuffer->handle); Loading @@ -259,8 +340,8 @@ status_t GLConsumer::releaseAndUpdateLocked(const BufferQueue::BufferItem& item) status_t status = releaseBufferLocked( mCurrentTexture, mCurrentTextureBuf, mEglDisplay, mEglSlots[mCurrentTexture].mEglFence); if (status != NO_ERROR && status != BufferQueue::STALE_BUFFER_SLOT) { ST_LOGE("releaseAndUpdate: failed to release buffer: %s (%d)", if (status < NO_ERROR) { ST_LOGE("updateAndRelease: failed to release buffer: %s (%d)", strerror(-status), status); err = status; // keep going, with error raised [?] Loading
services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -108,7 +108,7 @@ status_t FramebufferSurface::nextBuffer(sp<GraphicBuffer>& outBuffer, sp<Fence>& // Release the previous buffer. err = releaseBufferLocked(mCurrentBufferSlot, mCurrentBuffer, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR); if (err != NO_ERROR && err != BufferQueue::STALE_BUFFER_SLOT) { if (err < NO_ERROR) { ALOGE("error releasing buffer: %s (%d)", strerror(-err), err); return err; } Loading