summaryrefslogtreecommitdiff
path: root/libs/gui/Surface.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libs/gui/Surface.cpp')
-rw-r--r--libs/gui/Surface.cpp67
1 files changed, 52 insertions, 15 deletions
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index c29101e4a0..6a02a77592 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -52,7 +52,8 @@ Surface::Surface(
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 @@ status_t Surface::getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer,
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 @@ status_t Surface::getFrameTimestamps(uint64_t frameNumber,
Mutex::Autolock lock(mMutex);
+ if (!mEnableFrameTimestamps) {
+ return INVALID_OPERATION;
+ }
+
// Verify the requested timestamps are supported.
querySupportedTimestampsLocked();
if (outDisplayPresentTime != nullptr && !mFrameTimestampsSupportsPresent) {
@@ -308,6 +318,7 @@ int Surface::dequeueBuffer(android_native_buffer_t** buffer, int* fenceFd) {
uint32_t reqHeight;
PixelFormat reqFormat;
uint32_t reqUsage;
+ bool enableFrameTimestamps;
{
Mutex::Autolock lock(mMutex);
@@ -318,6 +329,8 @@ int Surface::dequeueBuffer(android_native_buffer_t** buffer, int* fenceFd) {
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 Surface::dequeueBuffer(android_native_buffer_t** buffer, int* fenceFd) {
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 @@ int Surface::dequeueBuffer(android_native_buffer_t** buffer, int* fenceFd) {
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 @@ int Surface::queueBuffer(android_native_buffer_t* buffer, int fenceFd) {
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 @@ int Surface::queueBuffer(android_native_buffer_t* buffer, int fenceFd) {
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 @@ int Surface::perform(int operation, va_list args)
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 @@ int Surface::dispatchSetAutoRefresh(va_list args) {
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 @@ int Surface::connect(int api, const sp<IProducerListener>& listener) {
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;