// ----------------------------------------------------------------------------
bool Layer::shouldPresentNow(const DispSync& dispSync) const {
- if (mSidebandStreamChanged) {
+ if (mSidebandStreamChanged || mSingleBufferMode) {
return true;
}
bool Layer::onPreComposition() {
mRefreshPending = false;
- return mQueuedFrames > 0 || mSidebandStreamChanged;
+ return mQueuedFrames > 0 || mSidebandStreamChanged || mSingleBufferMode;
}
void Layer::onPostComposition() {
}
Region outDirtyRegion;
- if (mQueuedFrames > 0) {
+ if (mQueuedFrames > 0 || mSingleBufferMode) {
// if we've already called updateTexImage() without going through
// a composition step, we have to skip this layer at this point
}
}
+ // This boolean is used to make sure that SurfaceFlinger's shadow copy
+ // of the buffer queue isn't modified when the buffer queue is returning
+ // BufferItem's that weren't actually queued. This can happen in single
+ // buffer mode.
+ bool queuedBuffer = false;
status_t updateResult = mSurfaceFlingerConsumer->updateTexImage(&r,
- mFlinger->mPrimaryDispSync, maxFrameNumber);
+ mFlinger->mPrimaryDispSync, &mSingleBufferMode, &queuedBuffer,
+ maxFrameNumber);
if (updateResult == BufferQueue::PRESENT_LATER) {
// Producer doesn't want buffer to be displayed yet. Signal a
// layer update so we check again at the next opportunity.
} else if (updateResult == SurfaceFlingerConsumer::BUFFER_REJECTED) {
// If the buffer has been rejected, remove it from the shadow queue
// and return early
- Mutex::Autolock lock(mQueueItemLock);
- mQueueItems.removeAt(0);
- android_atomic_dec(&mQueuedFrames);
+ if (queuedBuffer) {
+ Mutex::Autolock lock(mQueueItemLock);
+ mQueueItems.removeAt(0);
+ android_atomic_dec(&mQueuedFrames);
+ }
return outDirtyRegion;
} else if (updateResult != NO_ERROR || mUpdateTexImageFailed) {
// This can occur if something goes wrong when trying to create the
// EGLImage for this buffer. If this happens, the buffer has already
// been released, so we need to clean up the queue and bug out
// early.
- {
+ if (queuedBuffer) {
Mutex::Autolock lock(mQueueItemLock);
mQueueItems.clear();
android_atomic_and(0, &mQueuedFrames);
return outDirtyRegion;
}
- { // Autolock scope
+ if (queuedBuffer) {
+ // Autolock scope
auto currentFrameNumber = mSurfaceFlingerConsumer->getFrameNumber();
Mutex::Autolock lock(mQueueItemLock);
// Decrement the queued-frames count. Signal another event if we
// have more frames pending.
- if (android_atomic_dec(&mQueuedFrames) > 1) {
+ if ((queuedBuffer && android_atomic_dec(&mQueuedFrames) > 1)
+ || mSingleBufferMode) {
mFlinger->signalLayerUpdate();
}
/*
* Returns if a frame is queued.
*/
- bool hasQueuedFrame() const { return mQueuedFrames > 0 || mSidebandStreamChanged; }
+ bool hasQueuedFrame() const { return mQueuedFrames > 0 ||
+ mSidebandStreamChanged || mSingleBufferMode; }
// -----------------------------------------------------------------------
Vector<BufferItem> mQueueItems;
uint64_t mLastFrameNumberReceived;
bool mUpdateTexImageFailed; // This is only modified from the main thread
+
+ bool mSingleBufferMode;
};
// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------
status_t SurfaceFlingerConsumer::updateTexImage(BufferRejecter* rejecter,
- const DispSync& dispSync, uint64_t maxFrameNumber)
+ const DispSync& dispSync, bool* singleBufferMode, bool* queuedBuffer,
+ uint64_t maxFrameNumber)
{
ATRACE_CALL();
ALOGV("updateTexImage");
return err;
}
-
// We call the rejecter here, in case the caller has a reason to
// not accept this buffer. This is used by SurfaceFlinger to
// reject buffers which have the wrong size
return BUFFER_REJECTED;
}
+ if (singleBufferMode) {
+ *singleBufferMode = item.mSingleBufferMode;
+ }
+
+ if (queuedBuffer) {
+ *queuedBuffer = item.mQueuedBuffer;
+ }
+
// Release the previous buffer.
err = updateAndReleaseLocked(item);
if (err != NO_ERROR) {