diff options
Diffstat (limited to 'libs/gui')
-rw-r--r-- | libs/gui/BufferItem.cpp | 2 | ||||
-rw-r--r-- | libs/gui/BufferQueue.cpp | 5 | ||||
-rw-r--r-- | libs/gui/BufferQueueProducer.cpp | 61 | ||||
-rw-r--r-- | libs/gui/ConsumerBase.cpp | 4 | ||||
-rw-r--r-- | libs/gui/GLConsumer.cpp | 6 | ||||
-rw-r--r-- | libs/gui/IConsumerListener.cpp | 20 | ||||
-rw-r--r-- | libs/gui/ISurfaceComposer.cpp | 14 | ||||
-rw-r--r-- | libs/gui/LayerState.cpp | 8 | ||||
-rw-r--r-- | libs/gui/StreamSplitter.cpp | 2 | ||||
-rw-r--r-- | libs/gui/tests/BufferQueue_test.cpp | 2 | ||||
-rw-r--r-- | libs/gui/tests/DisconnectWaiter.h | 2 | ||||
-rw-r--r-- | libs/gui/tests/FrameWaiter.h | 2 | ||||
-rw-r--r-- | libs/gui/tests/IGraphicBufferProducer_test.cpp | 2 | ||||
-rw-r--r-- | libs/gui/tests/StreamSplitter_test.cpp | 2 | ||||
-rw-r--r-- | libs/gui/tests/SurfaceTextureGLThreadToGL.h | 2 |
15 files changed, 96 insertions, 38 deletions
diff --git a/libs/gui/BufferItem.cpp b/libs/gui/BufferItem.cpp index d3fa43e..e6fc791 100644 --- a/libs/gui/BufferItem.cpp +++ b/libs/gui/BufferItem.cpp @@ -36,6 +36,8 @@ BufferItem::BufferItem() : mCrop.makeInvalid(); } +BufferItem::~BufferItem() {} + BufferItem::operator IGraphicBufferConsumer::BufferItem() const { IGraphicBufferConsumer::BufferItem bufferItem; bufferItem.mGraphicBuffer = mGraphicBuffer; diff --git a/libs/gui/BufferQueue.cpp b/libs/gui/BufferQueue.cpp index c49a886..61fd8c4 100644 --- a/libs/gui/BufferQueue.cpp +++ b/libs/gui/BufferQueue.cpp @@ -31,10 +31,11 @@ BufferQueue::ProxyConsumerListener::ProxyConsumerListener( BufferQueue::ProxyConsumerListener::~ProxyConsumerListener() {} -void BufferQueue::ProxyConsumerListener::onFrameAvailable() { +void BufferQueue::ProxyConsumerListener::onFrameAvailable( + const android::BufferItem& item) { sp<ConsumerListener> listener(mConsumerListener.promote()); if (listener != NULL) { - listener->onFrameAvailable(); + listener->onFrameAvailable(item); } } diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp index d2fd3b0..16b9747 100644 --- a/libs/gui/BufferQueueProducer.cpp +++ b/libs/gui/BufferQueueProducer.cpp @@ -38,7 +38,12 @@ BufferQueueProducer::BufferQueueProducer(const sp<BufferQueueCore>& core) : mCore(core), mSlots(core->mSlots), mConsumerName(), - mStickyTransform(0) {} + mStickyTransform(0), + mLastQueueBufferFence(Fence::NO_FENCE), + mCallbackMutex(), + mNextCallbackTicket(0), + mCurrentCallbackTicket(0), + mCallbackCondition() {} BufferQueueProducer::~BufferQueueProducer() {} @@ -522,12 +527,7 @@ status_t BufferQueueProducer::queueBuffer(int slot, if (fence == NULL) { BQ_LOGE("queueBuffer: fence is NULL"); - // Temporary workaround for b/17946343: soldier-on instead of returning an error. This - // prevents the client from dying, at the risk of visible corruption due to hwcomposer - // reading the buffer before the producer is done rendering it. Unless the buffer is the - // last frame of an animation, the corruption will be transient. - fence = Fence::NO_FENCE; - // return BAD_VALUE; + return BAD_VALUE; } switch (scalingMode) { @@ -541,7 +541,10 @@ status_t BufferQueueProducer::queueBuffer(int slot, return BAD_VALUE; } - sp<IConsumerListener> listener; + sp<IConsumerListener> frameAvailableListener; + sp<IConsumerListener> frameReplacedListener; + int callbackTicket = 0; + BufferItem item; { // Autolock scope Mutex::Autolock lock(mCore->mMutex); @@ -597,7 +600,6 @@ status_t BufferQueueProducer::queueBuffer(int slot, ++mCore->mFrameCounter; mSlots[slot].mFrameNumber = mCore->mFrameCounter; - BufferItem item; item.mAcquireCalled = mSlots[slot].mAcquireCalled; item.mGraphicBuffer = mSlots[slot].mGraphicBuffer; item.mCrop = crop; @@ -618,7 +620,7 @@ status_t BufferQueueProducer::queueBuffer(int slot, // When the queue is empty, we can ignore mDequeueBufferCannotBlock // and simply queue this buffer mCore->mQueue.push_back(item); - listener = mCore->mConsumerListener; + frameAvailableListener = mCore->mConsumerListener; } else { // When the queue is not empty, we need to look at the front buffer // state to see if we need to replace it @@ -634,9 +636,10 @@ status_t BufferQueueProducer::queueBuffer(int slot, } // Overwrite the droppable buffer with the incoming one *front = item; + frameReplacedListener = mCore->mConsumerListener; } else { mCore->mQueue.push_back(item); - listener = mCore->mConsumerListener; + frameAvailableListener = mCore->mConsumerListener; } } @@ -647,11 +650,41 @@ status_t BufferQueueProducer::queueBuffer(int slot, mCore->mTransformHint, mCore->mQueue.size()); ATRACE_INT(mCore->mConsumerName.string(), mCore->mQueue.size()); + + // Take a ticket for the callback functions + callbackTicket = mNextCallbackTicket++; } // Autolock scope - // Call back without lock held - if (listener != NULL) { - listener->onFrameAvailable(); + // Wait without lock held + if (mCore->mConnectedApi == NATIVE_WINDOW_API_EGL) { + // Waiting here allows for two full buffers to be queued but not a + // third. In the event that frames take varying time, this makes a + // small trade-off in favor of latency rather than throughput. + mLastQueueBufferFence->waitForever("Throttling EGL Production"); + mLastQueueBufferFence = fence; + } + + // Don't send the GraphicBuffer through the callback, and don't send + // the slot number, since the consumer shouldn't need it + item.mGraphicBuffer.clear(); + item.mSlot = BufferItem::INVALID_BUFFER_SLOT; + + // Call back without the main BufferQueue lock held, but with the callback + // lock held so we can ensure that callbacks occur in order + { + Mutex::Autolock lock(mCallbackMutex); + while (callbackTicket != mCurrentCallbackTicket) { + mCallbackCondition.wait(mCallbackMutex); + } + + if (frameAvailableListener != NULL) { + frameAvailableListener->onFrameAvailable(item); + } else if (frameReplacedListener != NULL) { + frameReplacedListener->onFrameReplaced(item); + } + + ++mCurrentCallbackTicket; + mCallbackCondition.broadcast(); } return NO_ERROR; diff --git a/libs/gui/ConsumerBase.cpp b/libs/gui/ConsumerBase.cpp index e476c9a..95f5507 100644 --- a/libs/gui/ConsumerBase.cpp +++ b/libs/gui/ConsumerBase.cpp @@ -98,7 +98,7 @@ void ConsumerBase::freeBufferLocked(int slotIndex) { mSlots[slotIndex].mFrameNumber = 0; } -void ConsumerBase::onFrameAvailable() { +void ConsumerBase::onFrameAvailable(const BufferItem& item) { CB_LOGV("onFrameAvailable"); sp<FrameAvailableListener> listener; @@ -109,7 +109,7 @@ void ConsumerBase::onFrameAvailable() { if (listener != NULL) { CB_LOGV("actually calling onFrameAvailable"); - listener->onFrameAvailable(); + listener->onFrameAvailable(item); } } diff --git a/libs/gui/GLConsumer.cpp b/libs/gui/GLConsumer.cpp index 6ba2ef8..b886c5b 100644 --- a/libs/gui/GLConsumer.cpp +++ b/libs/gui/GLConsumer.cpp @@ -505,7 +505,7 @@ status_t GLConsumer::checkAndUpdateEglStateLocked(bool contextCheck) { if (mEglDisplay == EGL_NO_DISPLAY) { mEglDisplay = dpy; } - if (mEglContext == EGL_NO_DISPLAY) { + if (mEglContext == EGL_NO_CONTEXT) { mEglContext = ctx; } } @@ -1065,6 +1065,7 @@ GLConsumer::EglImage::~EglImage() { if (!eglDestroyImageKHR(mEglDisplay, mEglImage)) { ALOGE("~EglImage: eglDestroyImageKHR failed"); } + eglTerminate(mEglDisplay); } } @@ -1079,6 +1080,7 @@ status_t GLConsumer::EglImage::createIfNeeded(EGLDisplay eglDisplay, if (!eglDestroyImageKHR(mEglDisplay, mEglImage)) { ALOGE("createIfNeeded: eglDestroyImageKHR failed"); } + eglTerminate(mEglDisplay); mEglImage = EGL_NO_IMAGE_KHR; mEglDisplay = EGL_NO_DISPLAY; } @@ -1129,11 +1131,13 @@ EGLImageKHR GLConsumer::EglImage::createImage(EGLDisplay dpy, // removes this restriction if there is hardware that can support it. attrs[2] = EGL_NONE; } + eglInitialize(dpy, 0, 0); EGLImageKHR image = eglCreateImageKHR(dpy, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID, cbuf, attrs); if (image == EGL_NO_IMAGE_KHR) { EGLint error = eglGetError(); ALOGE("error creating EGLImage: %#x", error); + eglTerminate(dpy); } return image; } diff --git a/libs/gui/IConsumerListener.cpp b/libs/gui/IConsumerListener.cpp index 4ccf0ac..409dfe4 100644 --- a/libs/gui/IConsumerListener.cpp +++ b/libs/gui/IConsumerListener.cpp @@ -21,6 +21,7 @@ #include <binder/Parcel.h> #include <gui/IConsumerListener.h> +#include <gui/BufferItem.h> // --------------------------------------------------------------------------- namespace android { @@ -39,9 +40,10 @@ public: : BpInterface<IConsumerListener>(impl) { } - virtual void onFrameAvailable() { + virtual void onFrameAvailable(const BufferItem& item) { Parcel data, reply; data.writeInterfaceToken(IConsumerListener::getInterfaceDescriptor()); + data.write(item); remote()->transact(ON_FRAME_AVAILABLE, data, &reply, IBinder::FLAG_ONEWAY); } @@ -66,18 +68,20 @@ status_t BnConsumerListener::onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { switch(code) { - case ON_FRAME_AVAILABLE: + case ON_FRAME_AVAILABLE: { CHECK_INTERFACE(IConsumerListener, data, reply); - onFrameAvailable(); - return NO_ERROR; - case ON_BUFFER_RELEASED: + BufferItem item; + data.read(item); + onFrameAvailable(item); + return NO_ERROR; } + case ON_BUFFER_RELEASED: { CHECK_INTERFACE(IConsumerListener, data, reply); onBuffersReleased(); - return NO_ERROR; - case ON_SIDEBAND_STREAM_CHANGED: + return NO_ERROR; } + case ON_SIDEBAND_STREAM_CHANGED: { CHECK_INTERFACE(IConsumerListener, data, reply); onSidebandStreamChanged(); - return NO_ERROR; + return NO_ERROR; } } return BBinder::onTransact(code, data, reply, flags); } diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index 81e8336..ebb687a 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -312,19 +312,29 @@ status_t BnSurfaceComposer::onTransact( case SET_TRANSACTION_STATE: { CHECK_INTERFACE(ISurfaceComposer, data, reply); size_t count = data.readInt32(); + if (count > data.dataSize()) { + return BAD_VALUE; + } ComposerState s; Vector<ComposerState> state; state.setCapacity(count); for (size_t i=0 ; i<count ; i++) { - s.read(data); + if (s.read(data) == BAD_VALUE) { + return BAD_VALUE; + } state.add(s); } count = data.readInt32(); + if (count > data.dataSize()) { + return BAD_VALUE; + } DisplayState d; Vector<DisplayState> displays; displays.setCapacity(count); for (size_t i=0 ; i<count ; i++) { - d.read(data); + if (d.read(data) == BAD_VALUE) { + return BAD_VALUE; + } displays.add(d); } uint32_t flags = data.readInt32(); diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index 9d3f116..39f8f92 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -55,8 +55,12 @@ status_t layer_state_t::read(const Parcel& input) alpha = input.readFloat(); flags = input.readInt32(); mask = input.readInt32(); - matrix = *reinterpret_cast<layer_state_t::matrix22_t const *>( - input.readInplace(sizeof(layer_state_t::matrix22_t))); + const void* matrix_data = input.readInplace(sizeof(layer_state_t::matrix22_t)); + if (matrix_data) { + matrix = *reinterpret_cast<layer_state_t::matrix22_t const *>(matrix_data); + } else { + return BAD_VALUE; + } input.read(crop); input.read(transparentRegion); return NO_ERROR; diff --git a/libs/gui/StreamSplitter.cpp b/libs/gui/StreamSplitter.cpp index 771b263..5f39905 100644 --- a/libs/gui/StreamSplitter.cpp +++ b/libs/gui/StreamSplitter.cpp @@ -98,7 +98,7 @@ void StreamSplitter::setName(const String8 &name) { mInput->setConsumerName(name); } -void StreamSplitter::onFrameAvailable() { +void StreamSplitter::onFrameAvailable(const BufferItem& /* item */) { ATRACE_CALL(); Mutex::Autolock lock(mMutex); diff --git a/libs/gui/tests/BufferQueue_test.cpp b/libs/gui/tests/BufferQueue_test.cpp index c781366..96de11f 100644 --- a/libs/gui/tests/BufferQueue_test.cpp +++ b/libs/gui/tests/BufferQueue_test.cpp @@ -67,7 +67,7 @@ protected: }; struct DummyConsumer : public BnConsumerListener { - virtual void onFrameAvailable() {} + virtual void onFrameAvailable(const BufferItem& /* item */) {} virtual void onBuffersReleased() {} virtual void onSidebandStreamChanged() {} }; diff --git a/libs/gui/tests/DisconnectWaiter.h b/libs/gui/tests/DisconnectWaiter.h index 56e96c2..6e6915b 100644 --- a/libs/gui/tests/DisconnectWaiter.h +++ b/libs/gui/tests/DisconnectWaiter.h @@ -44,7 +44,7 @@ public: mPendingFrames--; } - virtual void onFrameAvailable() { + virtual void onFrameAvailable(const BufferItem& /* item */) { Mutex::Autolock lock(mMutex); mPendingFrames++; mFrameCondition.signal(); diff --git a/libs/gui/tests/FrameWaiter.h b/libs/gui/tests/FrameWaiter.h index bdedba6..f78fa00 100644 --- a/libs/gui/tests/FrameWaiter.h +++ b/libs/gui/tests/FrameWaiter.h @@ -35,7 +35,7 @@ public: mPendingFrames--; } - virtual void onFrameAvailable() { + virtual void onFrameAvailable(const BufferItem& /* item */) { Mutex::Autolock lock(mMutex); mPendingFrames++; mCondition.signal(); diff --git a/libs/gui/tests/IGraphicBufferProducer_test.cpp b/libs/gui/tests/IGraphicBufferProducer_test.cpp index aadfe61..8d5fd8f 100644 --- a/libs/gui/tests/IGraphicBufferProducer_test.cpp +++ b/libs/gui/tests/IGraphicBufferProducer_test.cpp @@ -65,7 +65,7 @@ const sp<Fence> QUEUE_BUFFER_INPUT_FENCE = Fence::NO_FENCE; }; // namespace anonymous struct DummyConsumer : public BnConsumerListener { - virtual void onFrameAvailable() {} + virtual void onFrameAvailable(const BufferItem& /* item */) {} virtual void onBuffersReleased() {} virtual void onSidebandStreamChanged() {} }; diff --git a/libs/gui/tests/StreamSplitter_test.cpp b/libs/gui/tests/StreamSplitter_test.cpp index 32ec90d..4e63a6f 100644 --- a/libs/gui/tests/StreamSplitter_test.cpp +++ b/libs/gui/tests/StreamSplitter_test.cpp @@ -46,7 +46,7 @@ protected: }; struct DummyListener : public BnConsumerListener { - virtual void onFrameAvailable() {} + virtual void onFrameAvailable(const BufferItem& /* item */) {} virtual void onBuffersReleased() {} virtual void onSidebandStreamChanged() {} }; diff --git a/libs/gui/tests/SurfaceTextureGLThreadToGL.h b/libs/gui/tests/SurfaceTextureGLThreadToGL.h index 6410516..14e42ac 100644 --- a/libs/gui/tests/SurfaceTextureGLThreadToGL.h +++ b/libs/gui/tests/SurfaceTextureGLThreadToGL.h @@ -130,7 +130,7 @@ protected: } // This should be called by GLConsumer on the producer thread. - virtual void onFrameAvailable() { + virtual void onFrameAvailable(const BufferItem& /* item */) { Mutex::Autolock lock(mMutex); ALOGV("+onFrameAvailable"); mFrameAvailable = true; |