summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrian Lindahl <blindahl@google.com>2023-03-13 19:09:21 +0000
committerAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2023-03-13 19:09:21 +0000
commit0bb30c48086c3a17816f090c6fe0c73f930a0773 (patch)
tree2518235464762601c025f5a1dbb5be3a80ec8841
parent60cd806a7aa2d813ac7a71cbd1a90031c281fbd8 (diff)
parent1427779de67824e59ee83963e9c19e29489ca347 (diff)
downloadnative-0bb30c48086c3a17816f090c6fe0c73f930a0773.tar.gz
Merge "Increase frame history size when SF buffer queue size changes" am: 1427779de6
Original change: https://android-review.googlesource.com/c/platform/frameworks/native/+/2474466 Change-Id: I5dc652c802d8f882cdb354090bd742f49d0c5383 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
-rw-r--r--libs/gui/BLASTBufferQueue.cpp45
-rw-r--r--libs/gui/BufferQueueProducer.cpp9
-rw-r--r--libs/gui/FrameTimestamps.cpp115
-rw-r--r--libs/gui/bufferqueue/1.0/Conversion.cpp15
-rw-r--r--libs/gui/bufferqueue/1.0/H2BGraphicBufferProducer.cpp5
-rw-r--r--libs/gui/include/gui/BLASTBufferQueue.h5
-rw-r--r--libs/gui/include/gui/BufferQueueProducer.h5
-rw-r--r--libs/gui/include/gui/FrameTimestamps.h15
8 files changed, 187 insertions, 27 deletions
diff --git a/libs/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp
index dd464943ed..97c467053e 100644
--- a/libs/gui/BLASTBufferQueue.cpp
+++ b/libs/gui/BLASTBufferQueue.cpp
@@ -132,6 +132,11 @@ void BLASTBufferItemConsumer::onSidebandStreamChanged() {
}
}
+void BLASTBufferItemConsumer::resizeFrameEventHistory(size_t newSize) {
+ Mutex::Autolock lock(mMutex);
+ mFrameEventHistory.resize(newSize);
+}
+
BLASTBufferQueue::BLASTBufferQueue(const std::string& name, bool updateDestinationFrame)
: mSurfaceControl(nullptr),
mSize(1, 1),
@@ -1039,8 +1044,9 @@ public:
// can be non-blocking when the producer is in the client process.
class BBQBufferQueueProducer : public BufferQueueProducer {
public:
- BBQBufferQueueProducer(const sp<BufferQueueCore>& core)
- : BufferQueueProducer(core, false /* consumerIsSurfaceFlinger*/) {}
+ BBQBufferQueueProducer(const sp<BufferQueueCore>& core, wp<BLASTBufferQueue> bbq)
+ : BufferQueueProducer(core, false /* consumerIsSurfaceFlinger*/),
+ mBLASTBufferQueue(std::move(bbq)) {}
status_t connect(const sp<IProducerListener>& listener, int api, bool producerControlledByApp,
QueueBufferOutput* output) override {
@@ -1052,6 +1058,26 @@ public:
producerControlledByApp, output);
}
+ // We want to resize the frame history when changing the size of the buffer queue
+ status_t setMaxDequeuedBufferCount(int maxDequeuedBufferCount) override {
+ int maxBufferCount;
+ status_t status = BufferQueueProducer::setMaxDequeuedBufferCount(maxDequeuedBufferCount,
+ &maxBufferCount);
+ // if we can't determine the max buffer count, then just skip growing the history size
+ if (status == OK) {
+ size_t newFrameHistorySize = maxBufferCount + 2; // +2 because triple buffer rendering
+ // optimize away resizing the frame history unless it will grow
+ if (newFrameHistorySize > FrameEventHistory::INITIAL_MAX_FRAME_HISTORY) {
+ sp<BLASTBufferQueue> bbq = mBLASTBufferQueue.promote();
+ if (bbq != nullptr) {
+ ALOGV("increasing frame history size to %zu", newFrameHistorySize);
+ bbq->resizeFrameEventHistory(newFrameHistorySize);
+ }
+ }
+ }
+ return status;
+ }
+
int query(int what, int* value) override {
if (what == NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER) {
*value = 1;
@@ -1059,6 +1085,9 @@ public:
}
return BufferQueueProducer::query(what, value);
}
+
+private:
+ const wp<BLASTBufferQueue> mBLASTBufferQueue;
};
// Similar to BufferQueue::createBufferQueue but creates an adapter specific bufferqueue producer.
@@ -1073,7 +1102,7 @@ void BLASTBufferQueue::createBufferQueue(sp<IGraphicBufferProducer>* outProducer
sp<BufferQueueCore> core(new BufferQueueCore());
LOG_ALWAYS_FATAL_IF(core == nullptr, "BLASTBufferQueue: failed to create BufferQueueCore");
- sp<IGraphicBufferProducer> producer(new BBQBufferQueueProducer(core));
+ sp<IGraphicBufferProducer> producer(new BBQBufferQueueProducer(core, this));
LOG_ALWAYS_FATAL_IF(producer == nullptr,
"BLASTBufferQueue: failed to create BBQBufferQueueProducer");
@@ -1086,6 +1115,16 @@ void BLASTBufferQueue::createBufferQueue(sp<IGraphicBufferProducer>* outProducer
*outConsumer = consumer;
}
+void BLASTBufferQueue::resizeFrameEventHistory(size_t newSize) {
+ // This can be null during creation of the buffer queue, but resizing won't do anything at that
+ // point in time, so just ignore. This can go away once the class relationships and lifetimes of
+ // objects are cleaned up with a major refactor of BufferQueue as a whole.
+ if (mBufferItemConsumer != nullptr) {
+ std::unique_lock _lock{mMutex};
+ mBufferItemConsumer->resizeFrameEventHistory(newSize);
+ }
+}
+
PixelFormat BLASTBufferQueue::convertBufferFormat(PixelFormat& format) {
PixelFormat convertedFormat = format;
switch (format) {
diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp
index 5fe5e71db9..9eb1a9f526 100644
--- a/libs/gui/BufferQueueProducer.cpp
+++ b/libs/gui/BufferQueueProducer.cpp
@@ -119,6 +119,12 @@ status_t BufferQueueProducer::requestBuffer(int slot, sp<GraphicBuffer>* buf) {
status_t BufferQueueProducer::setMaxDequeuedBufferCount(
int maxDequeuedBuffers) {
+ int maxBufferCount;
+ return setMaxDequeuedBufferCount(maxDequeuedBuffers, &maxBufferCount);
+}
+
+status_t BufferQueueProducer::setMaxDequeuedBufferCount(int maxDequeuedBuffers,
+ int* maxBufferCount) {
ATRACE_CALL();
BQ_LOGV("setMaxDequeuedBufferCount: maxDequeuedBuffers = %d",
maxDequeuedBuffers);
@@ -134,6 +140,8 @@ status_t BufferQueueProducer::setMaxDequeuedBufferCount(
return NO_INIT;
}
+ *maxBufferCount = mCore->getMaxBufferCountLocked();
+
if (maxDequeuedBuffers == mCore->mMaxDequeuedBufferCount) {
return NO_ERROR;
}
@@ -183,6 +191,7 @@ status_t BufferQueueProducer::setMaxDequeuedBufferCount(
return BAD_VALUE;
}
mCore->mMaxDequeuedBufferCount = maxDequeuedBuffers;
+ *maxBufferCount = mCore->getMaxBufferCountLocked();
VALIDATE_CONSISTENCY();
if (delta < 0) {
listener = mCore->mConsumerListener;
diff --git a/libs/gui/FrameTimestamps.cpp b/libs/gui/FrameTimestamps.cpp
index e2ea3f9ab1..f3eb4e83aa 100644
--- a/libs/gui/FrameTimestamps.cpp
+++ b/libs/gui/FrameTimestamps.cpp
@@ -168,10 +168,11 @@ struct FrameNumberEqual {
} // namespace
-const size_t FrameEventHistory::MAX_FRAME_HISTORY =
+const size_t FrameEventHistory::INITIAL_MAX_FRAME_HISTORY =
sysprop::LibGuiProperties::frame_event_history_size().value_or(8);
-FrameEventHistory::FrameEventHistory() : mFrames(std::vector<FrameEvents>(MAX_FRAME_HISTORY)) {}
+FrameEventHistory::FrameEventHistory()
+ : mFrames(std::vector<FrameEvents>(INITIAL_MAX_FRAME_HISTORY)) {}
FrameEventHistory::~FrameEventHistory() = default;
@@ -227,7 +228,6 @@ void FrameEventHistory::dump(std::string& outString) const {
}
}
-
// ============================================================================
// ProducerFrameEventHistory
// ============================================================================
@@ -273,6 +273,13 @@ void ProducerFrameEventHistory::applyDelta(
const FrameEventHistoryDelta& delta) {
mCompositorTiming = delta.mCompositorTiming;
+ // Deltas should have enough reserved capacity for the consumer-side, therefore if there's a
+ // different capacity, we re-sized on the consumer side and now need to resize on the producer
+ // side.
+ if (delta.mDeltas.capacity() > mFrames.capacity()) {
+ resize(delta.mDeltas.capacity());
+ }
+
for (auto& d : delta.mDeltas) {
// Avoid out-of-bounds access.
if (CC_UNLIKELY(d.mIndex >= mFrames.size())) {
@@ -349,13 +356,48 @@ std::shared_ptr<FenceTime> ProducerFrameEventHistory::createFenceTime(
return std::make_shared<FenceTime>(fence);
}
+void ProducerFrameEventHistory::resize(size_t newSize) {
+ // we don't want to drop events by resizing too small, so don't resize in the negative direction
+ if (newSize <= mFrames.size()) {
+ return;
+ }
+
+ // This algorithm for resizing needs to be the same as ConsumerFrameEventHistory::resize,
+ // because the indexes need to match when communicating the FrameEventDeltas.
+
+ // We need to find the oldest frame, because that frame needs to move to index 0 in the new
+ // frame history.
+ size_t oldestFrameIndex = 0;
+ size_t oldestFrameNumber = INT32_MAX;
+ for (size_t i = 0; i < mFrames.size(); ++i) {
+ if (mFrames[i].frameNumber < oldestFrameNumber && mFrames[i].valid) {
+ oldestFrameNumber = mFrames[i].frameNumber;
+ oldestFrameIndex = i;
+ }
+ }
+
+ // move the existing frame information into a new vector, so that the oldest frames are at
+ // index 0, and the latest frames are at the end of the vector
+ std::vector<FrameEvents> newFrames(newSize);
+ size_t oldI = oldestFrameIndex;
+ size_t newI = 0;
+ do {
+ if (mFrames[oldI].valid) {
+ newFrames[newI++] = std::move(mFrames[oldI]);
+ }
+ oldI = (oldI + 1) % mFrames.size();
+ } while (oldI != oldestFrameIndex);
+
+ mFrames = std::move(newFrames);
+ mAcquireOffset = 0; // this is just a hint, so setting this to anything is fine
+}
// ============================================================================
// ConsumerFrameEventHistory
// ============================================================================
ConsumerFrameEventHistory::ConsumerFrameEventHistory()
- : mFramesDirty(std::vector<FrameEventDirtyFields>(MAX_FRAME_HISTORY)) {}
+ : mFramesDirty(std::vector<FrameEventDirtyFields>(INITIAL_MAX_FRAME_HISTORY)) {}
ConsumerFrameEventHistory::~ConsumerFrameEventHistory() = default;
@@ -489,6 +531,36 @@ void ConsumerFrameEventHistory::getAndResetDelta(
}
}
+void ConsumerFrameEventHistory::resize(size_t newSize) {
+ // we don't want to drop events by resizing too small, so don't resize in the negative direction
+ if (newSize <= mFrames.size()) {
+ return;
+ }
+
+ // This algorithm for resizing needs to be the same as ProducerFrameEventHistory::resize,
+ // because the indexes need to match when communicating the FrameEventDeltas.
+
+ // move the existing frame information into a new vector, so that the oldest frames are at
+ // index 0, and the latest frames are towards the end of the vector
+ std::vector<FrameEvents> newFrames(newSize);
+ std::vector<FrameEventDirtyFields> newFramesDirty(newSize);
+ size_t oldestFrameIndex = mQueueOffset;
+ size_t oldI = oldestFrameIndex;
+ size_t newI = 0;
+ do {
+ if (mFrames[oldI].valid) {
+ newFrames[newI] = std::move(mFrames[oldI]);
+ newFramesDirty[newI] = mFramesDirty[oldI];
+ newI += 1;
+ }
+ oldI = (oldI + 1) % mFrames.size();
+ } while (oldI != oldestFrameIndex);
+
+ mFrames = std::move(newFrames);
+ mFramesDirty = std::move(newFramesDirty);
+ mQueueOffset = newI;
+ mCompositionOffset = 0; // this is just a hint, so setting this to anything is fine
+}
// ============================================================================
// FrameEventsDelta
@@ -558,8 +630,7 @@ status_t FrameEventsDelta::flatten(void*& buffer, size_t& size, int*& fds,
return NO_MEMORY;
}
- if (mIndex >= FrameEventHistory::MAX_FRAME_HISTORY ||
- mIndex > std::numeric_limits<uint16_t>::max()) {
+ if (mIndex >= UINT8_MAX || mIndex < 0) {
return BAD_VALUE;
}
@@ -601,7 +672,7 @@ status_t FrameEventsDelta::unflatten(void const*& buffer, size_t& size,
uint16_t temp16 = 0;
FlattenableUtils::read(buffer, size, temp16);
mIndex = temp16;
- if (mIndex >= FrameEventHistory::MAX_FRAME_HISTORY) {
+ if (mIndex >= UINT8_MAX) {
return BAD_VALUE;
}
uint8_t temp8 = 0;
@@ -627,6 +698,25 @@ status_t FrameEventsDelta::unflatten(void const*& buffer, size_t& size,
return NO_ERROR;
}
+uint64_t FrameEventsDelta::getFrameNumber() const {
+ return mFrameNumber;
+}
+
+bool FrameEventsDelta::getLatchTime(nsecs_t* latchTime) const {
+ if (mLatchTime == FrameEvents::TIMESTAMP_PENDING) {
+ return false;
+ }
+ *latchTime = mLatchTime;
+ return true;
+}
+
+bool FrameEventsDelta::getDisplayPresentFence(sp<Fence>* fence) const {
+ if (mDisplayPresentFence.fence == Fence::NO_FENCE) {
+ return false;
+ }
+ *fence = mDisplayPresentFence.fence;
+ return true;
+}
// ============================================================================
// FrameEventHistoryDelta
@@ -665,7 +755,7 @@ size_t FrameEventHistoryDelta::getFdCount() const {
status_t FrameEventHistoryDelta::flatten(
void*& buffer, size_t& size, int*& fds, size_t& count) const {
- if (mDeltas.size() > FrameEventHistory::MAX_FRAME_HISTORY) {
+ if (mDeltas.size() > UINT8_MAX) {
return BAD_VALUE;
}
if (size < getFlattenedSize()) {
@@ -695,7 +785,7 @@ status_t FrameEventHistoryDelta::unflatten(
uint32_t deltaCount = 0;
FlattenableUtils::read(buffer, size, deltaCount);
- if (deltaCount > FrameEventHistory::MAX_FRAME_HISTORY) {
+ if (deltaCount > UINT8_MAX) {
return BAD_VALUE;
}
mDeltas.resize(deltaCount);
@@ -708,5 +798,12 @@ status_t FrameEventHistoryDelta::unflatten(
return NO_ERROR;
}
+std::vector<FrameEventsDelta>::const_iterator FrameEventHistoryDelta::begin() const {
+ return mDeltas.begin();
+}
+
+std::vector<FrameEventsDelta>::const_iterator FrameEventHistoryDelta::end() const {
+ return mDeltas.end();
+}
} // namespace android
diff --git a/libs/gui/bufferqueue/1.0/Conversion.cpp b/libs/gui/bufferqueue/1.0/Conversion.cpp
index 55462c3b1f..96679549b2 100644
--- a/libs/gui/bufferqueue/1.0/Conversion.cpp
+++ b/libs/gui/bufferqueue/1.0/Conversion.cpp
@@ -725,12 +725,7 @@ status_t unflatten(HGraphicBufferProducer::FrameEventsDelta* t,
// These were written as uint8_t for alignment.
uint8_t temp = 0;
FlattenableUtils::read(buffer, size, temp);
- size_t index = static_cast<size_t>(temp);
- if (index >= ::android::FrameEventHistory::MAX_FRAME_HISTORY) {
- return BAD_VALUE;
- }
- t->index = static_cast<uint32_t>(index);
-
+ t->index = static_cast<uint32_t>(temp);
FlattenableUtils::read(buffer, size, temp);
t->addPostCompositeCalled = static_cast<bool>(temp);
FlattenableUtils::read(buffer, size, temp);
@@ -786,8 +781,7 @@ status_t unflatten(HGraphicBufferProducer::FrameEventsDelta* t,
status_t flatten(HGraphicBufferProducer::FrameEventsDelta const& t,
void*& buffer, size_t& size, int*& fds, size_t numFds) {
// Check that t.index is within a valid range.
- if (t.index >= static_cast<uint32_t>(FrameEventHistory::MAX_FRAME_HISTORY)
- || t.index > std::numeric_limits<uint8_t>::max()) {
+ if (t.index > UINT8_MAX || t.index < 0) {
return BAD_VALUE;
}
@@ -887,8 +881,7 @@ status_t unflatten(
uint32_t deltaCount = 0;
FlattenableUtils::read(buffer, size, deltaCount);
- if (static_cast<size_t>(deltaCount) >
- ::android::FrameEventHistory::MAX_FRAME_HISTORY) {
+ if (deltaCount > UINT8_MAX) {
return BAD_VALUE;
}
t->deltas.resize(deltaCount);
@@ -919,7 +912,7 @@ status_t unflatten(
status_t flatten(
HGraphicBufferProducer::FrameEventHistoryDelta const& t,
void*& buffer, size_t& size, int*& fds, size_t& numFds) {
- if (t.deltas.size() > ::android::FrameEventHistory::MAX_FRAME_HISTORY) {
+ if (t.deltas.size() > UINT8_MAX) {
return BAD_VALUE;
}
if (size < getFlattenedSize(t)) {
diff --git a/libs/gui/bufferqueue/1.0/H2BGraphicBufferProducer.cpp b/libs/gui/bufferqueue/1.0/H2BGraphicBufferProducer.cpp
index cee1b811a4..f684874aec 100644
--- a/libs/gui/bufferqueue/1.0/H2BGraphicBufferProducer.cpp
+++ b/libs/gui/bufferqueue/1.0/H2BGraphicBufferProducer.cpp
@@ -725,8 +725,7 @@ inline status_t flatten(HGraphicBufferProducer::FrameEventsDelta const& t,
std::vector<native_handle_t*>* nh,
void*& buffer, size_t& size, int*& fds, size_t numFds) {
// Check that t.index is within a valid range.
- if (t.index >= static_cast<uint32_t>(FrameEventHistory::MAX_FRAME_HISTORY)
- || t.index > std::numeric_limits<uint8_t>::max()) {
+ if (t.index > UINT8_MAX || t.index < 0) {
return BAD_VALUE;
}
@@ -829,7 +828,7 @@ inline status_t flatten(
HGraphicBufferProducer::FrameEventHistoryDelta const& t,
std::vector<std::vector<native_handle_t*> >* nh,
void*& buffer, size_t& size, int*& fds, size_t& numFds) {
- if (t.deltas.size() > ::android::FrameEventHistory::MAX_FRAME_HISTORY) {
+ if (t.deltas.size() > UINT8_MAX) {
return BAD_VALUE;
}
if (size < getFlattenedSize(t)) {
diff --git a/libs/gui/include/gui/BLASTBufferQueue.h b/libs/gui/include/gui/BLASTBufferQueue.h
index 48226b9641..1278931202 100644
--- a/libs/gui/include/gui/BLASTBufferQueue.h
+++ b/libs/gui/include/gui/BLASTBufferQueue.h
@@ -54,6 +54,8 @@ public:
nsecs_t dequeueReadyTime) REQUIRES(mMutex);
void getConnectionEvents(uint64_t frameNumber, bool* needsDisconnect);
+ void resizeFrameEventHistory(size_t newSize);
+
protected:
void onSidebandStreamChanged() override REQUIRES(mMutex);
@@ -129,6 +131,7 @@ public:
private:
friend class BLASTBufferQueueHelper;
+ friend class BBQBufferQueueProducer;
// can't be copied
BLASTBufferQueue& operator = (const BLASTBufferQueue& rhs);
@@ -136,6 +139,8 @@ private:
void createBufferQueue(sp<IGraphicBufferProducer>* outProducer,
sp<IGraphicBufferConsumer>* outConsumer);
+ void resizeFrameEventHistory(size_t newSize);
+
void acquireNextBufferLocked(
const std::optional<SurfaceComposerClient::Transaction*> transaction) REQUIRES(mMutex);
Rect computeCrop(const BufferItem& item) REQUIRES(mMutex);
diff --git a/libs/gui/include/gui/BufferQueueProducer.h b/libs/gui/include/gui/BufferQueueProducer.h
index 0ad3075a4d..1d13dab623 100644
--- a/libs/gui/include/gui/BufferQueueProducer.h
+++ b/libs/gui/include/gui/BufferQueueProducer.h
@@ -202,6 +202,11 @@ public:
// See IGraphicBufferProducer::setAutoPrerotation
virtual status_t setAutoPrerotation(bool autoPrerotation);
+protected:
+ // see IGraphicsBufferProducer::setMaxDequeuedBufferCount, but with the ability to retrieve the
+ // total maximum buffer count for the buffer queue (dequeued AND acquired)
+ status_t setMaxDequeuedBufferCount(int maxDequeuedBuffers, int* maxBufferCount);
+
private:
// This is required by the IBinder::DeathRecipient interface
virtual void binderDied(const wp<IBinder>& who);
diff --git a/libs/gui/include/gui/FrameTimestamps.h b/libs/gui/include/gui/FrameTimestamps.h
index dd3de58844..968aa2b257 100644
--- a/libs/gui/include/gui/FrameTimestamps.h
+++ b/libs/gui/include/gui/FrameTimestamps.h
@@ -114,9 +114,11 @@ public:
void checkFencesForCompletion();
void dump(std::string& outString) const;
- static const size_t MAX_FRAME_HISTORY;
+ static const size_t INITIAL_MAX_FRAME_HISTORY;
protected:
+ void resize(size_t newSize);
+
std::vector<FrameEvents> mFrames;
CompositorTiming mCompositorTiming;
@@ -155,6 +157,8 @@ protected:
virtual std::shared_ptr<FenceTime> createFenceTime(
const sp<Fence>& fence) const;
+ void resize(size_t newSize);
+
size_t mAcquireOffset{0};
// The consumer updates it's timelines in Layer and SurfaceFlinger since
@@ -225,6 +229,8 @@ public:
void getAndResetDelta(FrameEventHistoryDelta* delta);
+ void resize(size_t newSize);
+
private:
void getFrameDelta(FrameEventHistoryDelta* delta,
const std::vector<FrameEvents>::iterator& frame);
@@ -267,6 +273,10 @@ public:
status_t unflatten(void const*& buffer, size_t& size, int const*& fds,
size_t& count);
+ uint64_t getFrameNumber() const;
+ bool getLatchTime(nsecs_t* latchTime) const;
+ bool getDisplayPresentFence(sp<Fence>* fence) const;
+
private:
static constexpr size_t minFlattenedSize();
@@ -327,6 +337,9 @@ public:
status_t unflatten(void const*& buffer, size_t& size, int const*& fds,
size_t& count);
+ std::vector<FrameEventsDelta>::const_iterator begin() const;
+ std::vector<FrameEventsDelta>::const_iterator end() const;
+
private:
static constexpr size_t minFlattenedSize();