Merge "Fix PTS handling for buffer replacement" into mnc-dev
This commit is contained in:
commit
09d561dbee
@ -47,7 +47,7 @@ public:
|
|||||||
// returned. The presentation time is in nanoseconds, and the time base
|
// returned. The presentation time is in nanoseconds, and the time base
|
||||||
// is CLOCK_MONOTONIC.
|
// is CLOCK_MONOTONIC.
|
||||||
virtual status_t acquireBuffer(BufferItem* outBuffer,
|
virtual status_t acquireBuffer(BufferItem* outBuffer,
|
||||||
nsecs_t expectedPresent);
|
nsecs_t expectedPresent, uint64_t maxFrameNumber = 0) override;
|
||||||
|
|
||||||
// See IGraphicBufferConsumer::detachBuffer
|
// See IGraphicBufferConsumer::detachBuffer
|
||||||
virtual status_t detachBuffer(int slot);
|
virtual status_t detachBuffer(int slot);
|
||||||
@ -148,9 +148,6 @@ public:
|
|||||||
// Retrieve the sideband buffer stream, if any.
|
// Retrieve the sideband buffer stream, if any.
|
||||||
virtual sp<NativeHandle> getSidebandStream() const;
|
virtual sp<NativeHandle> getSidebandStream() const;
|
||||||
|
|
||||||
// See IGraphicBufferConsumer::setShadowQueueSize
|
|
||||||
virtual void setShadowQueueSize(size_t size);
|
|
||||||
|
|
||||||
// dump our state in a String
|
// dump our state in a String
|
||||||
virtual void dump(String8& result, const char* prefix) const;
|
virtual void dump(String8& result, const char* prefix) const;
|
||||||
|
|
||||||
|
@ -275,12 +275,6 @@ private:
|
|||||||
// buffer as the number of frames that have elapsed since it was last queued
|
// buffer as the number of frames that have elapsed since it was last queued
|
||||||
uint64_t mBufferAge;
|
uint64_t mBufferAge;
|
||||||
|
|
||||||
// mConsumerHasShadowQueue determines if acquireBuffer should be more
|
|
||||||
// cautious about dropping buffers so that it always returns a buffer that
|
|
||||||
// is represented in the consumer's shadow queue.
|
|
||||||
bool mConsumerHasShadowQueue;
|
|
||||||
size_t mConsumerShadowQueueSize;
|
|
||||||
|
|
||||||
}; // class BufferQueueCore
|
}; // class BufferQueueCore
|
||||||
|
|
||||||
} // namespace android
|
} // namespace android
|
||||||
|
@ -152,7 +152,8 @@ protected:
|
|||||||
// initialization that must take place the first time a buffer is assigned
|
// initialization that must take place the first time a buffer is assigned
|
||||||
// to a slot. If it is overridden the derived class's implementation must
|
// to a slot. If it is overridden the derived class's implementation must
|
||||||
// call ConsumerBase::acquireBufferLocked.
|
// call ConsumerBase::acquireBufferLocked.
|
||||||
virtual status_t acquireBufferLocked(BufferItem *item, nsecs_t presentWhen);
|
virtual status_t acquireBufferLocked(BufferItem *item, nsecs_t presentWhen,
|
||||||
|
uint64_t maxFrameNumber = 0);
|
||||||
|
|
||||||
// releaseBufferLocked relinquishes control over a buffer, returning that
|
// releaseBufferLocked relinquishes control over a buffer, returning that
|
||||||
// control to the BufferQueue.
|
// control to the BufferQueue.
|
||||||
|
@ -241,7 +241,8 @@ protected:
|
|||||||
|
|
||||||
// acquireBufferLocked overrides the ConsumerBase method to update the
|
// acquireBufferLocked overrides the ConsumerBase method to update the
|
||||||
// mEglSlots array in addition to the ConsumerBase behavior.
|
// mEglSlots array in addition to the ConsumerBase behavior.
|
||||||
virtual status_t acquireBufferLocked(BufferItem *item, nsecs_t presentWhen);
|
virtual status_t acquireBufferLocked(BufferItem *item, nsecs_t presentWhen,
|
||||||
|
uint64_t maxFrameNumber = 0) override;
|
||||||
|
|
||||||
// releaseBufferLocked overrides the ConsumerBase method to update the
|
// releaseBufferLocked overrides the ConsumerBase method to update the
|
||||||
// mEglSlots array in addition to the ConsumerBase.
|
// mEglSlots array in addition to the ConsumerBase.
|
||||||
|
@ -69,6 +69,12 @@ public:
|
|||||||
// returned. The presentation time is in nanoseconds, and the time base
|
// returned. The presentation time is in nanoseconds, and the time base
|
||||||
// is CLOCK_MONOTONIC.
|
// is CLOCK_MONOTONIC.
|
||||||
//
|
//
|
||||||
|
// If maxFrameNumber is non-zero, it indicates that acquireBuffer should
|
||||||
|
// only return a buffer with a frame number less than or equal to
|
||||||
|
// maxFrameNumber. If no such frame is available (such as when a buffer has
|
||||||
|
// been replaced but the consumer has not received the onFrameReplaced
|
||||||
|
// callback), then PRESENT_LATER will be returned.
|
||||||
|
//
|
||||||
// Return of NO_ERROR means the operation completed as normal.
|
// Return of NO_ERROR means the operation completed as normal.
|
||||||
//
|
//
|
||||||
// Return of a positive value means the operation could not be completed
|
// Return of a positive value means the operation could not be completed
|
||||||
@ -78,7 +84,8 @@ public:
|
|||||||
//
|
//
|
||||||
// Return of a negative value means an error has occurred:
|
// Return of a negative value means an error has occurred:
|
||||||
// * INVALID_OPERATION - too many buffers have been acquired
|
// * INVALID_OPERATION - too many buffers have been acquired
|
||||||
virtual status_t acquireBuffer(BufferItem* buffer, nsecs_t presentWhen) = 0;
|
virtual status_t acquireBuffer(BufferItem* buffer, nsecs_t presentWhen,
|
||||||
|
uint64_t maxFrameNumber = 0) = 0;
|
||||||
|
|
||||||
// detachBuffer attempts to remove all ownership of the buffer in the given
|
// detachBuffer attempts to remove all ownership of the buffer in the given
|
||||||
// slot from the buffer queue. If this call succeeds, the slot will be
|
// slot from the buffer queue. If this call succeeds, the slot will be
|
||||||
@ -248,11 +255,6 @@ public:
|
|||||||
// Retrieve the sideband buffer stream, if any.
|
// Retrieve the sideband buffer stream, if any.
|
||||||
virtual sp<NativeHandle> getSidebandStream() const = 0;
|
virtual sp<NativeHandle> getSidebandStream() const = 0;
|
||||||
|
|
||||||
// setShadowQueueSize notifies the BufferQueue that the consumer is
|
|
||||||
// shadowing its queue and allows it to limit the number of buffers it is
|
|
||||||
// permitted to drop during acquire so as to not get out of sync.
|
|
||||||
virtual void setShadowQueueSize(size_t size) = 0;
|
|
||||||
|
|
||||||
// dump state into a string
|
// dump state into a string
|
||||||
virtual void dump(String8& result, const char* prefix) const = 0;
|
virtual void dump(String8& result, const char* prefix) const = 0;
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@ BufferQueueConsumer::BufferQueueConsumer(const sp<BufferQueueCore>& core) :
|
|||||||
BufferQueueConsumer::~BufferQueueConsumer() {}
|
BufferQueueConsumer::~BufferQueueConsumer() {}
|
||||||
|
|
||||||
status_t BufferQueueConsumer::acquireBuffer(BufferItem* outBuffer,
|
status_t BufferQueueConsumer::acquireBuffer(BufferItem* outBuffer,
|
||||||
nsecs_t expectedPresent) {
|
nsecs_t expectedPresent, uint64_t maxFrameNumber) {
|
||||||
ATRACE_CALL();
|
ATRACE_CALL();
|
||||||
Mutex::Autolock lock(mCore->mMutex);
|
Mutex::Autolock lock(mCore->mMutex);
|
||||||
|
|
||||||
@ -89,17 +89,12 @@ status_t BufferQueueConsumer::acquireBuffer(BufferItem* outBuffer,
|
|||||||
// the timestamps are being auto-generated by Surface. If the app isn't
|
// the timestamps are being auto-generated by Surface. If the app isn't
|
||||||
// generating timestamps explicitly, it probably doesn't want frames to
|
// generating timestamps explicitly, it probably doesn't want frames to
|
||||||
// be discarded based on them.
|
// be discarded based on them.
|
||||||
//
|
|
||||||
// If the consumer is shadowing our queue, we also make sure that we
|
|
||||||
// don't drop so many buffers that the consumer hasn't received the
|
|
||||||
// onFrameAvailable callback for the buffer it acquires. That is, we
|
|
||||||
// want the buffer we return to be in the consumer's shadow queue.
|
|
||||||
size_t droppableBuffers = mCore->mConsumerShadowQueueSize > 1 ?
|
|
||||||
mCore->mConsumerShadowQueueSize - 1 : 0;
|
|
||||||
while (mCore->mQueue.size() > 1 && !mCore->mQueue[0].mIsAutoTimestamp) {
|
while (mCore->mQueue.size() > 1 && !mCore->mQueue[0].mIsAutoTimestamp) {
|
||||||
if (mCore->mConsumerHasShadowQueue && droppableBuffers == 0) {
|
const BufferItem& bufferItem(mCore->mQueue[1]);
|
||||||
BQ_LOGV("acquireBuffer: no droppable buffers in consumer's"
|
|
||||||
" shadow queue, continuing");
|
// If dropping entry[0] would leave us with a buffer that the
|
||||||
|
// consumer is not yet ready for, don't drop it.
|
||||||
|
if (maxFrameNumber && bufferItem.mFrameNumber > maxFrameNumber) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,7 +107,6 @@ status_t BufferQueueConsumer::acquireBuffer(BufferItem* outBuffer,
|
|||||||
//
|
//
|
||||||
// We may want to add an additional criterion: don't drop the
|
// We may want to add an additional criterion: don't drop the
|
||||||
// earlier buffer if entry[1]'s fence hasn't signaled yet.
|
// earlier buffer if entry[1]'s fence hasn't signaled yet.
|
||||||
const BufferItem& bufferItem(mCore->mQueue[1]);
|
|
||||||
nsecs_t desiredPresent = bufferItem.mTimestamp;
|
nsecs_t desiredPresent = bufferItem.mTimestamp;
|
||||||
if (desiredPresent < expectedPresent - MAX_REASONABLE_NSEC ||
|
if (desiredPresent < expectedPresent - MAX_REASONABLE_NSEC ||
|
||||||
desiredPresent > expectedPresent) {
|
desiredPresent > expectedPresent) {
|
||||||
@ -137,18 +131,22 @@ status_t BufferQueueConsumer::acquireBuffer(BufferItem* outBuffer,
|
|||||||
}
|
}
|
||||||
mCore->mQueue.erase(front);
|
mCore->mQueue.erase(front);
|
||||||
front = mCore->mQueue.begin();
|
front = mCore->mQueue.begin();
|
||||||
--droppableBuffers;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// See if the front buffer is due
|
// See if the front buffer is ready to be acquired
|
||||||
nsecs_t desiredPresent = front->mTimestamp;
|
nsecs_t desiredPresent = front->mTimestamp;
|
||||||
if (desiredPresent > expectedPresent &&
|
bool bufferIsDue = desiredPresent <= expectedPresent ||
|
||||||
desiredPresent < expectedPresent + MAX_REASONABLE_NSEC) {
|
desiredPresent > expectedPresent + MAX_REASONABLE_NSEC;
|
||||||
|
bool consumerIsReady = maxFrameNumber > 0 ?
|
||||||
|
front->mFrameNumber <= maxFrameNumber : true;
|
||||||
|
if (!bufferIsDue || !consumerIsReady) {
|
||||||
BQ_LOGV("acquireBuffer: defer desire=%" PRId64 " expect=%" PRId64
|
BQ_LOGV("acquireBuffer: defer desire=%" PRId64 " expect=%" PRId64
|
||||||
" (%" PRId64 ") now=%" PRId64,
|
" (%" PRId64 ") now=%" PRId64 " frame=%" PRIu64
|
||||||
|
" consumer=%" PRIu64,
|
||||||
desiredPresent, expectedPresent,
|
desiredPresent, expectedPresent,
|
||||||
desiredPresent - expectedPresent,
|
desiredPresent - expectedPresent,
|
||||||
systemTime(CLOCK_MONOTONIC));
|
systemTime(CLOCK_MONOTONIC),
|
||||||
|
front->mFrameNumber, maxFrameNumber);
|
||||||
return PRESENT_LATER;
|
return PRESENT_LATER;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -553,14 +551,6 @@ sp<NativeHandle> BufferQueueConsumer::getSidebandStream() const {
|
|||||||
return mCore->mSidebandStream;
|
return mCore->mSidebandStream;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BufferQueueConsumer::setShadowQueueSize(size_t size) {
|
|
||||||
ATRACE_CALL();
|
|
||||||
BQ_LOGV("setShadowQueueSize: %zu", size);
|
|
||||||
Mutex::Autolock lock(mCore->mMutex);
|
|
||||||
mCore->mConsumerHasShadowQueue = true;
|
|
||||||
mCore->mConsumerShadowQueueSize = size;
|
|
||||||
}
|
|
||||||
|
|
||||||
void BufferQueueConsumer::dump(String8& result, const char* prefix) const {
|
void BufferQueueConsumer::dump(String8& result, const char* prefix) const {
|
||||||
mCore->dump(result, prefix);
|
mCore->dump(result, prefix);
|
||||||
}
|
}
|
||||||
|
@ -71,9 +71,7 @@ BufferQueueCore::BufferQueueCore(const sp<IGraphicBufferAlloc>& allocator) :
|
|||||||
mIsAllocating(false),
|
mIsAllocating(false),
|
||||||
mIsAllocatingCondition(),
|
mIsAllocatingCondition(),
|
||||||
mAllowAllocation(true),
|
mAllowAllocation(true),
|
||||||
mBufferAge(0),
|
mBufferAge(0)
|
||||||
mConsumerHasShadowQueue(false),
|
|
||||||
mConsumerShadowQueueSize(0)
|
|
||||||
{
|
{
|
||||||
if (allocator == NULL) {
|
if (allocator == NULL) {
|
||||||
sp<ISurfaceComposer> composer(ComposerService::getComposerService());
|
sp<ISurfaceComposer> composer(ComposerService::getComposerService());
|
||||||
|
@ -211,8 +211,8 @@ void ConsumerBase::dumpLocked(String8& result, const char* prefix) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
status_t ConsumerBase::acquireBufferLocked(BufferItem *item,
|
status_t ConsumerBase::acquireBufferLocked(BufferItem *item,
|
||||||
nsecs_t presentWhen) {
|
nsecs_t presentWhen, uint64_t maxFrameNumber) {
|
||||||
status_t err = mConsumer->acquireBuffer(item, presentWhen);
|
status_t err = mConsumer->acquireBuffer(item, presentWhen, maxFrameNumber);
|
||||||
if (err != NO_ERROR) {
|
if (err != NO_ERROR) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -344,8 +344,9 @@ sp<GraphicBuffer> GLConsumer::getDebugTexImageBuffer() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
status_t GLConsumer::acquireBufferLocked(BufferItem *item,
|
status_t GLConsumer::acquireBufferLocked(BufferItem *item,
|
||||||
nsecs_t presentWhen) {
|
nsecs_t presentWhen, uint64_t maxFrameNumber) {
|
||||||
status_t err = ConsumerBase::acquireBufferLocked(item, presentWhen);
|
status_t err = ConsumerBase::acquireBufferLocked(item, presentWhen,
|
||||||
|
maxFrameNumber);
|
||||||
if (err != NO_ERROR) {
|
if (err != NO_ERROR) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -52,7 +52,6 @@ enum {
|
|||||||
SET_CONSUMER_USAGE_BITS,
|
SET_CONSUMER_USAGE_BITS,
|
||||||
SET_TRANSFORM_HINT,
|
SET_TRANSFORM_HINT,
|
||||||
GET_SIDEBAND_STREAM,
|
GET_SIDEBAND_STREAM,
|
||||||
SET_SHADOW_QUEUE_SIZE,
|
|
||||||
DUMP,
|
DUMP,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -67,10 +66,12 @@ public:
|
|||||||
|
|
||||||
virtual ~BpGraphicBufferConsumer();
|
virtual ~BpGraphicBufferConsumer();
|
||||||
|
|
||||||
virtual status_t acquireBuffer(BufferItem *buffer, nsecs_t presentWhen) {
|
virtual status_t acquireBuffer(BufferItem *buffer, nsecs_t presentWhen,
|
||||||
|
uint64_t maxFrameNumber) {
|
||||||
Parcel data, reply;
|
Parcel data, reply;
|
||||||
data.writeInterfaceToken(IGraphicBufferConsumer::getInterfaceDescriptor());
|
data.writeInterfaceToken(IGraphicBufferConsumer::getInterfaceDescriptor());
|
||||||
data.writeInt64(presentWhen);
|
data.writeInt64(presentWhen);
|
||||||
|
data.writeUint64(maxFrameNumber);
|
||||||
status_t result = remote()->transact(ACQUIRE_BUFFER, data, &reply);
|
status_t result = remote()->transact(ACQUIRE_BUFFER, data, &reply);
|
||||||
if (result != NO_ERROR) {
|
if (result != NO_ERROR) {
|
||||||
return result;
|
return result;
|
||||||
@ -270,17 +271,6 @@ public:
|
|||||||
return stream;
|
return stream;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void setShadowQueueSize(size_t size) {
|
|
||||||
Parcel data, reply;
|
|
||||||
data.writeInterfaceToken(IGraphicBufferConsumer::getInterfaceDescriptor());
|
|
||||||
data.writeInt64(static_cast<int64_t>(size));
|
|
||||||
status_t result = remote()->transact(SET_SHADOW_QUEUE_SIZE, data, &reply);
|
|
||||||
if (result != NO_ERROR) {
|
|
||||||
ALOGE("setShadowQueueSize failed (%d)", result);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void dump(String8& result, const char* prefix) const {
|
virtual void dump(String8& result, const char* prefix) const {
|
||||||
Parcel data, reply;
|
Parcel data, reply;
|
||||||
data.writeInterfaceToken(IGraphicBufferConsumer::getInterfaceDescriptor());
|
data.writeInterfaceToken(IGraphicBufferConsumer::getInterfaceDescriptor());
|
||||||
@ -307,7 +297,8 @@ status_t BnGraphicBufferConsumer::onTransact(
|
|||||||
CHECK_INTERFACE(IGraphicBufferConsumer, data, reply);
|
CHECK_INTERFACE(IGraphicBufferConsumer, data, reply);
|
||||||
BufferItem item;
|
BufferItem item;
|
||||||
int64_t presentWhen = data.readInt64();
|
int64_t presentWhen = data.readInt64();
|
||||||
status_t result = acquireBuffer(&item, presentWhen);
|
uint64_t maxFrameNumber = data.readUint64();
|
||||||
|
status_t result = acquireBuffer(&item, presentWhen, maxFrameNumber);
|
||||||
status_t err = reply->write(item);
|
status_t err = reply->write(item);
|
||||||
if (err) return err;
|
if (err) return err;
|
||||||
reply->writeInt32(result);
|
reply->writeInt32(result);
|
||||||
@ -435,12 +426,6 @@ status_t BnGraphicBufferConsumer::onTransact(
|
|||||||
}
|
}
|
||||||
return NO_ERROR;
|
return NO_ERROR;
|
||||||
}
|
}
|
||||||
case SET_SHADOW_QUEUE_SIZE: {
|
|
||||||
CHECK_INTERFACE(IGraphicBufferConsumer, data, reply);
|
|
||||||
size_t size = static_cast<size_t>(data.readInt64());
|
|
||||||
setShadowQueueSize(size);
|
|
||||||
return NO_ERROR;
|
|
||||||
}
|
|
||||||
case DUMP: {
|
case DUMP: {
|
||||||
CHECK_INTERFACE(IGraphicBufferConsumer, data, reply);
|
CHECK_INTERFACE(IGraphicBufferConsumer, data, reply);
|
||||||
String8 result = data.readString8();
|
String8 result = data.readString8();
|
||||||
|
@ -80,7 +80,11 @@ Layer::Layer(SurfaceFlinger* flinger, const sp<Client>& client,
|
|||||||
mProtectedByApp(false),
|
mProtectedByApp(false),
|
||||||
mHasSurface(false),
|
mHasSurface(false),
|
||||||
mClientRef(client),
|
mClientRef(client),
|
||||||
mPotentialCursor(false)
|
mPotentialCursor(false),
|
||||||
|
mQueueItemLock(),
|
||||||
|
mQueueItemCondition(),
|
||||||
|
mQueueItems(),
|
||||||
|
mLastFrameNumberReceived(0)
|
||||||
{
|
{
|
||||||
mCurrentCrop.makeInvalid();
|
mCurrentCrop.makeInvalid();
|
||||||
mFlinger->getRenderEngine().genTextures(1, &mTextureName);
|
mFlinger->getRenderEngine().genTextures(1, &mTextureName);
|
||||||
@ -127,10 +131,6 @@ void Layer::onFirstRef() {
|
|||||||
mSurfaceFlingerConsumer->setContentsChangedListener(this);
|
mSurfaceFlingerConsumer->setContentsChangedListener(this);
|
||||||
mSurfaceFlingerConsumer->setName(mName);
|
mSurfaceFlingerConsumer->setName(mName);
|
||||||
|
|
||||||
// Set the shadow queue size to 0 to notify the BufferQueue that we are
|
|
||||||
// shadowing it
|
|
||||||
mSurfaceFlingerConsumer->setShadowQueueSize(0);
|
|
||||||
|
|
||||||
#ifdef TARGET_DISABLE_TRIPLE_BUFFERING
|
#ifdef TARGET_DISABLE_TRIPLE_BUFFERING
|
||||||
#warning "disabling triple buffering"
|
#warning "disabling triple buffering"
|
||||||
mSurfaceFlingerConsumer->setDefaultMaxBufferCount(2);
|
mSurfaceFlingerConsumer->setDefaultMaxBufferCount(2);
|
||||||
@ -167,9 +167,28 @@ void Layer::onFrameAvailable(const BufferItem& item) {
|
|||||||
// Add this buffer from our internal queue tracker
|
// Add this buffer from our internal queue tracker
|
||||||
{ // Autolock scope
|
{ // Autolock scope
|
||||||
Mutex::Autolock lock(mQueueItemLock);
|
Mutex::Autolock lock(mQueueItemLock);
|
||||||
|
|
||||||
|
// Reset the frame number tracker when we receive the first buffer after
|
||||||
|
// a frame number reset
|
||||||
|
if (item.mFrameNumber == 1) {
|
||||||
|
mLastFrameNumberReceived = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure that callbacks are handled in order
|
||||||
|
while (item.mFrameNumber != mLastFrameNumberReceived + 1) {
|
||||||
|
status_t result = mQueueItemCondition.waitRelative(mQueueItemLock,
|
||||||
|
ms2ns(500));
|
||||||
|
if (result != NO_ERROR) {
|
||||||
|
ALOGE("[%s] Timed out waiting on callback", mName.string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mQueueItems.push_back(item);
|
mQueueItems.push_back(item);
|
||||||
mSurfaceFlingerConsumer->setShadowQueueSize(mQueueItems.size());
|
|
||||||
android_atomic_inc(&mQueuedFrames);
|
android_atomic_inc(&mQueuedFrames);
|
||||||
|
|
||||||
|
// Wake up any pending callbacks
|
||||||
|
mLastFrameNumberReceived = item.mFrameNumber;
|
||||||
|
mQueueItemCondition.broadcast();
|
||||||
}
|
}
|
||||||
|
|
||||||
mFlinger->signalLayerUpdate();
|
mFlinger->signalLayerUpdate();
|
||||||
@ -177,11 +196,25 @@ void Layer::onFrameAvailable(const BufferItem& item) {
|
|||||||
|
|
||||||
void Layer::onFrameReplaced(const BufferItem& item) {
|
void Layer::onFrameReplaced(const BufferItem& item) {
|
||||||
Mutex::Autolock lock(mQueueItemLock);
|
Mutex::Autolock lock(mQueueItemLock);
|
||||||
|
|
||||||
|
// Ensure that callbacks are handled in order
|
||||||
|
while (item.mFrameNumber != mLastFrameNumberReceived + 1) {
|
||||||
|
status_t result = mQueueItemCondition.waitRelative(mQueueItemLock,
|
||||||
|
ms2ns(500));
|
||||||
|
if (result != NO_ERROR) {
|
||||||
|
ALOGE("[%s] Timed out waiting on callback", mName.string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (mQueueItems.empty()) {
|
if (mQueueItems.empty()) {
|
||||||
ALOGE("Can't replace a frame on an empty queue");
|
ALOGE("Can't replace a frame on an empty queue");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mQueueItems.editItemAt(0) = item;
|
mQueueItems.editItemAt(0) = item;
|
||||||
|
|
||||||
|
// Wake up any pending callbacks
|
||||||
|
mLastFrameNumberReceived = item.mFrameNumber;
|
||||||
|
mQueueItemCondition.broadcast();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Layer::onSidebandStreamChanged() {
|
void Layer::onSidebandStreamChanged() {
|
||||||
@ -1261,8 +1294,14 @@ Region Layer::latchBuffer(bool& recomputeVisibleRegions)
|
|||||||
Reject r(mDrawingState, getCurrentState(), recomputeVisibleRegions,
|
Reject r(mDrawingState, getCurrentState(), recomputeVisibleRegions,
|
||||||
getProducerStickyTransform() != 0);
|
getProducerStickyTransform() != 0);
|
||||||
|
|
||||||
|
uint64_t maxFrameNumber = 0;
|
||||||
|
{
|
||||||
|
Mutex::Autolock lock(mQueueItemLock);
|
||||||
|
maxFrameNumber = mLastFrameNumberReceived;
|
||||||
|
}
|
||||||
|
|
||||||
status_t updateResult = mSurfaceFlingerConsumer->updateTexImage(&r,
|
status_t updateResult = mSurfaceFlingerConsumer->updateTexImage(&r,
|
||||||
mFlinger->mPrimaryDispSync);
|
mFlinger->mPrimaryDispSync, maxFrameNumber);
|
||||||
if (updateResult == BufferQueue::PRESENT_LATER) {
|
if (updateResult == BufferQueue::PRESENT_LATER) {
|
||||||
// Producer doesn't want buffer to be displayed yet. Signal a
|
// Producer doesn't want buffer to be displayed yet. Signal a
|
||||||
// layer update so we check again at the next opportunity.
|
// layer update so we check again at the next opportunity.
|
||||||
@ -1272,12 +1311,7 @@ Region Layer::latchBuffer(bool& recomputeVisibleRegions)
|
|||||||
// If the buffer has been rejected, remove it from the shadow queue
|
// If the buffer has been rejected, remove it from the shadow queue
|
||||||
// and return early
|
// and return early
|
||||||
Mutex::Autolock lock(mQueueItemLock);
|
Mutex::Autolock lock(mQueueItemLock);
|
||||||
|
|
||||||
// Update the BufferQueue with the new shadow queue size after
|
|
||||||
// dropping this item
|
|
||||||
mQueueItems.removeAt(0);
|
mQueueItems.removeAt(0);
|
||||||
mSurfaceFlingerConsumer->setShadowQueueSize(mQueueItems.size());
|
|
||||||
|
|
||||||
android_atomic_dec(&mQueuedFrames);
|
android_atomic_dec(&mQueuedFrames);
|
||||||
return outDirtyRegion;
|
return outDirtyRegion;
|
||||||
}
|
}
|
||||||
@ -1294,10 +1328,7 @@ Region Layer::latchBuffer(bool& recomputeVisibleRegions)
|
|||||||
android_atomic_dec(&mQueuedFrames);
|
android_atomic_dec(&mQueuedFrames);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the BufferQueue with our new shadow queue size, since we
|
|
||||||
// have removed at least one item
|
|
||||||
mQueueItems.removeAt(0);
|
mQueueItems.removeAt(0);
|
||||||
mSurfaceFlingerConsumer->setShadowQueueSize(mQueueItems.size());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -416,7 +416,9 @@ private:
|
|||||||
|
|
||||||
// Local copy of the queued contents of the incoming BufferQueue
|
// Local copy of the queued contents of the incoming BufferQueue
|
||||||
mutable Mutex mQueueItemLock;
|
mutable Mutex mQueueItemLock;
|
||||||
|
Condition mQueueItemCondition;
|
||||||
Vector<BufferItem> mQueueItems;
|
Vector<BufferItem> mQueueItems;
|
||||||
|
uint64_t mLastFrameNumberReceived;
|
||||||
};
|
};
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
@ -32,7 +32,7 @@ namespace android {
|
|||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
status_t SurfaceFlingerConsumer::updateTexImage(BufferRejecter* rejecter,
|
status_t SurfaceFlingerConsumer::updateTexImage(BufferRejecter* rejecter,
|
||||||
const DispSync& dispSync)
|
const DispSync& dispSync, uint64_t maxFrameNumber)
|
||||||
{
|
{
|
||||||
ATRACE_CALL();
|
ATRACE_CALL();
|
||||||
ALOGV("updateTexImage");
|
ALOGV("updateTexImage");
|
||||||
@ -54,7 +54,8 @@ status_t SurfaceFlingerConsumer::updateTexImage(BufferRejecter* rejecter,
|
|||||||
// Acquire the next buffer.
|
// Acquire the next buffer.
|
||||||
// In asynchronous mode the list is guaranteed to be one buffer
|
// In asynchronous mode the list is guaranteed to be one buffer
|
||||||
// deep, while in synchronous mode we use the oldest buffer.
|
// deep, while in synchronous mode we use the oldest buffer.
|
||||||
err = acquireBufferLocked(&item, computeExpectedPresent(dispSync));
|
err = acquireBufferLocked(&item, computeExpectedPresent(dispSync),
|
||||||
|
maxFrameNumber);
|
||||||
if (err != NO_ERROR) {
|
if (err != NO_ERROR) {
|
||||||
if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
|
if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
|
||||||
err = NO_ERROR;
|
err = NO_ERROR;
|
||||||
@ -104,8 +105,9 @@ status_t SurfaceFlingerConsumer::bindTextureImage()
|
|||||||
}
|
}
|
||||||
|
|
||||||
status_t SurfaceFlingerConsumer::acquireBufferLocked(BufferItem* item,
|
status_t SurfaceFlingerConsumer::acquireBufferLocked(BufferItem* item,
|
||||||
nsecs_t presentWhen) {
|
nsecs_t presentWhen, uint64_t maxFrameNumber) {
|
||||||
status_t result = GLConsumer::acquireBufferLocked(item, presentWhen);
|
status_t result = GLConsumer::acquireBufferLocked(item, presentWhen,
|
||||||
|
maxFrameNumber);
|
||||||
if (result == NO_ERROR) {
|
if (result == NO_ERROR) {
|
||||||
mTransformToDisplayInverse = item->mTransformToDisplayInverse;
|
mTransformToDisplayInverse = item->mTransformToDisplayInverse;
|
||||||
mSurfaceDamage = item->mSurfaceDamage;
|
mSurfaceDamage = item->mSurfaceDamage;
|
||||||
@ -125,10 +127,6 @@ sp<NativeHandle> SurfaceFlingerConsumer::getSidebandStream() const {
|
|||||||
return mConsumer->getSidebandStream();
|
return mConsumer->getSidebandStream();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SurfaceFlingerConsumer::setShadowQueueSize(size_t size) {
|
|
||||||
mConsumer->setShadowQueueSize(size);
|
|
||||||
}
|
|
||||||
|
|
||||||
// We need to determine the time when a buffer acquired now will be
|
// We need to determine the time when a buffer acquired now will be
|
||||||
// displayed. This can be calculated:
|
// displayed. This can be calculated:
|
||||||
// time when previous buffer's actual-present fence was signaled
|
// time when previous buffer's actual-present fence was signaled
|
||||||
|
@ -49,13 +49,15 @@ public:
|
|||||||
virtual ~BufferRejecter() { }
|
virtual ~BufferRejecter() { }
|
||||||
};
|
};
|
||||||
|
|
||||||
virtual status_t acquireBufferLocked(BufferItem *item, nsecs_t presentWhen);
|
virtual status_t acquireBufferLocked(BufferItem *item, nsecs_t presentWhen,
|
||||||
|
uint64_t maxFrameNumber = 0) override;
|
||||||
|
|
||||||
// This version of updateTexImage() takes a functor that may be used to
|
// This version of updateTexImage() takes a functor that may be used to
|
||||||
// reject the newly acquired buffer. Unlike the GLConsumer version,
|
// reject the newly acquired buffer. Unlike the GLConsumer version,
|
||||||
// this does not guarantee that the buffer has been bound to the GL
|
// this does not guarantee that the buffer has been bound to the GL
|
||||||
// texture.
|
// texture.
|
||||||
status_t updateTexImage(BufferRejecter* rejecter, const DispSync& dispSync);
|
status_t updateTexImage(BufferRejecter* rejecter, const DispSync& dispSync,
|
||||||
|
uint64_t maxFrameNumber = 0);
|
||||||
|
|
||||||
// See GLConsumer::bindTextureImageLocked().
|
// See GLConsumer::bindTextureImageLocked().
|
||||||
status_t bindTextureImage();
|
status_t bindTextureImage();
|
||||||
@ -70,9 +72,6 @@ public:
|
|||||||
|
|
||||||
sp<NativeHandle> getSidebandStream() const;
|
sp<NativeHandle> getSidebandStream() const;
|
||||||
|
|
||||||
// See IGraphicBufferConsumer::setShadowQueueSize
|
|
||||||
void setShadowQueueSize(size_t size);
|
|
||||||
|
|
||||||
nsecs_t computeExpectedPresent(const DispSync& dispSync);
|
nsecs_t computeExpectedPresent(const DispSync& dispSync);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Loading…
Reference in New Issue
Block a user