summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Yin-Chia Yeh <yinchiayeh@google.com> 2017-03-28 19:07:39 -0700
committer Yin-Chia Yeh <yinchiayeh@google.com> 2017-04-03 15:30:19 -0700
commite572fd7b6262389e89cc23d9eb25129394698eb8 (patch)
treef4477d0f5de3ef80b5c5a6889c9b5bba342775e3
parentf2e5430b95b9545e5a355607ba8e7d693b7a7d18 (diff)
Surface: add getRemovedBuffer API
This allows clients to optionally sign up to track buffers going out of Surface. Test: compile Bug: 34461678 Change-Id: I8696b304c169099c872bd9ba783015c0f0dad73a
-rw-r--r--include/gui/Surface.h18
-rw-r--r--libs/gui/Surface.cpp36
2 files changed, 53 insertions, 1 deletions
diff --git a/include/gui/Surface.h b/include/gui/Surface.h
index 62f6cadece..88ef010368 100644
--- a/include/gui/Surface.h
+++ b/include/gui/Surface.h
@@ -257,10 +257,25 @@ public:
virtual int query(int what, int* value) const;
virtual int connect(int api, const sp<IProducerListener>& listener);
+
+ // When reportBufferRemoval is true, clients must call getAndFlushRemovedBuffers to fetch
+ // GraphicBuffers removed from this surface after a dequeueBuffer, detachNextBuffer or
+ // attachBuffer call. This allows clients with their own buffer caches to free up buffers no
+ // longer in use by this surface.
+ virtual int connect(
+ int api, const sp<IProducerListener>& listener,
+ bool reportBufferRemoval);
virtual int detachNextBuffer(sp<GraphicBuffer>* outBuffer,
sp<Fence>* outFence);
virtual int attachBuffer(ANativeWindowBuffer*);
+ // When client connects to Surface with reportBufferRemoval set to true, any buffers removed
+ // from this Surface will be collected and returned here. Once this method returns, these
+ // buffers will no longer be referenced by this Surface unless they are attached to this
+ // Surface later. The list of removed buffers will only be stored until the next dequeueBuffer,
+ // detachNextBuffer, or attachBuffer call.
+ status_t getAndFlushRemovedBuffers(std::vector<sp<GraphicBuffer>>* out);
+
protected:
enum { NUM_BUFFER_SLOTS = BufferQueueDefs::NUM_BUFFER_SLOTS };
enum { DEFAULT_FORMAT = PIXEL_FORMAT_RGBA_8888 };
@@ -414,6 +429,9 @@ protected:
// A cached copy of the FrameEventHistory maintained by the consumer.
bool mEnableFrameTimestamps = false;
std::unique_ptr<ProducerFrameEventHistory> mFrameEventHistory;
+
+ bool mReportRemovedBuffers = false;
+ std::vector<sp<GraphicBuffer>> mRemovedBuffers;
};
} // namespace android
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index 06fc31d16c..1149b8980b 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -505,7 +505,11 @@ int Surface::dequeueBuffer(android_native_buffer_t** buffer, int* fenceFd) {
mFrameEventHistory->applyDelta(frameTimestamps);
}
- if ((result & IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION) || gbuf == 0) {
+ if ((result & IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION) || gbuf == nullptr) {
+ if (mReportRemovedBuffers && (gbuf != nullptr)) {
+ mRemovedBuffers.clear();
+ mRemovedBuffers.push_back(gbuf);
+ }
result = mGraphicBufferProducer->requestBuffer(buf, &gbuf);
if (result != NO_ERROR) {
ALOGE("dequeueBuffer: IGraphicBufferProducer::requestBuffer failed: %d", result);
@@ -1075,10 +1079,16 @@ int Surface::connect(int api) {
}
int Surface::connect(int api, const sp<IProducerListener>& listener) {
+ return connect(api, listener, false);
+}
+
+int Surface::connect(
+ int api, const sp<IProducerListener>& listener, bool reportBufferRemoval) {
ATRACE_CALL();
ALOGV("Surface::connect");
Mutex::Autolock lock(mMutex);
IGraphicBufferProducer::QueueBufferOutput output;
+ mReportRemovedBuffers = reportBufferRemoval;
int err = mGraphicBufferProducer->connect(listener, api, mProducerControlledByApp, &output);
if (err == NO_ERROR) {
mDefaultWidth = output.width;
@@ -1109,6 +1119,7 @@ int Surface::disconnect(int api, IGraphicBufferProducer::DisconnectMode mode) {
ATRACE_CALL();
ALOGV("Surface::disconnect");
Mutex::Autolock lock(mMutex);
+ mRemovedBuffers.clear();
mSharedBufferSlot = BufferItem::INVALID_BUFFER_SLOT;
mSharedBufferHasBeenQueued = false;
freeAllBuffers();
@@ -1156,9 +1167,16 @@ int Surface::detachNextBuffer(sp<GraphicBuffer>* outBuffer,
*outFence = Fence::NO_FENCE;
}
+ if (mReportRemovedBuffers) {
+ mRemovedBuffers.clear();
+ }
+
for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
if (mSlots[i].buffer != NULL &&
mSlots[i].buffer->handle == buffer->handle) {
+ if (mReportRemovedBuffers) {
+ mRemovedBuffers.push_back(mSlots[i].buffer);
+ }
mSlots[i].buffer = NULL;
}
}
@@ -1184,6 +1202,10 @@ int Surface::attachBuffer(ANativeWindowBuffer* buffer)
graphicBuffer->mGenerationNumber = priorGeneration;
return result;
}
+ if (mReportRemovedBuffers && (mSlots[attachedSlot].buffer != nullptr)) {
+ mRemovedBuffers.clear();
+ mRemovedBuffers.push_back(mSlots[attachedSlot].buffer);
+ }
mSlots[attachedSlot].buffer = graphicBuffer;
return NO_ERROR;
@@ -1617,4 +1639,16 @@ status_t Surface::getUniqueId(uint64_t* outId) const {
return mGraphicBufferProducer->getUniqueId(outId);
}
+status_t Surface::getAndFlushRemovedBuffers(std::vector<sp<GraphicBuffer>>* out) {
+ if (out == nullptr) {
+ ALOGE("%s: out must not be null!", __FUNCTION__);
+ return BAD_VALUE;
+ }
+
+ Mutex::Autolock lock(mMutex);
+ *out = mRemovedBuffers;
+ mRemovedBuffers.clear();
+ return OK;
+}
+
}; // namespace android