From ce796e78a57018f186b062199c75d94545318aca Mon Sep 17 00:00:00 2001 From: Pablo Ceballos Date: Thu, 4 Feb 2016 19:10:51 -0800 Subject: [PATCH] Plumbing for getting FenceTracker timestamps Change-Id: I1ebee9e42e28658bd3a2b161fdaabb7da756d8f3 --- include/gui/BufferQueue.h | 2 + include/gui/BufferQueueProducer.h | 4 ++ include/gui/FrameTimestamps.h | 45 ++++++++++++++++ include/gui/IConsumerListener.h | 7 +++ include/gui/IGraphicBufferProducer.h | 10 ++++ include/gui/Surface.h | 7 +++ libs/gui/BufferQueue.cpp | 9 ++++ libs/gui/BufferQueueProducer.cpp | 16 ++++++ libs/gui/IConsumerListener.cpp | 61 ++++++++++++++++++++++ libs/gui/IGraphicBufferProducer.cpp | 61 ++++++++++++++++++++++ libs/gui/Surface.cpp | 50 ++++++++++++++++++ services/surfaceflinger/FenceTracker.cpp | 47 ++++++++++++++--- services/surfaceflinger/FenceTracker.h | 4 +- services/surfaceflinger/Layer.cpp | 3 +- services/surfaceflinger/Layer.h | 5 ++ services/surfaceflinger/SurfaceFlinger.cpp | 5 ++ services/surfaceflinger/SurfaceFlinger.h | 3 ++ services/surfaceflinger/SurfaceFlingerConsumer.cpp | 7 +++ services/surfaceflinger/SurfaceFlingerConsumer.h | 12 ++++- services/surfaceflinger/SurfaceFlinger_hwc1.cpp | 5 ++ 20 files changed, 353 insertions(+), 10 deletions(-) create mode 100644 include/gui/FrameTimestamps.h diff --git a/include/gui/BufferQueue.h b/include/gui/BufferQueue.h index 09300a20c9..fe4b1fa830 100644 --- a/include/gui/BufferQueue.h +++ b/include/gui/BufferQueue.h @@ -66,6 +66,8 @@ public: virtual void onFrameReplaced(const BufferItem& item) override; virtual void onBuffersReleased() override; virtual void onSidebandStreamChanged() override; + virtual bool getFrameTimestamps(uint64_t frameNumber, + FrameTimestamps* outTimestamps) const override; private: // mConsumerListener is a weak reference to the IConsumerListener. This is // the raison d'etre of ProxyConsumerListener. diff --git a/include/gui/BufferQueueProducer.h b/include/gui/BufferQueueProducer.h index a75ed98b57..a85bbb7974 100644 --- a/include/gui/BufferQueueProducer.h +++ b/include/gui/BufferQueueProducer.h @@ -186,6 +186,10 @@ public: virtual status_t getLastQueuedBuffer(sp* outBuffer, sp* outFence, float outTransformMatrix[16]) override; + // See IGraphicBufferProducer::getFrameTimestamps + virtual bool getFrameTimestamps(uint64_t frameNumber, + FrameTimestamps* outTimestamps) const override; + private: // This is required by the IBinder::DeathRecipient interface virtual void binderDied(const wp& who); diff --git a/include/gui/FrameTimestamps.h b/include/gui/FrameTimestamps.h new file mode 100644 index 0000000000..4dc7467029 --- /dev/null +++ b/include/gui/FrameTimestamps.h @@ -0,0 +1,45 @@ +/* + * Copyright 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_GUI_FRAMETIMESTAMPS_H +#define ANDROID_GUI_FRAMETIMESTAMPS_H + +#include +#include + +namespace android { + +struct FrameTimestamps : public LightFlattenablePod { + FrameTimestamps() : + frameNumber(0), + postedTime(0), + acquireTime(0), + refreshStartTime(0), + glCompositionDoneTime(0), + displayRetireTime(0), + releaseTime(0) {} + + uint64_t frameNumber; + nsecs_t postedTime; + nsecs_t acquireTime; + nsecs_t refreshStartTime; + nsecs_t glCompositionDoneTime; + nsecs_t displayRetireTime; + nsecs_t releaseTime; +}; + +} // namespace android +#endif diff --git a/include/gui/IConsumerListener.h b/include/gui/IConsumerListener.h index 3f39799564..1efcf3cfb5 100644 --- a/include/gui/IConsumerListener.h +++ b/include/gui/IConsumerListener.h @@ -25,6 +25,8 @@ #include +#include + namespace android { // ---------------------------------------------------------------------------- @@ -78,6 +80,11 @@ public: // stream is first attached and when it is either detached or replaced by a // different stream. virtual void onSidebandStreamChanged() = 0; /* Asynchronous */ + + // See IGraphicBufferProducer::getFrameTimestamps + // This queries the consumer for the timestamps + virtual bool getFrameTimestamps(uint64_t /*frameNumber*/, + FrameTimestamps* /*outTimestamps*/) const { return false; } }; diff --git a/include/gui/IGraphicBufferProducer.h b/include/gui/IGraphicBufferProducer.h index 37ae6df39e..0c24606823 100644 --- a/include/gui/IGraphicBufferProducer.h +++ b/include/gui/IGraphicBufferProducer.h @@ -30,6 +30,8 @@ #include #include +#include + namespace android { // ---------------------------------------------------------------------------- @@ -568,6 +570,14 @@ public: // Returns NO_ERROR or the status of the Binder transaction virtual status_t getLastQueuedBuffer(sp* outBuffer, sp* outFence, float outTransformMatrix[16]) = 0; + + // Attempts to retrieve timestamp information for the given frame number. + // If information for the given frame number is not found, returns false. + // Returns true otherwise. + // + // If a fence has not yet signaled the timestamp returned will be 0; + virtual bool getFrameTimestamps(uint64_t /*frameNumber*/, + FrameTimestamps* /*outTimestamps*/) const { return false; } }; // ---------------------------------------------------------------------------- diff --git a/include/gui/Surface.h b/include/gui/Surface.h index 646203bd9a..7d9d901df2 100644 --- a/include/gui/Surface.h +++ b/include/gui/Surface.h @@ -134,6 +134,12 @@ public: status_t getLastQueuedBuffer(sp* outBuffer, sp* outFence, float outTransformMatrix[16]); + // See IGraphicBufferProducer::getFrameTimestamps + bool getFrameTimestamps(uint64_t frameNumber, nsecs_t* outPostedTime, + nsecs_t* outAcquireTime, nsecs_t* outRefreshStartTime, + nsecs_t* outGlCompositionDoneTime, nsecs_t* outDisplayRetireTime, + nsecs_t* outReleaseTime); + protected: virtual ~Surface(); @@ -183,6 +189,7 @@ private: int dispatchSetSurfaceDamage(va_list args); int dispatchSetSharedBufferMode(va_list args); int dispatchSetAutoRefresh(va_list args); + int dispatchGetFrameTimestamps(va_list args); protected: virtual int dequeueBuffer(ANativeWindowBuffer** buffer, int* fenceFd); diff --git a/libs/gui/BufferQueue.cpp b/libs/gui/BufferQueue.cpp index ccbb5a25f3..6de98f5a25 100644 --- a/libs/gui/BufferQueue.cpp +++ b/libs/gui/BufferQueue.cpp @@ -61,6 +61,15 @@ void BufferQueue::ProxyConsumerListener::onSidebandStreamChanged() { } } +bool BufferQueue::ProxyConsumerListener::getFrameTimestamps( + uint64_t frameNumber, FrameTimestamps* outTimestamps) const { + sp listener(mConsumerListener.promote()); + if (listener != NULL) { + return listener->getFrameTimestamps(frameNumber, outTimestamps); + } + return false; +} + void BufferQueue::createBufferQueue(sp* outProducer, sp* outConsumer, const sp& allocator) { diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp index 65f8255dec..ac7ac07490 100644 --- a/libs/gui/BufferQueueProducer.cpp +++ b/libs/gui/BufferQueueProducer.cpp @@ -1401,6 +1401,22 @@ status_t BufferQueueProducer::getLastQueuedBuffer(sp* outBuffer, return NO_ERROR; } +bool BufferQueueProducer::getFrameTimestamps(uint64_t frameNumber, + FrameTimestamps* outTimestamps) const { + ATRACE_CALL(); + BQ_LOGV("getFrameTimestamps, %" PRIu64, frameNumber); + sp listener; + + { + Mutex::Autolock lock(mCore->mMutex); + listener = mCore->mConsumerListener; + } + if (listener != NULL) { + return listener->getFrameTimestamps(frameNumber, outTimestamps); + } + return false; +} + void BufferQueueProducer::binderDied(const wp& /* who */) { // If we're here, it means that a producer we were connected to died. // We're guaranteed that we are still connected to it because we remove diff --git a/libs/gui/IConsumerListener.cpp b/libs/gui/IConsumerListener.cpp index cab7dc3d5a..9a06011ce0 100644 --- a/libs/gui/IConsumerListener.cpp +++ b/libs/gui/IConsumerListener.cpp @@ -31,6 +31,7 @@ enum { ON_FRAME_AVAILABLE = IBinder::FIRST_CALL_TRANSACTION, ON_BUFFER_RELEASED, ON_SIDEBAND_STREAM_CHANGED, + GET_FRAME_TIMESTAMPS }; class BpConsumerListener : public BpInterface @@ -60,6 +61,42 @@ public: data.writeInterfaceToken(IConsumerListener::getInterfaceDescriptor()); remote()->transact(ON_SIDEBAND_STREAM_CHANGED, data, &reply, IBinder::FLAG_ONEWAY); } + + virtual bool getFrameTimestamps(uint64_t frameNumber, + FrameTimestamps* outTimestamps) const { + Parcel data, reply; + status_t result = data.writeInterfaceToken( + IConsumerListener::getInterfaceDescriptor()); + if (result != NO_ERROR) { + ALOGE("getFrameTimestamps failed to write token: %d", result); + return false; + } + result = data.writeUint64(frameNumber); + if (result != NO_ERROR) { + ALOGE("getFrameTimestamps failed to write: %d", result); + return false; + } + result = remote()->transact(GET_FRAME_TIMESTAMPS, data, &reply); + if (result != NO_ERROR) { + ALOGE("getFrameTimestamps failed to transact: %d", result); + return false; + } + bool found = false; + result = reply.readBool(&found); + if (result != NO_ERROR) { + ALOGE("getFrameTimestamps failed to read: %d", result); + return false; + } + if (found) { + result = reply.read(*outTimestamps); + if (result != NO_ERROR) { + ALOGE("getFrameTimestamps failed to read timestamps: %d", + result); + return false; + } + } + return found; + } }; // Out-of-line virtual method definition to trigger vtable emission in this @@ -88,6 +125,30 @@ status_t BnConsumerListener::onTransact( CHECK_INTERFACE(IConsumerListener, data, reply); onSidebandStreamChanged(); return NO_ERROR; } + case GET_FRAME_TIMESTAMPS: { + CHECK_INTERFACE(IConsumerListener, data, reply); + uint64_t frameNumber = 0; + status_t result = data.readUint64(&frameNumber); + if (result != NO_ERROR) { + ALOGE("onTransact failed to read: %d", result); + return result; + } + FrameTimestamps timestamps; + bool found = getFrameTimestamps(frameNumber, ×tamps); + result = reply->writeBool(found); + if (result != NO_ERROR) { + ALOGE("onTransact failed to write: %d", result); + return result; + } + if (found) { + result = reply->write(timestamps); + if (result != NO_ERROR) { + ALOGE("onTransact failed to write timestamps: %d", result); + return result; + } + } + return NO_ERROR; + } } return BBinder::onTransact(code, data, reply, flags); } diff --git a/libs/gui/IGraphicBufferProducer.cpp b/libs/gui/IGraphicBufferProducer.cpp index 2c48d83d96..9317eff3e7 100644 --- a/libs/gui/IGraphicBufferProducer.cpp +++ b/libs/gui/IGraphicBufferProducer.cpp @@ -55,6 +55,7 @@ enum { SET_AUTO_REFRESH, SET_DEQUEUE_TIMEOUT, GET_LAST_QUEUED_BUFFER, + GET_FRAME_TIMESTAMPS }; class BpGraphicBufferProducer : public BpInterface @@ -418,6 +419,42 @@ public: *outFence = fence; return result; } + + virtual bool getFrameTimestamps(uint64_t frameNumber, + FrameTimestamps* outTimestamps) const { + Parcel data, reply; + status_t result = data.writeInterfaceToken( + IGraphicBufferProducer::getInterfaceDescriptor()); + if (result != NO_ERROR) { + ALOGE("getFrameTimestamps failed to write token: %d", result); + return false; + } + result = data.writeUint64(frameNumber); + if (result != NO_ERROR) { + ALOGE("getFrameTimestamps failed to write: %d", result); + return false; + } + result = remote()->transact(GET_FRAME_TIMESTAMPS, data, &reply); + if (result != NO_ERROR) { + ALOGE("getFrameTimestamps failed to transact: %d", result); + return false; + } + bool found = false; + result = reply.readBool(&found); + if (result != NO_ERROR) { + ALOGE("getFrameTimestamps failed to read: %d", result); + return false; + } + if (found) { + result = reply.read(*outTimestamps); + if (result != NO_ERROR) { + ALOGE("getFrameTimestamps failed to read timestamps: %d", + result); + return false; + } + } + return found; + } }; // Out-of-line virtual method definition to trigger vtable emission in this @@ -659,6 +696,30 @@ status_t BnGraphicBufferProducer::onTransact( } return NO_ERROR; } + case GET_FRAME_TIMESTAMPS: { + CHECK_INTERFACE(IGraphicBufferProducer, data, reply); + uint64_t frameNumber = 0; + status_t result = data.readUint64(&frameNumber); + if (result != NO_ERROR) { + ALOGE("onTransact failed to read: %d", result); + return result; + } + FrameTimestamps timestamps; + bool found = getFrameTimestamps(frameNumber, ×tamps); + result = reply->writeBool(found); + if (result != NO_ERROR) { + ALOGE("onTransact failed to write: %d", result); + return result; + } + if (found) { + result = reply->write(timestamps); + if (result != NO_ERROR) { + ALOGE("onTransact failed to write timestamps: %d", result); + return result; + } + } + return NO_ERROR; + } } return BBinder::onTransact(code, data, reply, flags); } diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp index 6811269a39..85c194d457 100644 --- a/libs/gui/Surface.cpp +++ b/libs/gui/Surface.cpp @@ -133,6 +133,39 @@ status_t Surface::getLastQueuedBuffer(sp* outBuffer, outTransformMatrix); } +bool Surface::getFrameTimestamps(uint64_t frameNumber, nsecs_t* outPostedTime, + nsecs_t* outAcquireTime, nsecs_t* outRefreshStartTime, + nsecs_t* outGlCompositionDoneTime, nsecs_t* outDisplayRetireTime, + nsecs_t* outReleaseTime) { + ATRACE_CALL(); + + FrameTimestamps timestamps; + bool found = mGraphicBufferProducer->getFrameTimestamps(frameNumber, + ×tamps); + if (found) { + if (outPostedTime) { + *outPostedTime = timestamps.postedTime; + } + if (outAcquireTime) { + *outAcquireTime = timestamps.acquireTime; + } + if (outRefreshStartTime) { + *outRefreshStartTime = timestamps.refreshStartTime; + } + if (outGlCompositionDoneTime) { + *outGlCompositionDoneTime = timestamps.glCompositionDoneTime; + } + if (outDisplayRetireTime) { + *outDisplayRetireTime = timestamps.displayRetireTime; + } + if (outReleaseTime) { + *outReleaseTime = timestamps.releaseTime; + } + return true; + } + return false; +} + int Surface::hook_setSwapInterval(ANativeWindow* window, int interval) { Surface* c = getSelf(window); return c->setSwapInterval(interval); @@ -614,6 +647,9 @@ int Surface::perform(int operation, va_list args) case NATIVE_WINDOW_SET_AUTO_REFRESH: res = dispatchSetAutoRefresh(args); break; + case NATIVE_WINDOW_GET_FRAME_TIMESTAMPS: + res = dispatchGetFrameTimestamps(args); + break; default: res = NAME_NOT_FOUND; break; @@ -734,6 +770,20 @@ int Surface::dispatchSetAutoRefresh(va_list args) { return setAutoRefresh(autoRefresh); } +int Surface::dispatchGetFrameTimestamps(va_list args) { + uint32_t framesAgo = va_arg(args, uint32_t); + nsecs_t* outPostedTime = va_arg(args, int64_t*); + nsecs_t* outAcquireTime = va_arg(args, int64_t*); + nsecs_t* outRefreshStartTime = va_arg(args, int64_t*); + nsecs_t* outGlCompositionDoneTime = va_arg(args, int64_t*); + nsecs_t* outDisplayRetireTime = va_arg(args, int64_t*); + nsecs_t* outReleaseTime = va_arg(args, int64_t*); + bool ret = getFrameTimestamps(getNextFrameNumber() - 1 - framesAgo, + outPostedTime, outAcquireTime, outRefreshStartTime, + outGlCompositionDoneTime, outDisplayRetireTime, outReleaseTime); + return ret ? NO_ERROR : BAD_VALUE; +} + int Surface::connect(int api) { static sp listener = new DummyProducerListener(); return connect(api, listener); diff --git a/services/surfaceflinger/FenceTracker.cpp b/services/surfaceflinger/FenceTracker.cpp index d415bd5ed8..3ff9bbfad6 100644 --- a/services/surfaceflinger/FenceTracker.cpp +++ b/services/surfaceflinger/FenceTracker.cpp @@ -26,7 +26,9 @@ namespace android { FenceTracker::FenceTracker() : mFrameCounter(0), mOffset(0), - mFrames() {} + mFrames(), + mMutex() { +} void FenceTracker::dump(String8* outString) { Mutex::Autolock lock(mMutex); @@ -135,7 +137,7 @@ void FenceTracker::addFrame(nsecs_t refreshStartTime, sp retireFence, nsecs_t postedTime; sp acquireFence; sp prevReleaseFence; - int32_t key = layers[i]->getSequence(); + int32_t layerId = layers[i]->getSequence(); layers[i]->getFenceData(&name, &frameNumber, &glesComposition, &postedTime, &acquireFence, &prevReleaseFence); @@ -144,13 +146,17 @@ void FenceTracker::addFrame(nsecs_t refreshStartTime, sp retireFence, frame.layers.emplace(std::piecewise_construct, std::forward_as_tuple(key), std::forward_as_tuple(name, frameNumber, glesComposition, - postedTime, 0, 0, acquireFence, prevReleaseFence)); + postedTime, FrameTimestamps::INVALID_TIME, + FrameTimestamps::INVALID_TIME, acquireFence, + prevReleaseFence)); wasGlesCompositionDone = true; } else { frame.layers.emplace(std::piecewise_construct, std::forward_as_tuple(key), std::forward_as_tuple(name, frameNumber, glesComposition, - postedTime, 0, 0, acquireFence, Fence::NO_FENCE)); + postedTime, FrameTimestamps::INVALID_TIME, + FrameTimestamps::INVALID_TIME, acquireFence, + Fence::NO_FENCE)); auto prevLayer = prevFrame.layers.find(key); if (prevLayer != prevFrame.layers.end()) { @@ -159,7 +165,7 @@ void FenceTracker::addFrame(nsecs_t refreshStartTime, sp retireFence, } #else frame.layers.emplace(std::piecewise_construct, - std::forward_as_tuple(key), + std::forward_as_tuple(layerId), std::forward_as_tuple(name, frameNumber, glesComposition, postedTime, 0, 0, acquireFence, glesComposition ? Fence::NO_FENCE : prevReleaseFence)); @@ -168,7 +174,7 @@ void FenceTracker::addFrame(nsecs_t refreshStartTime, sp retireFence, } #endif frame.layers.emplace(std::piecewise_construct, - std::forward_as_tuple(key), + std::forward_as_tuple(layerId), std::forward_as_tuple(name, frameNumber, glesComposition, postedTime, 0, 0, acquireFence, prevReleaseFence)); } @@ -186,4 +192,33 @@ void FenceTracker::addFrame(nsecs_t refreshStartTime, sp retireFence, mFrameCounter++; } +bool FenceTracker::getFrameTimestamps(const Layer& layer, + uint64_t frameNumber, FrameTimestamps* outTimestamps) { + Mutex::Autolock lock(mMutex); + checkFencesForCompletion(); + int32_t layerId = layer.getSequence(); + + size_t i = 0; + for (; i < MAX_FRAME_HISTORY; i++) { + if (mFrames[i].layers.count(layerId) && + mFrames[i].layers[layerId].frameNumber == frameNumber) { + break; + } + } + if (i == MAX_FRAME_HISTORY) { + return false; + } + + const FrameRecord& frameRecord = mFrames[i]; + const LayerRecord& layerRecord = mFrames[i].layers[layerId]; + outTimestamps->frameNumber = frameNumber; + outTimestamps->postedTime = layerRecord.postedTime; + outTimestamps->acquireTime = layerRecord.acquireTime; + outTimestamps->refreshStartTime = frameRecord.refreshStartTime; + outTimestamps->glCompositionDoneTime = frameRecord.glesCompositionDoneTime; + outTimestamps->displayRetireTime = frameRecord.retireTime; + outTimestamps->releaseTime = layerRecord.releaseTime; + return true; +} + } // namespace android diff --git a/services/surfaceflinger/FenceTracker.h b/services/surfaceflinger/FenceTracker.h index 2fcc314117..4cb14a539d 100644 --- a/services/surfaceflinger/FenceTracker.h +++ b/services/surfaceflinger/FenceTracker.h @@ -29,7 +29,7 @@ namespace android { class Layer; - +struct FrameTimestamps; /* * Keeps a circular buffer of fence/timestamp data for the last N frames in * SurfaceFlinger. Gets timestamps for fences after they have signaled. @@ -40,6 +40,8 @@ public: void dump(String8* outString); void addFrame(nsecs_t refreshStartTime, sp retireFence, const Vector>& layers, sp glDoneFence); + bool getFrameTimestamps(const Layer& layer, uint64_t frameNumber, + FrameTimestamps* outTimestamps); protected: static constexpr size_t MAX_FRAME_HISTORY = 8; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index abf0e6ce07..15e5615316 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -154,7 +154,8 @@ void Layer::onFirstRef() { sp consumer; BufferQueue::createBufferQueue(&producer, &consumer); mProducer = new MonitoredProducer(producer, mFlinger); - mSurfaceFlingerConsumer = new SurfaceFlingerConsumer(consumer, mTextureName); + mSurfaceFlingerConsumer = new SurfaceFlingerConsumer(consumer, mTextureName, + this); mSurfaceFlingerConsumer->setConsumerUsageBits(getEffectiveUsage(0)); mSurfaceFlingerConsumer->setContentsChangedListener(this); mSurfaceFlingerConsumer->setName(mName); diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 79750a6d42..fef2d981d6 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -409,6 +409,11 @@ public: std::vector getOccupancyHistory(bool forceFlush); + bool getFrameTimestamps(uint64_t frameNumber, + FrameTimestamps* outTimestamps) const { + return mFlinger->getFrameTimestamps(*this, frameNumber, outTimestamps); + } + protected: // constant sp mFlinger; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 0276d38243..0dc04ebe0a 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -3606,6 +3606,11 @@ void SurfaceFlinger::checkScreenshot(size_t w, size_t s, size_t h, void const* v } } +bool SurfaceFlinger::getFrameTimestamps(const Layer& layer, + uint64_t frameNumber, FrameTimestamps* outTimestamps) { + return mFenceTracker.getFrameTimestamps(layer, frameNumber, outTimestamps); +} + // --------------------------------------------------------------------------- SurfaceFlinger::LayerVector::LayerVector() { diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 8263994859..28666e2aa5 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -440,6 +440,9 @@ private: std::vector&& history); void dumpBufferingStats(String8& result) const; + bool getFrameTimestamps(const Layer& layer, uint64_t frameNumber, + FrameTimestamps* outTimestamps); + /* ------------------------------------------------------------------------ * Attributes */ diff --git a/services/surfaceflinger/SurfaceFlingerConsumer.cpp b/services/surfaceflinger/SurfaceFlingerConsumer.cpp index c71b3bcbfd..ba0a527ebc 100644 --- a/services/surfaceflinger/SurfaceFlingerConsumer.cpp +++ b/services/surfaceflinger/SurfaceFlingerConsumer.cpp @@ -18,6 +18,7 @@ //#define LOG_NDEBUG 0 #include "SurfaceFlingerConsumer.h" +#include "Layer.h" #include @@ -251,6 +252,12 @@ void SurfaceFlingerConsumer::onSidebandStreamChanged() { } } +bool SurfaceFlingerConsumer::getFrameTimestamps(uint64_t frameNumber, + FrameTimestamps* outTimestamps) const { + sp l = mLayer.promote(); + return l.get() ? l->getFrameTimestamps(frameNumber, outTimestamps) : false; +} + // --------------------------------------------------------------------------- }; // namespace android diff --git a/services/surfaceflinger/SurfaceFlingerConsumer.h b/services/surfaceflinger/SurfaceFlingerConsumer.h index 51b002f991..37626591a7 100644 --- a/services/surfaceflinger/SurfaceFlingerConsumer.h +++ b/services/surfaceflinger/SurfaceFlingerConsumer.h @@ -23,6 +23,8 @@ namespace android { // ---------------------------------------------------------------------------- +class Layer; + /* * This is a thin wrapper around GLConsumer. */ @@ -35,10 +37,10 @@ public: }; SurfaceFlingerConsumer(const sp& consumer, - uint32_t tex) + uint32_t tex, const Layer* layer) : GLConsumer(consumer, tex, GLConsumer::TEXTURE_EXTERNAL, false, false), mTransformToDisplayInverse(false), mSurfaceDamage(), - mPrevReleaseFence(Fence::NO_FENCE) + mPrevReleaseFence(Fence::NO_FENCE), mLayer(layer) {} class BufferRejecter { @@ -82,6 +84,9 @@ public: void releasePendingBuffer(); #endif + virtual bool getFrameTimestamps(uint64_t frameNumber, + FrameTimestamps* outTimestamps) const override; + private: virtual void onSidebandStreamChanged(); @@ -103,6 +108,9 @@ private: // The release fence of the already displayed buffer (previous frame). sp mPrevReleaseFence; + + // The layer for this SurfaceFlingerConsumer + wp mLayer; }; // ---------------------------------------------------------------------------- diff --git a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp index 71d7cf976f..f4061e7de1 100644 --- a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp +++ b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp @@ -3593,6 +3593,11 @@ status_t SurfaceFlinger::captureScreenImplLocked( return result; } +bool SurfaceFlinger::getFrameTimestamps(const Layer& layer, + uint64_t frameNumber, FrameTimestamps* outTimestamps) { + return mFenceTracker.getFrameTimestamps(layer, frameNumber, outTimestamps); +} + void SurfaceFlinger::checkScreenshot(size_t w, size_t s, size_t h, void const* vaddr, const sp& hw, uint32_t minLayerZ, uint32_t maxLayerZ) { if (DEBUG_SCREENSHOTS) { -- 2.11.0