Update producer's cache of frame events in de/queue
* Cache is only updated during queue and dequeue if
the getFrameTimestamps is enabled.
* The consumer avoids sending a copy of the acquire
fence back to the producer since the producer
already has a copy.
Test: adb shell /data/nativetest/libgui_test/libgui_test
--gtest_filter=*GetFrameTimestamps*
Change-Id: I6a8b965ae79441a40893b5df937f9ed004fe7359
diff --git a/include/gui/BufferQueueProducer.h b/include/gui/BufferQueueProducer.h
index e6ee6c6..5541468 100644
--- a/include/gui/BufferQueueProducer.h
+++ b/include/gui/BufferQueueProducer.h
@@ -80,9 +80,9 @@
//
// In both cases, the producer will need to call requestBuffer to get a
// GraphicBuffer handle for the returned slot.
- virtual status_t dequeueBuffer(int *outSlot, sp<Fence>* outFence,
+ status_t dequeueBuffer(int *outSlot, sp<Fence>* outFence,
uint32_t width, uint32_t height, PixelFormat format,
- uint32_t usage);
+ uint32_t usage, FrameEventHistoryDelta* outTimestamps) override;
// See IGraphicBufferProducer::detachBuffer
virtual status_t detachBuffer(int slot);
diff --git a/include/gui/FrameTimestamps.h b/include/gui/FrameTimestamps.h
index 5076597..0e95ec3 100644
--- a/include/gui/FrameTimestamps.h
+++ b/include/gui/FrameTimestamps.h
@@ -226,7 +226,6 @@
nsecs_t mFirstRefreshStartTime{0};
nsecs_t mLastRefreshStartTime{0};
- sp<Fence> mAcquireFence{Fence::NO_FENCE};
sp<Fence> mGpuCompositionDoneFence{Fence::NO_FENCE};
sp<Fence> mDisplayPresentFence{Fence::NO_FENCE};
sp<Fence> mDisplayRetireFence{Fence::NO_FENCE};
@@ -234,13 +233,12 @@
// This is a static method with an auto return value so we can call
// it without needing const and non-const versions.
- template <typename ThisType>
- static inline auto allFences(ThisType fed) ->
- std::array<decltype(&fed->mAcquireFence), 5> {
+ template <typename ThisT>
+ static inline auto allFences(ThisT fed) ->
+ std::array<decltype(&fed->mReleaseFence), 4> {
return {{
- &fed->mAcquireFence, &fed->mGpuCompositionDoneFence,
- &fed->mDisplayPresentFence, &fed->mDisplayRetireFence,
- &fed->mReleaseFence
+ &fed->mGpuCompositionDoneFence, &fed->mDisplayPresentFence,
+ &fed->mDisplayRetireFence, &fed->mReleaseFence
}};
}
};
diff --git a/include/gui/IGraphicBufferProducer.h b/include/gui/IGraphicBufferProducer.h
index 612a902..492db35 100644
--- a/include/gui/IGraphicBufferProducer.h
+++ b/include/gui/IGraphicBufferProducer.h
@@ -190,7 +190,8 @@
// All other negative values are an unknown error returned downstream
// from the graphics allocator (typically errno).
virtual status_t dequeueBuffer(int* slot, sp<Fence>* fence, uint32_t w,
- uint32_t h, PixelFormat format, uint32_t usage) = 0;
+ uint32_t h, PixelFormat format, uint32_t usage,
+ FrameEventHistoryDelta* outTimestamps) = 0;
// 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
@@ -306,20 +307,23 @@
// set this to Fence::NO_FENCE if the buffer is ready immediately
// sticky - the sticky transform set in Surface (only used by the LEGACY
// camera mode).
+ // getFrameTimestamps - whether or not the latest frame timestamps
+ // should be retrieved from the consumer.
inline QueueBufferInput(int64_t _timestamp, bool _isAutoTimestamp,
android_dataspace _dataSpace, const Rect& _crop,
int _scalingMode, uint32_t _transform, const sp<Fence>& _fence,
- uint32_t _sticky = 0)
+ uint32_t _sticky = 0, bool _getFrameTimestamps = false)
: timestamp(_timestamp), isAutoTimestamp(_isAutoTimestamp),
dataSpace(_dataSpace), crop(_crop), scalingMode(_scalingMode),
transform(_transform), stickyTransform(_sticky), fence(_fence),
- surfaceDamage() { }
+ surfaceDamage(), getFrameTimestamps(_getFrameTimestamps) { }
inline void deflate(int64_t* outTimestamp, bool* outIsAutoTimestamp,
android_dataspace* outDataSpace,
Rect* outCrop, int* outScalingMode,
uint32_t* outTransform, sp<Fence>* outFence,
- uint32_t* outStickyTransform = nullptr) const {
+ uint32_t* outStickyTransform = nullptr,
+ bool* outGetFrameTimestamps = nullptr) const {
*outTimestamp = timestamp;
*outIsAutoTimestamp = bool(isAutoTimestamp);
*outDataSpace = dataSpace;
@@ -330,9 +334,13 @@
if (outStickyTransform != NULL) {
*outStickyTransform = stickyTransform;
}
+ if (outGetFrameTimestamps) {
+ *outGetFrameTimestamps = getFrameTimestamps;
+ }
}
// Flattenable protocol
+ static constexpr size_t minFlattenedSize();
size_t getFlattenedSize() const;
size_t getFdCount() const;
status_t flatten(void*& buffer, size_t& size, int*& fds, size_t& count) const;
@@ -351,37 +359,12 @@
uint32_t stickyTransform{0};
sp<Fence> fence;
Region surfaceDamage;
+ bool getFrameTimestamps{false};
};
struct QueueBufferOutput : public Flattenable<QueueBufferOutput> {
- // outWidth - filled with default width applied to the buffer
- // outHeight - filled with default height applied to the buffer
- // outTransformHint - filled with default transform applied to the buffer
- // outNumPendingBuffers - num buffers queued that haven't yet been acquired
- // (counting the currently queued buffer)
- inline void deflate(uint32_t* outWidth,
- uint32_t* outHeight,
- uint32_t* outTransformHint,
- uint32_t* outNumPendingBuffers,
- uint64_t* outNextFrameNumber) const {
- *outWidth = width;
- *outHeight = height;
- *outTransformHint = transformHint;
- *outNumPendingBuffers = numPendingBuffers;
- *outNextFrameNumber = nextFrameNumber;
- }
-
- inline void inflate(uint32_t inWidth, uint32_t inHeight,
- uint32_t inTransformHint, uint32_t inNumPendingBuffers,
- uint64_t inNextFrameNumber) {
- width = inWidth;
- height = inHeight;
- transformHint = inTransformHint;
- numPendingBuffers = inNumPendingBuffers;
- nextFrameNumber = inNextFrameNumber;
- }
-
// Flattenable protocol
+ static constexpr size_t minFlattenedSize();
size_t getFlattenedSize() const;
size_t getFdCount() const;
status_t flatten(void*& buffer, size_t& size, int*& fds, size_t& count) const;
@@ -392,6 +375,7 @@
uint32_t transformHint{0};
uint32_t numPendingBuffers{0};
uint64_t nextFrameNumber{0};
+ FrameEventHistoryDelta frameTimestamps;
};
virtual status_t queueBuffer(int slot, const QueueBufferInput& input,
diff --git a/include/gui/Surface.h b/include/gui/Surface.h
index c12d452..a10dad1 100644
--- a/include/gui/Surface.h
+++ b/include/gui/Surface.h
@@ -134,6 +134,12 @@
status_t getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer,
sp<Fence>* outFence, float outTransformMatrix[16]);
+ /* Enables or disables frame timestamp tracking. It is disabled by default
+ * to avoid overhead during queue and dequeue for applications that don't
+ * need the feature. If disabled, calls to getFrameTimestamps will fail.
+ */
+ void enableFrameTimestamps(bool enable);
+
// See IGraphicBufferProducer::getFrameTimestamps
status_t getFrameTimestamps(uint64_t frameNumber,
nsecs_t* outRequestedPresentTime, nsecs_t* outAcquireTime,
@@ -192,6 +198,7 @@
int dispatchSetSurfaceDamage(va_list args);
int dispatchSetSharedBufferMode(va_list args);
int dispatchSetAutoRefresh(va_list args);
+ int dispatchEnableFrameTimestamps(va_list args);
int dispatchGetFrameTimestamps(va_list args);
protected:
@@ -390,6 +397,7 @@
mutable bool mFrameTimestampsSupportsRetire;
// A cached copy of the FrameEventHistory maintained by the consumer.
+ bool mEnableFrameTimestamps = false;
ProducerFrameEventHistory mFrameEventHistory;
};
diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp
index e27fd7a..75198d7 100644
--- a/libs/gui/BufferQueueProducer.cpp
+++ b/libs/gui/BufferQueueProducer.cpp
@@ -348,7 +348,8 @@
status_t BufferQueueProducer::dequeueBuffer(int *outSlot,
sp<android::Fence> *outFence, uint32_t width, uint32_t height,
- PixelFormat format, uint32_t usage) {
+ PixelFormat format, uint32_t usage,
+ FrameEventHistoryDelta* outTimestamps) {
ATRACE_CALL();
{ // Autolock scope
Mutex::Autolock lock(mCore->mMutex);
@@ -560,6 +561,8 @@
mSlots[*outSlot].mFrameNumber,
mSlots[*outSlot].mGraphicBuffer->handle, returnFlags);
+ addAndGetFrameTimestamps(nullptr, outTimestamps);
+
return returnFlags;
}
@@ -748,8 +751,10 @@
uint32_t transform;
uint32_t stickyTransform;
sp<Fence> acquireFence;
+ bool getFrameTimestamps = false;
input.deflate(&requestedPresentTimestamp, &isAutoTimestamp, &dataSpace,
- &crop, &scalingMode, &transform, &acquireFence, &stickyTransform);
+ &crop, &scalingMode, &transform, &acquireFence, &stickyTransform,
+ &getFrameTimestamps);
Region surfaceDamage = input.getSurfaceDamage();
if (acquireFence == NULL) {
@@ -913,10 +918,11 @@
mCore->mDequeueCondition.broadcast();
mCore->mLastQueuedSlot = slot;
- output->inflate(mCore->mDefaultWidth, mCore->mDefaultHeight,
- mCore->mTransformHint,
- static_cast<uint32_t>(mCore->mQueue.size()),
- mCore->mFrameCounter + 1);
+ output->width = mCore->mDefaultWidth;
+ output->height = mCore->mDefaultHeight;
+ output->transformHint = mCore->mTransformHint;
+ output->numPendingBuffers = static_cast<uint32_t>(mCore->mQueue.size());
+ output->nextFrameNumber = mCore->mFrameCounter + 1;
ATRACE_INT(mCore->mConsumerName.string(),
static_cast<int32_t>(mCore->mQueue.size()));
@@ -975,7 +981,8 @@
requestedPresentTimestamp,
acquireFence
};
- addAndGetFrameTimestamps(&newFrameEventsEntry, nullptr);
+ addAndGetFrameTimestamps(&newFrameEventsEntry,
+ getFrameTimestamps ? &output->frameTimestamps : nullptr);
return NO_ERROR;
}
@@ -1141,10 +1148,13 @@
case NATIVE_WINDOW_API_MEDIA:
case NATIVE_WINDOW_API_CAMERA:
mCore->mConnectedApi = api;
- output->inflate(mCore->mDefaultWidth, mCore->mDefaultHeight,
- mCore->mTransformHint,
- static_cast<uint32_t>(mCore->mQueue.size()),
- mCore->mFrameCounter + 1);
+
+ output->width = mCore->mDefaultWidth;
+ output->height = mCore->mDefaultHeight;
+ output->transformHint = mCore->mTransformHint;
+ output->numPendingBuffers =
+ static_cast<uint32_t>(mCore->mQueue.size());
+ output->nextFrameNumber = mCore->mFrameCounter + 1;
if (listener != NULL) {
// Set up a death notification so that we can disconnect
diff --git a/libs/gui/FrameTimestamps.cpp b/libs/gui/FrameTimestamps.cpp
index 4b98cff..30ff65f 100644
--- a/libs/gui/FrameTimestamps.cpp
+++ b/libs/gui/FrameTimestamps.cpp
@@ -301,7 +301,6 @@
// Existing frame. Merge.
// Consumer never sends timestamps of fences, only the fences
// themselves, so we never need to update the fence timestamps here.
- applyFenceDelta(&frame.acquireFence, d.mAcquireFence);
applyFenceDelta(
&frame.gpuCompositionDoneFence, d.mGpuCompositionDoneFence);
applyFenceDelta(&frame.displayPresentFence, d.mDisplayPresentFence);
@@ -318,7 +317,7 @@
// Set aquire fence and time at this point.
frame.acquireTime = 0;
- frame.acquireFence = d.mAcquireFence;
+ frame.acquireFence = Fence::NO_FENCE;
// Reset fence-related timestamps
frame.gpuCompositionDoneTime = 0;
@@ -348,8 +347,11 @@
newTimestamps.acquireFence = newEntry.acquireFence;
newTimestamps.valid = true;
mFrames[mQueueOffset] = newTimestamps;
+
+ // Note: We avoid sending the acquire fence back to the caller since
+ // they have the original one already, so there is no need to set the
+ // acquire dirty bit.
mFramesDirty[mQueueOffset].setDirty<FrameEvent::POSTED>();
- mFramesDirty[mQueueOffset].setDirty<FrameEvent::ACQUIRE>();
mQueueOffset = (mQueueOffset + 1) % mFrames.size();
}
@@ -456,8 +458,6 @@
mLatchTime(frameTimestamps.latchTime),
mFirstRefreshStartTime(frameTimestamps.firstRefreshStartTime),
mLastRefreshStartTime(frameTimestamps.lastRefreshStartTime) {
- mAcquireFence = dirtyFields.isDirty<FrameEvent::ACQUIRE>() ?
- frameTimestamps.acquireFence : Fence::NO_FENCE;
mGpuCompositionDoneFence =
dirtyFields.isDirty<FrameEvent::GL_COMPOSITION_DONE>() ?
frameTimestamps.gpuCompositionDoneFence : Fence::NO_FENCE;
diff --git a/libs/gui/IGraphicBufferProducer.cpp b/libs/gui/IGraphicBufferProducer.cpp
index bed7d53..e37b65b 100644
--- a/libs/gui/IGraphicBufferProducer.cpp
+++ b/libs/gui/IGraphicBufferProducer.cpp
@@ -118,14 +118,17 @@
}
virtual status_t dequeueBuffer(int *buf, sp<Fence>* fence, uint32_t width,
- uint32_t height, PixelFormat format, uint32_t usage) {
+ uint32_t height, PixelFormat format, uint32_t usage,
+ FrameEventHistoryDelta* outTimestamps) {
Parcel data, reply;
+ bool getFrameTimestamps = (outTimestamps != nullptr);
data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
data.writeUint32(width);
data.writeUint32(height);
data.writeInt32(static_cast<int32_t>(format));
data.writeUint32(usage);
+ data.writeBool(getFrameTimestamps);
status_t result = remote()->transact(DEQUEUE_BUFFER, data, &reply);
if (result != NO_ERROR) {
@@ -139,6 +142,14 @@
fence->clear();
return result;
}
+ if (getFrameTimestamps) {
+ result = reply.read(*outTimestamps);
+ if (result != NO_ERROR) {
+ ALOGE("IGBP::dequeueBuffer failed to read timestamps: %d",
+ result);
+ return result;
+ }
+ }
result = reply.readInt32();
return result;
}
@@ -513,14 +524,19 @@
uint32_t height = data.readUint32();
PixelFormat format = static_cast<PixelFormat>(data.readInt32());
uint32_t usage = data.readUint32();
+ bool getTimestamps = data.readBool();
int buf = 0;
sp<Fence> fence = Fence::NO_FENCE;
+ FrameEventHistoryDelta frameTimestamps;
int result = dequeueBuffer(&buf, &fence, width, height, format,
- usage);
+ usage, getTimestamps ? &frameTimestamps : nullptr);
reply->writeInt32(buf);
reply->write(*fence);
+ if (getTimestamps) {
+ reply->write(frameTimestamps);
+ }
reply->writeInt32(result);
return NO_ERROR;
}
@@ -563,14 +579,14 @@
}
case QUEUE_BUFFER: {
CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
+
int buf = data.readInt32();
QueueBufferInput input(data);
-
QueueBufferOutput output;
status_t result = queueBuffer(buf, input, &output);
-
reply->write(output);
reply->writeInt32(result);
+
return NO_ERROR;
}
case CANCEL_BUFFER: {
@@ -740,16 +756,21 @@
parcel.read(*this);
}
+constexpr size_t IGraphicBufferProducer::QueueBufferInput::minFlattenedSize() {
+ return sizeof(timestamp) +
+ sizeof(isAutoTimestamp) +
+ sizeof(dataSpace) +
+ sizeof(crop) +
+ sizeof(scalingMode) +
+ sizeof(transform) +
+ sizeof(stickyTransform) +
+ sizeof(getFrameTimestamps);
+}
+
size_t IGraphicBufferProducer::QueueBufferInput::getFlattenedSize() const {
- return sizeof(timestamp)
- + sizeof(isAutoTimestamp)
- + sizeof(dataSpace)
- + sizeof(crop)
- + sizeof(scalingMode)
- + sizeof(transform)
- + sizeof(stickyTransform)
- + fence->getFlattenedSize()
- + surfaceDamage.getFlattenedSize();
+ return minFlattenedSize() +
+ fence->getFlattenedSize() +
+ surfaceDamage.getFlattenedSize();
}
size_t IGraphicBufferProducer::QueueBufferInput::getFdCount() const {
@@ -762,6 +783,7 @@
if (size < getFlattenedSize()) {
return NO_MEMORY;
}
+
FlattenableUtils::write(buffer, size, timestamp);
FlattenableUtils::write(buffer, size, isAutoTimestamp);
FlattenableUtils::write(buffer, size, dataSpace);
@@ -769,6 +791,8 @@
FlattenableUtils::write(buffer, size, scalingMode);
FlattenableUtils::write(buffer, size, transform);
FlattenableUtils::write(buffer, size, stickyTransform);
+ FlattenableUtils::write(buffer, size, getFrameTimestamps);
+
status_t result = fence->flatten(buffer, size, fds, count);
if (result != NO_ERROR) {
return result;
@@ -779,16 +803,7 @@
status_t IGraphicBufferProducer::QueueBufferInput::unflatten(
void const*& buffer, size_t& size, int const*& fds, size_t& count)
{
- size_t minNeeded =
- sizeof(timestamp)
- + sizeof(isAutoTimestamp)
- + sizeof(dataSpace)
- + sizeof(crop)
- + sizeof(scalingMode)
- + sizeof(transform)
- + sizeof(stickyTransform);
-
- if (size < minNeeded) {
+ if (size < minFlattenedSize()) {
return NO_MEMORY;
}
@@ -799,6 +814,7 @@
FlattenableUtils::read(buffer, size, scalingMode);
FlattenableUtils::read(buffer, size, transform);
FlattenableUtils::read(buffer, size, stickyTransform);
+ FlattenableUtils::read(buffer, size, getFrameTimestamps);
fence = new Fence();
status_t result = fence->unflatten(buffer, size, fds, count);
@@ -809,49 +825,52 @@
}
// ----------------------------------------------------------------------------
+constexpr size_t IGraphicBufferProducer::QueueBufferOutput::minFlattenedSize() {
+ return sizeof(width) +
+ sizeof(height) +
+ sizeof(transformHint) +
+ sizeof(numPendingBuffers) +
+ sizeof(nextFrameNumber);
+}
size_t IGraphicBufferProducer::QueueBufferOutput::getFlattenedSize() const {
- size_t size = sizeof(width)
- + sizeof(height)
- + sizeof(transformHint)
- + sizeof(numPendingBuffers)
- + sizeof(nextFrameNumber);
- return size;
+ return minFlattenedSize() + frameTimestamps.getFlattenedSize();
}
size_t IGraphicBufferProducer::QueueBufferOutput::getFdCount() const {
- return 0;
+ return frameTimestamps.getFdCount();
}
status_t IGraphicBufferProducer::QueueBufferOutput::flatten(
- void*& buffer, size_t& size, int*& /*fds*/, size_t& /*count*/) const
+ void*& buffer, size_t& size, int*& fds, size_t& count) const
{
if (size < getFlattenedSize()) {
return NO_MEMORY;
}
+
FlattenableUtils::write(buffer, size, width);
FlattenableUtils::write(buffer, size, height);
FlattenableUtils::write(buffer, size, transformHint);
FlattenableUtils::write(buffer, size, numPendingBuffers);
FlattenableUtils::write(buffer, size, nextFrameNumber);
- return NO_ERROR;
+ return frameTimestamps.flatten(buffer, size, fds, count);
}
status_t IGraphicBufferProducer::QueueBufferOutput::unflatten(
- void const*& buffer, size_t& size,
- int const*& /*fds*/, size_t& /*count*/)
+ void const*& buffer, size_t& size, int const*& fds, size_t& count)
{
- if (size < getFlattenedSize()) {
+ if (size < minFlattenedSize()) {
return NO_MEMORY;
}
+
FlattenableUtils::read(buffer, size, width);
FlattenableUtils::read(buffer, size, height);
FlattenableUtils::read(buffer, size, transformHint);
FlattenableUtils::read(buffer, size, numPendingBuffers);
FlattenableUtils::read(buffer, size, nextFrameNumber);
- return NO_ERROR;
+ return frameTimestamps.unflatten(buffer, size, fds, count);
}
}; // namespace android
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index c29101e..6a02a77 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -52,7 +52,8 @@
mNextFrameNumber(1),
mQueriedSupportedTimestamps(false),
mFrameTimestampsSupportsPresent(false),
- mFrameTimestampsSupportsRetire(false)
+ mFrameTimestampsSupportsRetire(false),
+ mEnableFrameTimestamps(false)
{
// Initialize the ANativeWindow function pointers.
ANativeWindow::setSwapInterval = hook_setSwapInterval;
@@ -138,6 +139,11 @@
outTransformMatrix);
}
+void Surface::enableFrameTimestamps(bool enable) {
+ Mutex::Autolock lock(mMutex);
+ mEnableFrameTimestamps = enable;
+}
+
status_t Surface::getFrameTimestamps(uint64_t frameNumber,
nsecs_t* outRequestedPresentTime, nsecs_t* outAcquireTime,
nsecs_t* outRefreshStartTime, nsecs_t* outGlCompositionDoneTime,
@@ -147,6 +153,10 @@
Mutex::Autolock lock(mMutex);
+ if (!mEnableFrameTimestamps) {
+ return INVALID_OPERATION;
+ }
+
// Verify the requested timestamps are supported.
querySupportedTimestampsLocked();
if (outDisplayPresentTime != nullptr && !mFrameTimestampsSupportsPresent) {
@@ -308,6 +318,7 @@
uint32_t reqHeight;
PixelFormat reqFormat;
uint32_t reqUsage;
+ bool enableFrameTimestamps;
{
Mutex::Autolock lock(mMutex);
@@ -318,6 +329,8 @@
reqFormat = mReqFormat;
reqUsage = mReqUsage;
+ enableFrameTimestamps = mEnableFrameTimestamps;
+
if (mSharedBufferMode && mAutoRefresh && mSharedBufferSlot !=
BufferItem::INVALID_BUFFER_SLOT) {
sp<GraphicBuffer>& gbuf(mSlots[mSharedBufferSlot].buffer);
@@ -332,8 +345,13 @@
int buf = -1;
sp<Fence> fence;
nsecs_t now = systemTime();
+
+ FrameEventHistoryDelta frameTimestamps;
+ FrameEventHistoryDelta* frameTimestampsOrNull =
+ enableFrameTimestamps ? &frameTimestamps : nullptr;
+
status_t result = mGraphicBufferProducer->dequeueBuffer(&buf, &fence,
- reqWidth, reqHeight, reqFormat, reqUsage);
+ reqWidth, reqHeight, reqFormat, reqUsage, frameTimestampsOrNull);
mLastDequeueDuration = systemTime() - now;
if (result < 0) {
@@ -354,6 +372,10 @@
freeAllBuffers();
}
+ if (enableFrameTimestamps) {
+ mFrameEventHistory.applyDelta(frameTimestamps);
+ }
+
if ((result & IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION) || gbuf == 0) {
result = mGraphicBufferProducer->requestBuffer(buf, &gbuf);
if (result != NO_ERROR) {
@@ -472,7 +494,7 @@
IGraphicBufferProducer::QueueBufferOutput output;
IGraphicBufferProducer::QueueBufferInput input(timestamp, isAutoTimestamp,
mDataSpace, crop, mScalingMode, mTransform ^ mStickyTransform,
- fence, mStickyTransform);
+ fence, mStickyTransform, mEnableFrameTimestamps);
if (mConnectedToCpu || mDirtyRegion.bounds() == Rect::INVALID_RECT) {
input.setSurfaceDamage(Region::INVALID_REGION);
@@ -544,17 +566,24 @@
ALOGE("queueBuffer: error queuing buffer to SurfaceTexture, %d", err);
}
- uint32_t numPendingBuffers = 0;
- uint32_t hint = 0;
- output.deflate(&mDefaultWidth, &mDefaultHeight, &hint,
- &numPendingBuffers, &mNextFrameNumber);
+ if (mEnableFrameTimestamps) {
+ mFrameEventHistory.applyDelta(output.frameTimestamps);
+ // Update timestamps with the local acquire fence.
+ // The consumer doesn't send it back to prevent us from having two
+ // file descriptors of the same fence.
+ mFrameEventHistory.updateAcquireFence(mNextFrameNumber, fence);
+ }
+
+ mDefaultWidth = output.width;
+ mDefaultHeight = output.height;
+ mNextFrameNumber = output.nextFrameNumber;
// Disable transform hint if sticky transform is set.
if (mStickyTransform == 0) {
- mTransformHint = hint;
+ mTransformHint = output.transformHint;
}
- mConsumerRunningBehind = (numPendingBuffers >= 2);
+ mConsumerRunningBehind = (output.numPendingBuffers >= 2);
if (!mConnectedToCpu) {
// Clear surface damage back to full-buffer
@@ -743,6 +772,9 @@
case NATIVE_WINDOW_SET_AUTO_REFRESH:
res = dispatchSetAutoRefresh(args);
break;
+ case NATIVE_WINDOW_ENABLE_FRAME_TIMESTAMPS:
+ res = dispatchEnableFrameTimestamps(args);
+ break;
case NATIVE_WINDOW_GET_FRAME_TIMESTAMPS:
res = dispatchGetFrameTimestamps(args);
break;
@@ -866,6 +898,12 @@
return setAutoRefresh(autoRefresh);
}
+int Surface::dispatchEnableFrameTimestamps(va_list args) {
+ bool enable = va_arg(args, int);
+ enableFrameTimestamps(enable);
+ return NO_ERROR;
+}
+
int Surface::dispatchGetFrameTimestamps(va_list args) {
uint32_t framesAgo = va_arg(args, uint32_t);
nsecs_t* outRequestedPresentTime = va_arg(args, int64_t*);
@@ -893,17 +931,16 @@
IGraphicBufferProducer::QueueBufferOutput output;
int err = mGraphicBufferProducer->connect(listener, api, mProducerControlledByApp, &output);
if (err == NO_ERROR) {
- uint32_t numPendingBuffers = 0;
- uint32_t hint = 0;
- output.deflate(&mDefaultWidth, &mDefaultHeight, &hint,
- &numPendingBuffers, &mNextFrameNumber);
+ mDefaultWidth = output.width;
+ mDefaultHeight = output.height;
+ mNextFrameNumber = output.nextFrameNumber;
// Disable transform hint if sticky transform is set.
if (mStickyTransform == 0) {
- mTransformHint = hint;
+ mTransformHint = output.transformHint;
}
- mConsumerRunningBehind = (numPendingBuffers >= 2);
+ mConsumerRunningBehind = (output.numPendingBuffers >= 2);
}
if (!err && api == NATIVE_WINDOW_API_CPU) {
mConnectedToCpu = true;
diff --git a/libs/gui/tests/BufferQueue_test.cpp b/libs/gui/tests/BufferQueue_test.cpp
index 65df7dc..98c0449 100644
--- a/libs/gui/tests/BufferQueue_test.cpp
+++ b/libs/gui/tests/BufferQueue_test.cpp
@@ -139,7 +139,7 @@
sp<GraphicBuffer> buffer;
ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
- GRALLOC_USAGE_SW_WRITE_OFTEN));
+ GRALLOC_USAGE_SW_WRITE_OFTEN, nullptr));
ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
uint32_t* dataIn;
@@ -183,7 +183,7 @@
for (int i = 0; i < 2; i++) {
ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
mProducer->dequeueBuffer(&slot, &fence, 1, 1, 0,
- GRALLOC_USAGE_SW_READ_OFTEN));
+ GRALLOC_USAGE_SW_READ_OFTEN, nullptr));
ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buf));
ASSERT_EQ(OK, mProducer->queueBuffer(slot, qbi, &qbo));
ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
@@ -191,7 +191,7 @@
ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
mProducer->dequeueBuffer(&slot, &fence, 1, 1, 0,
- GRALLOC_USAGE_SW_READ_OFTEN));
+ GRALLOC_USAGE_SW_READ_OFTEN, nullptr));
ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buf));
ASSERT_EQ(OK, mProducer->queueBuffer(slot, qbi, &qbo));
@@ -234,7 +234,7 @@
for (int i = 0; i < 3; i++) {
ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
mProducer->dequeueBuffer(&slot, &fence, 1, 1, 0,
- GRALLOC_USAGE_SW_READ_OFTEN));
+ GRALLOC_USAGE_SW_READ_OFTEN, nullptr));
ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buf));
ASSERT_EQ(OK, mProducer->queueBuffer(slot, qbi, &qbo));
ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
@@ -270,7 +270,7 @@
ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
mProducer->dequeueBuffer(&slot, &fence, 1, 1, 0,
- GRALLOC_USAGE_SW_READ_OFTEN));
+ GRALLOC_USAGE_SW_READ_OFTEN, nullptr));
ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buf));
ASSERT_EQ(OK, mProducer->queueBuffer(slot, qbi, &qbo));
ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
@@ -280,7 +280,7 @@
for (int i = 0; i < 2; i++) {
ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
mProducer->dequeueBuffer(&slot, &fence, 1, 1, 0,
- GRALLOC_USAGE_SW_READ_OFTEN));
+ GRALLOC_USAGE_SW_READ_OFTEN, nullptr));
ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buf));
ASSERT_EQ(OK, mProducer->queueBuffer(slot, qbi, &qbo));
ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
@@ -330,7 +330,7 @@
sp<GraphicBuffer> buffer;
ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
- GRALLOC_USAGE_SW_WRITE_OFTEN));
+ GRALLOC_USAGE_SW_WRITE_OFTEN, nullptr));
ASSERT_EQ(BAD_VALUE, mProducer->detachBuffer(slot)); // Not requested
ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
ASSERT_EQ(OK, mProducer->detachBuffer(slot));
@@ -379,7 +379,7 @@
sp<GraphicBuffer> buffer;
ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
- GRALLOC_USAGE_SW_WRITE_OFTEN));
+ GRALLOC_USAGE_SW_WRITE_OFTEN, nullptr));
ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
IGraphicBufferProducer::QueueBufferInput input(0, false,
HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
@@ -415,7 +415,7 @@
ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
- GRALLOC_USAGE_SW_WRITE_OFTEN));
+ GRALLOC_USAGE_SW_WRITE_OFTEN, nullptr));
ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
uint32_t* dataOut;
@@ -438,7 +438,7 @@
sp<GraphicBuffer> buffer;
ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
- GRALLOC_USAGE_SW_WRITE_OFTEN));
+ GRALLOC_USAGE_SW_WRITE_OFTEN, nullptr));
ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
uint32_t* dataIn;
@@ -487,13 +487,13 @@
// This should return an error since it would require an allocation
ASSERT_EQ(OK, mProducer->allowAllocation(false));
ASSERT_EQ(WOULD_BLOCK, mProducer->dequeueBuffer(&slot, &fence, 0, 0,
- 0, GRALLOC_USAGE_SW_WRITE_OFTEN));
+ 0, GRALLOC_USAGE_SW_WRITE_OFTEN, nullptr));
// This should succeed, now that we've lifted the prohibition
ASSERT_EQ(OK, mProducer->allowAllocation(true));
ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
- GRALLOC_USAGE_SW_WRITE_OFTEN));
+ GRALLOC_USAGE_SW_WRITE_OFTEN, nullptr));
// Release the previous buffer back to the BufferQueue
mProducer->cancelBuffer(slot, fence);
@@ -501,7 +501,7 @@
// This should fail since we're requesting a different size
ASSERT_EQ(OK, mProducer->allowAllocation(false));
ASSERT_EQ(WOULD_BLOCK, mProducer->dequeueBuffer(&slot, &fence,
- WIDTH * 2, HEIGHT * 2, 0, GRALLOC_USAGE_SW_WRITE_OFTEN));
+ WIDTH * 2, HEIGHT * 2, 0, GRALLOC_USAGE_SW_WRITE_OFTEN, nullptr));
}
TEST_F(BufferQueueTest, TestGenerationNumbers) {
@@ -518,7 +518,7 @@
int slot;
sp<Fence> fence;
ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
- mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0));
+ mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr));
sp<GraphicBuffer> buffer;
ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
@@ -561,7 +561,7 @@
sp<Fence> fence;
sp<GraphicBuffer> buffer;
ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
- mProducer->dequeueBuffer(&sharedSlot, &fence, 0, 0, 0, 0));
+ mProducer->dequeueBuffer(&sharedSlot, &fence, 0, 0, 0, 0, nullptr));
ASSERT_EQ(OK, mProducer->requestBuffer(sharedSlot, &buffer));
// Queue the buffer
@@ -575,7 +575,8 @@
// always the same one and because async mode gets enabled.
int slot;
for (int i = 0; i < 5; i++) {
- ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0));
+ ASSERT_EQ(OK, mProducer->dequeueBuffer(
+ &slot, &fence, 0, 0, 0, 0, nullptr));
ASSERT_EQ(sharedSlot, slot);
ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
}
@@ -612,7 +613,7 @@
sp<Fence> fence;
sp<GraphicBuffer> buffer;
ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
- mProducer->dequeueBuffer(&sharedSlot, &fence, 0, 0, 0, 0));
+ mProducer->dequeueBuffer(&sharedSlot, &fence, 0, 0, 0, 0, nullptr));
ASSERT_EQ(OK, mProducer->requestBuffer(sharedSlot, &buffer));
// Queue the buffer
@@ -639,7 +640,8 @@
// always return the same one.
int slot;
for (int i = 0; i < 5; i++) {
- ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0));
+ ASSERT_EQ(OK, mProducer->dequeueBuffer(
+ &slot, &fence, 0, 0, 0, 0, nullptr));
ASSERT_EQ(sharedSlot, slot);
ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
}
@@ -678,7 +680,7 @@
sp<Fence> fence;
sp<GraphicBuffer> buffer;
ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
- mProducer->dequeueBuffer(&sharedSlot, &fence, 0, 0, 0, 0));
+ mProducer->dequeueBuffer(&sharedSlot, &fence, 0, 0, 0, 0, nullptr));
ASSERT_EQ(OK, mProducer->requestBuffer(sharedSlot, &buffer));
// Enable shared buffer mode
@@ -695,7 +697,8 @@
// always the same one and because async mode gets enabled.
int slot;
for (int i = 0; i < 5; i++) {
- ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0));
+ ASSERT_EQ(OK, mProducer->dequeueBuffer(
+ &slot, &fence, 0, 0, 0, 0, nullptr));
ASSERT_EQ(sharedSlot, slot);
ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
}
@@ -730,7 +733,8 @@
for (int i = 0; i < 5; ++i) {
int slot = BufferQueue::INVALID_BUFFER_SLOT;
sp<Fence> fence = Fence::NO_FENCE;
- auto result = mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0);
+ auto result = mProducer->dequeueBuffer(
+ &slot, &fence, 0, 0, 0, 0, nullptr);
if (i < 2) {
ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
result);
@@ -757,7 +761,8 @@
for (int i = 0; i < 2; ++i) {
int slot = BufferQueue::INVALID_BUFFER_SLOT;
sp<Fence> fence = Fence::NO_FENCE;
- ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0));
+ ASSERT_EQ(OK, mProducer->dequeueBuffer(
+ &slot, &fence, 0, 0, 0, 0, nullptr));
ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
IGraphicBufferProducer::QueueBufferInput input(0ull, true,
HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
@@ -768,7 +773,8 @@
int slot = BufferQueue::INVALID_BUFFER_SLOT;
sp<Fence> fence = Fence::NO_FENCE;
auto startTime = systemTime();
- ASSERT_EQ(TIMED_OUT, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0));
+ ASSERT_EQ(TIMED_OUT, mProducer->dequeueBuffer(
+ &slot, &fence, 0, 0, 0, 0, nullptr));
ASSERT_GE(systemTime() - startTime, TIMEOUT);
// We're technically attaching the same buffer multiple times (since we
@@ -789,7 +795,7 @@
int slot = BufferQueue::INVALID_BUFFER_SLOT;
sp<Fence> sourceFence;
ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
- mProducer->dequeueBuffer(&slot, &sourceFence, 0, 0, 0, 0));
+ mProducer->dequeueBuffer(&slot, &sourceFence, 0, 0, 0, 0, nullptr));
sp<GraphicBuffer> buffer;
ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
ASSERT_EQ(OK, mProducer->detachBuffer(slot));
@@ -812,7 +818,7 @@
int slot = BufferQueue::INVALID_BUFFER_SLOT;
sp<Fence> fence;
ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
- mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0));
+ mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr));
sp<GraphicBuffer> firstBuffer;
ASSERT_EQ(OK, mProducer->requestBuffer(slot, &firstBuffer));
@@ -824,7 +830,7 @@
// Dequeue a second buffer
slot = BufferQueue::INVALID_BUFFER_SLOT;
ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
- mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0));
+ mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr));
sp<GraphicBuffer> secondBuffer;
ASSERT_EQ(OK, mProducer->requestBuffer(slot, &secondBuffer));
@@ -876,7 +882,7 @@
mProducer->setMaxDequeuedBufferCount(3);
for (size_t i = 0; i < 3; ++i) {
status_t result = mProducer->dequeueBuffer(&slots[i], &fence,
- 0, 0, 0, 0);
+ 0, 0, 0, 0, nullptr);
ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, result);
ASSERT_EQ(OK, mProducer->requestBuffer(slots[i], &buffer));
}
@@ -889,7 +895,8 @@
// The first segment is a two-buffer segment, so we only put one buffer into
// the queue at a time
for (size_t i = 0; i < 5; ++i) {
- ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0));
+ ASSERT_EQ(OK, mProducer->dequeueBuffer(
+ &slot, &fence, 0, 0, 0, 0, nullptr));
ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
@@ -904,16 +911,17 @@
// two-buffer segment, but then at the end, we put two buffers in the queue
// at the same time before draining it.
for (size_t i = 0; i < 5; ++i) {
- ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0));
+ ASSERT_EQ(OK, mProducer->dequeueBuffer(
+ &slot, &fence, 0, 0, 0, 0, nullptr));
ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
std::this_thread::sleep_for(16ms);
}
- ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0));
+ ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr));
ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
- ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0));
+ ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr));
ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
@@ -928,10 +936,11 @@
// The third segment is a triple-buffer segment, so the queue is switching
// between one buffer and two buffers deep.
- ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0));
+ ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr));
ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
for (size_t i = 0; i < 5; ++i) {
- ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0));
+ ASSERT_EQ(OK, mProducer->dequeueBuffer(
+ &slot, &fence, 0, 0, 0, 0, nullptr));
ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
@@ -1012,7 +1021,7 @@
mProducer->setMaxDequeuedBufferCount(4);
for (size_t i = 0; i < 4; ++i) {
status_t result = mProducer->dequeueBuffer(&slots[i], &fence,
- 0, 0, 0, 0);
+ 0, 0, 0, 0, nullptr);
ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, result);
ASSERT_EQ(OK, mProducer->requestBuffer(slots[i], &buffer));
}
@@ -1023,14 +1032,14 @@
// Get buffers in all states: dequeued, filled, acquired, free
// Fill 3 buffers
- ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0));
+ ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr));
ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
- ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0));
+ ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr));
ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
- ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0));
+ ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr));
ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
// Dequeue 1 buffer
- ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0));
+ ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0, nullptr));
// Acquire and free 1 buffer
ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
diff --git a/libs/gui/tests/IGraphicBufferProducer_test.cpp b/libs/gui/tests/IGraphicBufferProducer_test.cpp
index 9f33047..0329a6d 100644
--- a/libs/gui/tests/IGraphicBufferProducer_test.cpp
+++ b/libs/gui/tests/IGraphicBufferProducer_test.cpp
@@ -196,7 +196,7 @@
};
status_t dequeueBuffer(uint32_t w, uint32_t h, uint32_t format, uint32_t usage, DequeueBufferResult* result) {
- return mProducer->dequeueBuffer(&result->slot, &result->fence, w, h, format, usage);
+ return mProducer->dequeueBuffer(&result->slot, &result->fence, w, h, format, usage, nullptr);
}
void setupDequeueRequestBuffer(int *slot, sp<Fence> *fence,
@@ -210,7 +210,7 @@
ASSERT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
(mProducer->dequeueBuffer(slot, fence, DEFAULT_WIDTH,
- DEFAULT_HEIGHT, DEFAULT_FORMAT, TEST_PRODUCER_USAGE_BITS)));
+ DEFAULT_HEIGHT, DEFAULT_FORMAT, TEST_PRODUCER_USAGE_BITS, nullptr)));
EXPECT_LE(0, *slot);
EXPECT_GT(BufferQueue::NUM_BUFFER_SLOTS, *slot);
@@ -349,7 +349,7 @@
ASSERT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
(mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence,
DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_FORMAT,
- TEST_PRODUCER_USAGE_BITS)));
+ TEST_PRODUCER_USAGE_BITS, nullptr)));
EXPECT_LE(0, dequeuedSlot);
EXPECT_GT(BufferQueue::NUM_BUFFER_SLOTS, dequeuedSlot);
@@ -366,20 +366,12 @@
ASSERT_OK(mProducer->queueBuffer(dequeuedSlot, input, &output));
{
- uint32_t width;
- uint32_t height;
- uint32_t transformHint;
- uint32_t numPendingBuffers;
- uint64_t nextFrameNumber;
-
- output.deflate(&width, &height, &transformHint, &numPendingBuffers,
- &nextFrameNumber);
-
- EXPECT_EQ(DEFAULT_WIDTH, width);
- EXPECT_EQ(DEFAULT_HEIGHT, height);
- EXPECT_EQ(DEFAULT_TRANSFORM_HINT, transformHint);
- EXPECT_EQ(1u, numPendingBuffers); // since queueBuffer was called exactly once
- EXPECT_EQ(2u, nextFrameNumber);
+ EXPECT_EQ(DEFAULT_WIDTH, output.width);
+ EXPECT_EQ(DEFAULT_HEIGHT, output.height);
+ EXPECT_EQ(DEFAULT_TRANSFORM_HINT, output.transformHint);
+ // Since queueBuffer was called exactly once
+ EXPECT_EQ(1u, output.numPendingBuffers);
+ EXPECT_EQ(2u, output.nextFrameNumber);
}
// Buffer was not in the dequeued state
@@ -416,7 +408,7 @@
ASSERT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
(mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence,
DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_FORMAT,
- TEST_PRODUCER_USAGE_BITS)));
+ TEST_PRODUCER_USAGE_BITS, nullptr)));
// Slot was enqueued without requesting a buffer
{
@@ -485,7 +477,7 @@
ASSERT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
(mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence,
DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_FORMAT,
- TEST_PRODUCER_USAGE_BITS)));
+ TEST_PRODUCER_USAGE_BITS, nullptr)));
// No return code, but at least test that it doesn't blow up...
// TODO: add a return code
@@ -534,7 +526,7 @@
(mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence,
DEFAULT_WIDTH, DEFAULT_HEIGHT,
DEFAULT_FORMAT,
- TEST_PRODUCER_USAGE_BITS)))
+ TEST_PRODUCER_USAGE_BITS, nullptr)))
<< "iteration: " << i << ", slot: " << dequeuedSlot;
}
@@ -571,7 +563,7 @@
(mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence,
DEFAULT_WIDTH, DEFAULT_HEIGHT,
DEFAULT_FORMAT,
- TEST_PRODUCER_USAGE_BITS)))
+ TEST_PRODUCER_USAGE_BITS, nullptr)))
<< "slot: " << dequeuedSlot;
}
@@ -606,7 +598,8 @@
ASSERT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
(mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence,
DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_FORMAT,
- TEST_PRODUCER_USAGE_BITS))) << "slot : " << dequeuedSlot;
+ TEST_PRODUCER_USAGE_BITS, nullptr)))
+ << "slot : " << dequeuedSlot;
ASSERT_OK(mProducer->requestBuffer(dequeuedSlot, &dequeuedBuffer));
ASSERT_OK(mProducer->queueBuffer(dequeuedSlot, input, &output));
}
@@ -622,7 +615,8 @@
ASSERT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
(mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence,
DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_FORMAT,
- TEST_PRODUCER_USAGE_BITS))) << "slot: " << dequeuedSlot;
+ TEST_PRODUCER_USAGE_BITS, nullptr)))
+ << "slot: " << dequeuedSlot;
}
// Abandon buffer queue
@@ -639,7 +633,7 @@
sp<Fence> fence;
ASSERT_EQ(NO_INIT, mProducer->dequeueBuffer(&slot, &fence, DEFAULT_WIDTH,
- DEFAULT_HEIGHT, DEFAULT_FORMAT, TEST_PRODUCER_USAGE_BITS));
+ DEFAULT_HEIGHT, DEFAULT_FORMAT, TEST_PRODUCER_USAGE_BITS, nullptr));
}
TEST_F(IGraphicBufferProducerTest,
@@ -659,7 +653,8 @@
ASSERT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
(mProducer->dequeueBuffer(&slot, &fence, DEFAULT_WIDTH,
- DEFAULT_HEIGHT, DEFAULT_FORMAT, TEST_PRODUCER_USAGE_BITS)));
+ DEFAULT_HEIGHT, DEFAULT_FORMAT, TEST_PRODUCER_USAGE_BITS,
+ nullptr)));
EXPECT_LE(0, slot);
EXPECT_GT(BufferQueue::NUM_BUFFER_SLOTS, slot);
diff --git a/libs/gui/tests/StreamSplitter_test.cpp b/libs/gui/tests/StreamSplitter_test.cpp
index 498492e..80e30da 100644
--- a/libs/gui/tests/StreamSplitter_test.cpp
+++ b/libs/gui/tests/StreamSplitter_test.cpp
@@ -81,7 +81,7 @@
sp<GraphicBuffer> buffer;
ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
inputProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
- GRALLOC_USAGE_SW_WRITE_OFTEN));
+ GRALLOC_USAGE_SW_WRITE_OFTEN, nullptr));
ASSERT_EQ(OK, inputProducer->requestBuffer(slot, &buffer));
uint32_t* dataIn;
@@ -115,7 +115,7 @@
// received the buffer back from the output BufferQueue
ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
inputProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
- GRALLOC_USAGE_SW_WRITE_OFTEN));
+ GRALLOC_USAGE_SW_WRITE_OFTEN, nullptr));
}
TEST_F(StreamSplitterTest, OneInputMultipleOutputs) {
@@ -153,7 +153,7 @@
sp<GraphicBuffer> buffer;
ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
inputProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
- GRALLOC_USAGE_SW_WRITE_OFTEN));
+ GRALLOC_USAGE_SW_WRITE_OFTEN, nullptr));
ASSERT_EQ(OK, inputProducer->requestBuffer(slot, &buffer));
uint32_t* dataIn;
@@ -190,7 +190,7 @@
// received the buffer back from the output BufferQueues
ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
inputProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
- GRALLOC_USAGE_SW_WRITE_OFTEN));
+ GRALLOC_USAGE_SW_WRITE_OFTEN, nullptr));
}
TEST_F(StreamSplitterTest, OutputAbandonment) {
@@ -217,7 +217,7 @@
sp<GraphicBuffer> buffer;
ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
inputProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
- GRALLOC_USAGE_SW_WRITE_OFTEN));
+ GRALLOC_USAGE_SW_WRITE_OFTEN, nullptr));
ASSERT_EQ(OK, inputProducer->requestBuffer(slot, &buffer));
// Abandon the output
@@ -230,7 +230,7 @@
// Input should be abandoned
ASSERT_EQ(NO_INIT, inputProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
- GRALLOC_USAGE_SW_WRITE_OFTEN));
+ GRALLOC_USAGE_SW_WRITE_OFTEN, nullptr));
}
} // namespace android
diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
index d5a02e3..3d3df76 100644
--- a/opengl/libs/EGL/eglApi.cpp
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -1218,7 +1218,6 @@
if (!s->win.get()) {
return setError(EGL_BAD_SURFACE, EGL_FALSE);
}
- s->enableTimestamps = value;
int err = native_window_enable_frame_timestamps(
s->win.get(), value ? true : false);
return (err == NO_ERROR) ? EGL_TRUE :
@@ -2040,7 +2039,7 @@
egl_surface_t const * const s = get_surface(surface);
- if (!s->enableTimestamps) {
+ if (!s->win.get()) {
return setError(EGL_BAD_SURFACE, EGL_FALSE);
}
@@ -2090,6 +2089,8 @@
return EGL_TRUE;
case NAME_NOT_FOUND:
return setError(EGL_BAD_ACCESS, EGL_FALSE);
+ case INVALID_OPERATION:
+ return setError(EGL_BAD_SURFACE, EGL_FALSE);
case BAD_VALUE:
return setError(EGL_BAD_PARAMETER, EGL_FALSE);
default:
diff --git a/opengl/libs/EGL/egl_object.cpp b/opengl/libs/EGL/egl_object.cpp
index 6a76737..7fc5609 100644
--- a/opengl/libs/EGL/egl_object.cpp
+++ b/opengl/libs/EGL/egl_object.cpp
@@ -68,7 +68,7 @@
EGLNativeWindowType win, EGLSurface surface,
egl_connection_t const* cnx) :
egl_object_t(dpy), surface(surface), config(config), win(win), cnx(cnx),
- enableTimestamps(false), connected(true)
+ connected(true)
{}
egl_surface_t::~egl_surface_t() {
diff --git a/opengl/libs/EGL/egl_object.h b/opengl/libs/EGL/egl_object.h
index 3150ba6..8ceba1d 100644
--- a/opengl/libs/EGL/egl_object.h
+++ b/opengl/libs/EGL/egl_object.h
@@ -139,7 +139,6 @@
EGLConfig config;
sp<ANativeWindow> win;
egl_connection_t const* cnx;
- bool enableTimestamps;
private:
bool connected;
void disconnect();
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
index 69902e2..9de74d6 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
@@ -340,7 +340,7 @@
LOG_FATAL_IF(mDisplayId < 0, "mDisplayId=%d but should not be < 0.", mDisplayId);
status_t result = mSource[source]->dequeueBuffer(sslot, fence,
- mSinkBufferWidth, mSinkBufferHeight, format, usage);
+ mSinkBufferWidth, mSinkBufferHeight, format, usage, nullptr);
if (result < 0)
return result;
int pslot = mapSource2ProducerSlot(source, *sslot);
@@ -379,9 +379,12 @@
}
status_t VirtualDisplaySurface::dequeueBuffer(int* pslot, sp<Fence>* fence,
- uint32_t w, uint32_t h, PixelFormat format, uint32_t usage) {
- if (mDisplayId < 0)
- return mSource[SOURCE_SINK]->dequeueBuffer(pslot, fence, w, h, format, usage);
+ uint32_t w, uint32_t h, PixelFormat format, uint32_t usage,
+ FrameEventHistoryDelta* outTimestamps) {
+ if (mDisplayId < 0) {
+ return mSource[SOURCE_SINK]->dequeueBuffer(
+ pslot, fence, w, h, format, usage, outTimestamps);
+ }
VDS_LOGW_IF(mDbgState != DBG_STATE_PREPARED,
"Unexpected dequeueBuffer() in %s state", dbgStateStr());
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
index 70f717f..b435bf5 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
@@ -104,7 +104,8 @@
virtual status_t setMaxDequeuedBufferCount(int maxDequeuedBuffers);
virtual status_t setAsyncMode(bool async);
virtual status_t dequeueBuffer(int* pslot, sp<Fence>* fence, uint32_t w,
- uint32_t h, PixelFormat format, uint32_t usage);
+ uint32_t h, PixelFormat format, uint32_t usage,
+ FrameEventHistoryDelta *outTimestamps);
virtual status_t detachBuffer(int slot);
virtual status_t detachNextBuffer(sp<GraphicBuffer>* outBuffer,
sp<Fence>* outFence);
diff --git a/services/surfaceflinger/MonitoredProducer.cpp b/services/surfaceflinger/MonitoredProducer.cpp
index a2cc531..359ca4e 100644
--- a/services/surfaceflinger/MonitoredProducer.cpp
+++ b/services/surfaceflinger/MonitoredProducer.cpp
@@ -66,8 +66,10 @@
}
status_t MonitoredProducer::dequeueBuffer(int* slot, sp<Fence>* fence,
- uint32_t w, uint32_t h, PixelFormat format, uint32_t usage) {
- return mProducer->dequeueBuffer(slot, fence, w, h, format, usage);
+ uint32_t w, uint32_t h, PixelFormat format, uint32_t usage,
+ FrameEventHistoryDelta* outTimestamps) {
+ return mProducer->dequeueBuffer(
+ slot, fence, w, h, format, usage, outTimestamps);
}
status_t MonitoredProducer::detachBuffer(int slot) {
diff --git a/services/surfaceflinger/MonitoredProducer.h b/services/surfaceflinger/MonitoredProducer.h
index 3e64cae..17adaa7 100644
--- a/services/surfaceflinger/MonitoredProducer.h
+++ b/services/surfaceflinger/MonitoredProducer.h
@@ -38,7 +38,8 @@
virtual status_t setMaxDequeuedBufferCount(int maxDequeuedBuffers);
virtual status_t setAsyncMode(bool async);
virtual status_t dequeueBuffer(int* slot, sp<Fence>* fence, uint32_t w,
- uint32_t h, PixelFormat format, uint32_t usage);
+ uint32_t h, PixelFormat format, uint32_t usage,
+ FrameEventHistoryDelta* outTimestamps);
virtual status_t detachBuffer(int slot);
virtual status_t detachNextBuffer(sp<GraphicBuffer>* outBuffer,
sp<Fence>* outFence);