diff options
author | 2016-03-25 16:30:50 +0000 | |
---|---|---|
committer | 2016-03-25 16:30:50 +0000 | |
commit | 830f5004da53a83e23b4102ba9b72e4cb366cb34 (patch) | |
tree | ea9960192a5836d51c384a38dc52c18fc346cc03 | |
parent | a207fca4eda8c17389ea13ec3762ecb2a49d81be (diff) | |
parent | 40845df1285b387bcbf8f43ac72228eee2606d80 (diff) |
Merge "SF: Add FenceTracker" into nyc-dev
17 files changed, 369 insertions, 32 deletions
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk index 8cc9fc175b..d0a04014a5 100644 --- a/services/surfaceflinger/Android.mk +++ b/services/surfaceflinger/Android.mk @@ -10,6 +10,7 @@ LOCAL_SRC_FILES := \ DispSync.cpp \ EventControlThread.cpp \ EventThread.cpp \ + FenceTracker.cpp \ FrameTracker.cpp \ Layer.cpp \ LayerDim.cpp \ @@ -103,7 +104,7 @@ else endif LOCAL_CFLAGS += -fvisibility=hidden -Werror=format -LOCAL_CFLAGS += -std=c++11 +LOCAL_CFLAGS += -std=c++14 LOCAL_SHARED_LIBRARIES := \ libcutils \ @@ -133,7 +134,7 @@ LOCAL_CLANG := true LOCAL_LDFLAGS := -Wl,--version-script,art/sigchainlib/version-script.txt -Wl,--export-dynamic LOCAL_CFLAGS := -DLOG_TAG=\"SurfaceFlinger\" -LOCAL_CPPFLAGS := -std=c++11 +LOCAL_CPPFLAGS := -std=c++14 LOCAL_INIT_RC := surfaceflinger.rc @@ -172,7 +173,7 @@ include $(CLEAR_VARS) LOCAL_CLANG := true LOCAL_CFLAGS := -DLOG_TAG=\"SurfaceFlinger\" -LOCAL_CPPFLAGS := -std=c++11 +LOCAL_CPPFLAGS := -std=c++14 LOCAL_SRC_FILES := \ DdmConnection.cpp diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index 8d8e40d0da..f7c84738da 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -364,11 +364,9 @@ void DisplayDevice::setViewportAndProjection() const { false, Transform::ROT_0); } -#ifdef USE_HWC2 const sp<Fence>& DisplayDevice::getClientTargetAcquireFence() const { return mDisplaySurface->getClientTargetAcquireFence(); } -#endif // ---------------------------------------------------------------------------- diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h index 38241d994b..9ac8a97937 100644 --- a/services/surfaceflinger/DisplayDevice.h +++ b/services/surfaceflinger/DisplayDevice.h @@ -49,9 +49,7 @@ namespace android { struct DisplayInfo; class DisplaySurface; -#ifdef USE_HWC2 class Fence; -#endif class IGraphicBufferProducer; class Layer; class SurfaceFlinger; @@ -174,9 +172,7 @@ public: EGLBoolean makeCurrent(EGLDisplay dpy, EGLContext ctx) const; void setViewportAndProjection() const; -#ifdef USE_HWC2 const sp<Fence>& getClientTargetAcquireFence() const; -#endif /* ------------------------------------------------------------------------ * Display power mode management. diff --git a/services/surfaceflinger/DisplayHardware/DisplaySurface.h b/services/surfaceflinger/DisplayHardware/DisplaySurface.h index d819f8311b..d801bb3a98 100644 --- a/services/surfaceflinger/DisplayHardware/DisplaySurface.h +++ b/services/surfaceflinger/DisplayHardware/DisplaySurface.h @@ -76,9 +76,7 @@ public: virtual void resizeBuffers(const uint32_t w, const uint32_t h) = 0; -#ifdef USE_HWC2 virtual const sp<Fence>& getClientTargetAcquireFence() const = 0; -#endif protected: DisplaySurface() {} diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp index 29e0766383..7368d775ad 100644 --- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp +++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp @@ -60,15 +60,14 @@ FramebufferSurface::FramebufferSurface(HWComposer& hwc, int disp, ConsumerBase(consumer), mDisplayType(disp), mCurrentBufferSlot(-1), -#ifdef USE_HWC2 mCurrentBuffer(), mCurrentFence(Fence::NO_FENCE), +#ifdef USE_HWC2 mHwc(hwc), mHasPendingRelease(false), mPreviousBufferSlot(BufferQueue::INVALID_BUFFER_SLOT), mPreviousBuffer() #else - mCurrentBuffer(0), mHwc(hwc) #endif { @@ -168,9 +167,7 @@ status_t FramebufferSurface::nextBuffer(sp<GraphicBuffer>& outBuffer, sp<Fence>& } mCurrentBufferSlot = item.mSlot; mCurrentBuffer = mSlots[mCurrentBufferSlot].mGraphicBuffer; -#ifdef USE_HWC2 mCurrentFence = item.mFence; -#endif outFence = item.mFence; outBuffer = mCurrentBuffer; @@ -254,11 +251,9 @@ void FramebufferSurface::dumpLocked(String8& result, const char* prefix) const ConsumerBase::dumpLocked(result, prefix); } -#ifdef USE_HWC2 const sp<Fence>& FramebufferSurface::getClientTargetAcquireFence() const { return mCurrentFence; } -#endif // ---------------------------------------------------------------------------- }; // namespace android diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h index 0605602a10..439435ac50 100644 --- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h +++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h @@ -52,9 +52,7 @@ public: // displays. virtual void resizeBuffers(const uint32_t /*w*/, const uint32_t /*h*/) { }; -#ifdef USE_HWC2 virtual const sp<Fence>& getClientTargetAcquireFence() const override; -#endif private: virtual ~FramebufferSurface() { }; // this class cannot be overloaded @@ -88,10 +86,8 @@ private: // no current buffer. sp<GraphicBuffer> mCurrentBuffer; -#ifdef USE_HWC2 // mCurrentFence is the current buffer's acquire fence sp<Fence> mCurrentFence; -#endif // Hardware composer, owned by SurfaceFlinger. HWComposer& mHwc; diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp index 1afed360f6..ee4bf02555 100644 --- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp +++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp @@ -311,11 +311,9 @@ void VirtualDisplaySurface::resizeBuffers(const uint32_t w, const uint32_t h) { mSinkBufferHeight = h; } -#ifdef USE_HWC2 const sp<Fence>& VirtualDisplaySurface::getClientTargetAcquireFence() const { return mFbFence; } -#endif status_t VirtualDisplaySurface::requestBuffer(int pslot, sp<GraphicBuffer>* outBuf) { diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h index fe187c20a3..cfa4e4cb63 100644 --- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h +++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h @@ -90,9 +90,7 @@ public: virtual void onFrameCommitted(); virtual void dumpAsString(String8& result) const; virtual void resizeBuffers(const uint32_t w, const uint32_t h); -#ifdef USE_HWC2 virtual const sp<Fence>& getClientTargetAcquireFence() const override; -#endif private: enum Source {SOURCE_SINK = 0, SOURCE_SCRATCH = 1}; diff --git a/services/surfaceflinger/FenceTracker.cpp b/services/surfaceflinger/FenceTracker.cpp new file mode 100644 index 0000000000..7da1d936c1 --- /dev/null +++ b/services/surfaceflinger/FenceTracker.cpp @@ -0,0 +1,186 @@ +/* + * 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. + */ + +#include <inttypes.h> +#include "FenceTracker.h" +#include "Layer.h" + +namespace android { + +FenceTracker::FenceTracker() : + mFrameCounter(0), + mOffset(0), + mFrames() {} + +void FenceTracker::dump(String8* outString) { + Mutex::Autolock lock(mMutex); + checkFencesForCompletion(); + + for (size_t i = 0; i < MAX_FRAME_HISTORY; i++) { + int index = (mOffset + i) % MAX_FRAME_HISTORY; + const FrameRecord& frame = mFrames[index]; + + outString->appendFormat("Frame %" PRIu64 "\n", frame.frameId); + outString->appendFormat("- Refresh start\t%" PRId64 "\n", + frame.refreshStartTime); + + if (frame.glesCompositionDoneTime) { + outString->appendFormat("- GLES done\t%" PRId64 "\n", + frame.glesCompositionDoneTime); + } else if (frame.glesCompositionDoneFence != Fence::NO_FENCE) { + outString->append("- GLES done\tNot signaled\n"); + } + if (frame.retireTime) { + outString->appendFormat("- Retire\t%" PRId64 "\n", + frame.retireTime); + } else { + outString->append("- Retire\tNot signaled\n"); + } + for (const auto& kv : frame.layers) { + const LayerRecord& layer = kv.second; + outString->appendFormat("-- %s\n", layer.name.string()); + outString->appendFormat("---- Frame # %" PRIu64 " (%s)\n", + layer.frameNumber, + layer.isGlesComposition ? "GLES" : "HWC"); + outString->appendFormat("---- Posted\t%" PRId64 "\n", + layer.postedTime); + if (layer.acquireTime) { + outString->appendFormat("---- Acquire\t%" PRId64 "\n", + layer.acquireTime); + } else { + outString->append("---- Acquire\tNot signaled\n"); + } + if (layer.releaseTime) { + outString->appendFormat("---- Release\t%" PRId64 "\n", + layer.releaseTime); + } else { + outString->append("---- Release\tNot signaled\n"); + } + } + } +} + +static inline bool isValidTimestamp(nsecs_t time) { + return time > 0 && time < INT64_MAX; +} + +void FenceTracker::checkFencesForCompletion() { + for (auto& frame : mFrames) { + if (frame.retireFence != Fence::NO_FENCE) { + nsecs_t time = frame.retireFence->getSignalTime(); + if (isValidTimestamp(time)) { + frame.retireTime = time; + frame.retireFence = Fence::NO_FENCE; + } + } + if (frame.glesCompositionDoneFence != Fence::NO_FENCE) { + nsecs_t time = frame.glesCompositionDoneFence->getSignalTime(); + if (isValidTimestamp(time)) { + frame.glesCompositionDoneTime = time; + frame.glesCompositionDoneFence = Fence::NO_FENCE; + } + } + for (auto& kv : frame.layers) { + LayerRecord& layer = kv.second; + if (layer.acquireFence != Fence::NO_FENCE) { + nsecs_t time = layer.acquireFence->getSignalTime(); + if (isValidTimestamp(time)) { + layer.acquireTime = time; + layer.acquireFence = Fence::NO_FENCE; + } + } + if (layer.releaseFence != Fence::NO_FENCE) { + nsecs_t time = layer.releaseFence->getSignalTime(); + if (isValidTimestamp(time)) { + layer.releaseTime = time; + layer.releaseFence = Fence::NO_FENCE; + } + } + } + } +} + +void FenceTracker::addFrame(nsecs_t refreshStartTime, sp<Fence> retireFence, + const Vector<sp<Layer>>& layers, sp<Fence> glDoneFence) { + Mutex::Autolock lock(mMutex); + FrameRecord& frame = mFrames[mOffset]; + FrameRecord& prevFrame = mFrames[(mOffset + MAX_FRAME_HISTORY - 1) % + MAX_FRAME_HISTORY]; + frame.layers.clear(); + + bool wasGlesCompositionDone = false; + const size_t count = layers.size(); + for (size_t i = 0; i < count; i++) { + String8 name; + uint64_t frameNumber; + bool glesComposition; + nsecs_t postedTime; + sp<Fence> acquireFence; + sp<Fence> prevReleaseFence; + int32_t key = layers[i]->getSequence(); + + layers[i]->getFenceData(&name, &frameNumber, &glesComposition, + &postedTime, &acquireFence, &prevReleaseFence); +#ifdef USE_HWC2 + if (glesComposition) { + frame.layers.emplace(std::piecewise_construct, + std::forward_as_tuple(key), + std::forward_as_tuple(name, frameNumber, glesComposition, + postedTime, 0, 0, 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)); + + auto prevLayer = prevFrame.layers.find(key); + if (prevLayer != prevFrame.layers.end()) { + prevLayer->second.releaseFence = prevReleaseFence; + } + } +#else + frame.layers.emplace(std::piecewise_construct, + std::forward_as_tuple(key), + std::forward_as_tuple(name, frameNumber, glesComposition, + postedTime, 0, 0, acquireFence, + glesComposition ? Fence::NO_FENCE : prevReleaseFence)); + if (glesComposition) { + wasGlesCompositionDone = true; + } +#endif + frame.layers.emplace(std::piecewise_construct, + std::forward_as_tuple(key), + std::forward_as_tuple(name, frameNumber, glesComposition, + postedTime, 0, 0, acquireFence, prevReleaseFence)); + } + + frame.frameId = mFrameCounter; + frame.refreshStartTime = refreshStartTime; + frame.retireTime = 0; + frame.glesCompositionDoneTime = 0; + prevFrame.retireFence = retireFence; + frame.retireFence = Fence::NO_FENCE; + frame.glesCompositionDoneFence = wasGlesCompositionDone ? glDoneFence : + Fence::NO_FENCE; + + mOffset = (mOffset + 1) % MAX_FRAME_HISTORY; + mFrameCounter++; + + checkFencesForCompletion(); +} + +} // namespace android diff --git a/services/surfaceflinger/FenceTracker.h b/services/surfaceflinger/FenceTracker.h new file mode 100644 index 0000000000..de99820370 --- /dev/null +++ b/services/surfaceflinger/FenceTracker.h @@ -0,0 +1,103 @@ +/* + * 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_FENCETRACKER_H +#define ANDROID_FENCETRACKER_H + +#include <ui/Fence.h> +#include <utils/Mutex.h> +#include <utils/RefBase.h> +#include <utils/String8.h> +#include <utils/Timers.h> +#include <utils/Vector.h> + +#include <unordered_map> + +namespace android { + +class Layer; + +/* + * Keeps a circular buffer of fence/timestamp data for the last N frames in + * SurfaceFlinger. Gets timestamps for fences after they have signaled. + */ +class FenceTracker { +public: + FenceTracker(); + void dump(String8* outString); + void addFrame(nsecs_t refreshStartTime, sp<Fence> retireFence, + const Vector<sp<Layer>>& layers, sp<Fence> glDoneFence); + +protected: + static constexpr size_t MAX_FRAME_HISTORY = 128; + + struct LayerRecord { + String8 name; // layer name + uint64_t frameNumber; // frame number for this layer + bool isGlesComposition; // was GLES composition used for this layer? + nsecs_t postedTime; // time when buffer was queued + nsecs_t acquireTime; // timestamp from the acquire fence + nsecs_t releaseTime; // timestamp from the release fence + sp<Fence> acquireFence; // acquire fence + sp<Fence> releaseFence; // release fence + + LayerRecord(const String8& name, uint64_t frameNumber, + bool isGlesComposition, nsecs_t postedTime, + nsecs_t acquireTime, nsecs_t releaseTime, + sp<Fence> acquireFence, sp<Fence> releaseFence) : + name(name), frameNumber(frameNumber), + isGlesComposition(isGlesComposition), postedTime(postedTime), + acquireTime(acquireTime), releaseTime(releaseTime), + acquireFence(acquireFence), releaseFence(releaseFence) {}; + LayerRecord() : name("uninitialized"), frameNumber(0), + isGlesComposition(false), postedTime(0), acquireTime(0), + releaseTime(0), acquireFence(Fence::NO_FENCE), + releaseFence(Fence::NO_FENCE) {}; + }; + + struct FrameRecord { + // global SurfaceFlinger frame counter + uint64_t frameId; + // layer data for this frame + std::unordered_map<int32_t, LayerRecord> layers; + // timestamp for when SurfaceFlinger::handleMessageRefresh() was called + nsecs_t refreshStartTime; + // timestamp from the retire fence + nsecs_t retireTime; + // timestamp from the GLES composition completion fence + nsecs_t glesCompositionDoneTime; + // primary display retire fence for this frame + sp<Fence> retireFence; + // if GLES composition was done, the fence for its completion + sp<Fence> glesCompositionDoneFence; + + FrameRecord() : frameId(0), layers(), refreshStartTime(0), + retireTime(0), glesCompositionDoneTime(0), + retireFence(Fence::NO_FENCE), + glesCompositionDoneFence(Fence::NO_FENCE) {} + }; + + uint64_t mFrameCounter; + uint32_t mOffset; + FrameRecord mFrames[MAX_FRAME_HISTORY]; + Mutex mMutex; + + void checkFencesForCompletion(); +}; + +} + +#endif // ANDROID_FRAMETRACKER_H diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 910aeae3df..80012a6e32 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -82,6 +82,9 @@ Layer::Layer(SurfaceFlinger* flinger, const sp<Client>& client, mFiltering(false), mNeedsFiltering(false), mMesh(Mesh::TRIANGLE_FAN, 4, 2, 2), +#ifndef USE_HWC2 + mIsGlesComposition(false), +#endif mProtectedByApp(false), mHasSurface(false), mClientRef(client), @@ -772,6 +775,7 @@ void Layer::setPerFrameData(const sp<const DisplayDevice>& hw, Region visible = tr.transform(visibleRegion.intersect(hw->getViewport())); layer.setVisibleRegionScreen(visible); layer.setSurfaceDamage(surfaceDamageRegion); + mIsGlesComposition = (layer.getCompositionType() == HWC_FRAMEBUFFER); if (mSidebandStream.get()) { layer.setSidebandStream(mSidebandStream); @@ -2130,6 +2134,23 @@ void Layer::getFrameStats(FrameStats* outStats) const { mFrameTracker.getStats(outStats); } +void Layer::getFenceData(String8* outName, uint64_t* outFrameNumber, + bool* outIsGlesComposition, nsecs_t* outPostedTime, + sp<Fence>* outAcquireFence, sp<Fence>* outPrevReleaseFence) const { + *outName = mName; + *outFrameNumber = mSurfaceFlingerConsumer->getFrameNumber(); + +#ifdef USE_HWC2 + *outIsGlesComposition = mHwcLayers.count(HWC_DISPLAY_PRIMARY) ? + mHwcLayers.at(HWC_DISPLAY_PRIMARY).compositionType == + HWC2::Composition::Client : true; +#else + *outIsGlesComposition = mIsGlesComposition; +#endif + *outPostedTime = mSurfaceFlingerConsumer->getTimestamp(); + *outAcquireFence = mSurfaceFlingerConsumer->getCurrentFence(); + *outPrevReleaseFence = mSurfaceFlingerConsumer->getPrevReleaseFence(); +} // --------------------------------------------------------------------------- Layer::LayerCleaner::LayerCleaner(const sp<SurfaceFlinger>& flinger, diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 4dc0764940..34857c217e 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -179,6 +179,8 @@ public: sp<IGraphicBufferProducer> getProducer() const; const String8& getName() const; + int32_t getSequence() const { return sequence; } + // ----------------------------------------------------------------------- // Virtuals @@ -398,6 +400,10 @@ public: void logFrameStats(); void getFrameStats(FrameStats* outStats) const; + void getFenceData(String8* outName, uint64_t* outFrameNumber, + bool* outIsGlesComposition, nsecs_t* outPostedTime, + sp<Fence>* outAcquireFence, sp<Fence>* outPrevReleaseFence) const; + protected: // constant sp<SurfaceFlinger> mFlinger; @@ -557,6 +563,8 @@ private: bool clearClientTarget; }; std::unordered_map<int32_t, HWCInfo> mHwcLayers; +#else + bool mIsGlesComposition; #endif // page-flip thread (currently main thread) diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 019bcec2a5..9b438498df 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -910,6 +910,7 @@ bool SurfaceFlinger::handleMessageInvalidate() { void SurfaceFlinger::handleMessageRefresh() { ATRACE_CALL(); + nsecs_t refreshStartTime = systemTime(SYSTEM_TIME_MONOTONIC); static nsecs_t previousExpectedPresent = 0; nsecs_t expectedPresent = mPrimaryDispSync.computeNextRefresh(0); static bool previousFrameMissed = false; @@ -930,7 +931,7 @@ void SurfaceFlinger::handleMessageRefresh() { setUpHWComposer(); doDebugFlashRegions(); doComposition(); - postComposition(); + postComposition(refreshStartTime); } // Release any buffers which were replaced this frame @@ -999,7 +1000,7 @@ void SurfaceFlinger::preComposition() } } -void SurfaceFlinger::postComposition() +void SurfaceFlinger::postComposition(nsecs_t refreshStartTime) { ATRACE_CALL(); ALOGV("postComposition"); @@ -1027,6 +1028,9 @@ void SurfaceFlinger::postComposition() } } + mFenceTracker.addFrame(refreshStartTime, presentFence, + hw->getVisibleLayersSortedByZ(), hw->getClientTargetAcquireFence()); + if (mAnimCompositionPending) { mAnimCompositionPending = false; @@ -2543,6 +2547,13 @@ status_t SurfaceFlinger::dump(int fd, const Vector<String16>& args) dumpStaticScreenStats(result); dumpAll = false; } + + if ((index < numArgs) && + (args[index] == String16("--fences"))) { + index++; + mFenceTracker.dump(&result); + dumpAll = false; + } } if (dumpAll) { diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 7d6f139157..37110b9260 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -50,6 +50,7 @@ #include "Barrier.h" #include "DisplayDevice.h" #include "DispSync.h" +#include "FenceTracker.h" #include "FrameTracker.h" #include "MessageQueue.h" @@ -384,7 +385,7 @@ private: Region& dirtyRegion, Region& opaqueRegion); void preComposition(); - void postComposition(); + void postComposition(nsecs_t refreshStartTime); void rebuildLayerStacks(); void setUpHWComposer(); void doComposition(); @@ -488,6 +489,7 @@ private: nsecs_t mLastTransactionTime; bool mBootFinished; bool mForceFullDamage; + FenceTracker mFenceTracker; // these are thread safe mutable MessageQueue mEventQueue; diff --git a/services/surfaceflinger/SurfaceFlingerConsumer.cpp b/services/surfaceflinger/SurfaceFlingerConsumer.cpp index 4c80fa063a..c71b3bcbfd 100644 --- a/services/surfaceflinger/SurfaceFlingerConsumer.cpp +++ b/services/surfaceflinger/SurfaceFlingerConsumer.cpp @@ -190,6 +190,7 @@ nsecs_t SurfaceFlingerConsumer::computeExpectedPresent(const DispSync& dispSync) #ifdef USE_HWC2 void SurfaceFlingerConsumer::setReleaseFence(const sp<Fence>& fence) { + mPrevReleaseFence = fence; if (!mPendingRelease.isPending) { GLConsumer::setReleaseFence(fence); return; @@ -219,8 +220,17 @@ void SurfaceFlingerConsumer::releasePendingBuffer() strerror(-result), result); mPendingRelease = PendingRelease(); } +#else +void SurfaceFlingerConsumer::setReleaseFence(const sp<Fence>& fence) { + mPrevReleaseFence = fence; + GLConsumer::setReleaseFence(fence); +} #endif +sp<Fence> SurfaceFlingerConsumer::getPrevReleaseFence() const { + return mPrevReleaseFence; +} + void SurfaceFlingerConsumer::setContentsChangedListener( const wp<ContentsChangedListener>& listener) { setFrameAvailableListener(listener); diff --git a/services/surfaceflinger/SurfaceFlingerConsumer.h b/services/surfaceflinger/SurfaceFlingerConsumer.h index f40d53e964..51b002f991 100644 --- a/services/surfaceflinger/SurfaceFlingerConsumer.h +++ b/services/surfaceflinger/SurfaceFlingerConsumer.h @@ -37,7 +37,8 @@ public: SurfaceFlingerConsumer(const sp<IGraphicBufferConsumer>& consumer, uint32_t tex) : GLConsumer(consumer, tex, GLConsumer::TEXTURE_EXTERNAL, false, false), - mTransformToDisplayInverse(false), mSurfaceDamage() + mTransformToDisplayInverse(false), mSurfaceDamage(), + mPrevReleaseFence(Fence::NO_FENCE) {} class BufferRejecter { @@ -75,8 +76,9 @@ public: nsecs_t computeExpectedPresent(const DispSync& dispSync); -#ifdef USE_HWC2 virtual void setReleaseFence(const sp<Fence>& fence) override; + sp<Fence> getPrevReleaseFence() const; +#ifdef USE_HWC2 void releasePendingBuffer(); #endif @@ -98,6 +100,9 @@ private: // presentDisplay PendingRelease mPendingRelease; #endif + + // The release fence of the already displayed buffer (previous frame). + sp<Fence> mPrevReleaseFence; }; // ---------------------------------------------------------------------------- diff --git a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp index e41fbdd69c..11f19d099f 100644 --- a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp +++ b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp @@ -927,6 +927,7 @@ bool SurfaceFlinger::handleMessageInvalidate() { void SurfaceFlinger::handleMessageRefresh() { ATRACE_CALL(); + nsecs_t refreshStartTime = systemTime(SYSTEM_TIME_MONOTONIC); static nsecs_t previousExpectedPresent = 0; nsecs_t expectedPresent = mPrimaryDispSync.computeNextRefresh(0); static bool previousFrameMissed = false; @@ -947,7 +948,7 @@ void SurfaceFlinger::handleMessageRefresh() { setUpHWComposer(); doDebugFlashRegions(); doComposition(); - postComposition(); + postComposition(refreshStartTime); } previousExpectedPresent = mPrimaryDispSync.computeNextRefresh(0); @@ -1008,7 +1009,7 @@ void SurfaceFlinger::preComposition() } } -void SurfaceFlinger::postComposition() +void SurfaceFlinger::postComposition(nsecs_t refreshStartTime) { const LayerVector& layers(mDrawingState.layersSortedByZ); const size_t count = layers.size(); @@ -1034,6 +1035,9 @@ void SurfaceFlinger::postComposition() } } + mFenceTracker.addFrame(refreshStartTime, presentFence, + hw->getVisibleLayersSortedByZ(), hw->getClientTargetAcquireFence()); + if (mAnimCompositionPending) { mAnimCompositionPending = false; @@ -2581,6 +2585,13 @@ status_t SurfaceFlinger::dump(int fd, const Vector<String16>& args) dumpStaticScreenStats(result); dumpAll = false; } + + if ((index < numArgs) && + (args[index] == String16("--fences"))) { + index++; + mFenceTracker.dump(&result); + dumpAll = false; + } } if (dumpAll) { |