Merge changes I8bded1ea,I7478293e
* changes: SurfaceFlinger: add win anim frame time tracking SurfaceFlinger: remove a driver bug workaround
This commit is contained in:
commit
351c294173
|
@ -31,28 +31,34 @@ FrameTracker::FrameTracker() :
|
||||||
}
|
}
|
||||||
|
|
||||||
void FrameTracker::setDesiredPresentTime(nsecs_t presentTime) {
|
void FrameTracker::setDesiredPresentTime(nsecs_t presentTime) {
|
||||||
|
Mutex::Autolock lock(mMutex);
|
||||||
mFrameRecords[mOffset].desiredPresentTime = presentTime;
|
mFrameRecords[mOffset].desiredPresentTime = presentTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FrameTracker::setFrameReadyTime(nsecs_t readyTime) {
|
void FrameTracker::setFrameReadyTime(nsecs_t readyTime) {
|
||||||
|
Mutex::Autolock lock(mMutex);
|
||||||
mFrameRecords[mOffset].frameReadyTime = readyTime;
|
mFrameRecords[mOffset].frameReadyTime = readyTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FrameTracker::setFrameReadyFence(const sp<Fence>& readyFence) {
|
void FrameTracker::setFrameReadyFence(const sp<Fence>& readyFence) {
|
||||||
|
Mutex::Autolock lock(mMutex);
|
||||||
mFrameRecords[mOffset].frameReadyFence = readyFence;
|
mFrameRecords[mOffset].frameReadyFence = readyFence;
|
||||||
mNumFences++;
|
mNumFences++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FrameTracker::setActualPresentTime(nsecs_t presentTime) {
|
void FrameTracker::setActualPresentTime(nsecs_t presentTime) {
|
||||||
|
Mutex::Autolock lock(mMutex);
|
||||||
mFrameRecords[mOffset].actualPresentTime = presentTime;
|
mFrameRecords[mOffset].actualPresentTime = presentTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FrameTracker::setActualPresentFence(const sp<Fence>& readyFence) {
|
void FrameTracker::setActualPresentFence(const sp<Fence>& readyFence) {
|
||||||
|
Mutex::Autolock lock(mMutex);
|
||||||
mFrameRecords[mOffset].actualPresentFence = readyFence;
|
mFrameRecords[mOffset].actualPresentFence = readyFence;
|
||||||
mNumFences++;
|
mNumFences++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FrameTracker::advanceFrame() {
|
void FrameTracker::advanceFrame() {
|
||||||
|
Mutex::Autolock lock(mMutex);
|
||||||
mOffset = (mOffset+1) % NUM_FRAME_RECORDS;
|
mOffset = (mOffset+1) % NUM_FRAME_RECORDS;
|
||||||
mFrameRecords[mOffset].desiredPresentTime = INT64_MAX;
|
mFrameRecords[mOffset].desiredPresentTime = INT64_MAX;
|
||||||
mFrameRecords[mOffset].frameReadyTime = INT64_MAX;
|
mFrameRecords[mOffset].frameReadyTime = INT64_MAX;
|
||||||
|
@ -74,10 +80,11 @@ void FrameTracker::advanceFrame() {
|
||||||
|
|
||||||
// Clean up the signaled fences to keep the number of open fence FDs in
|
// Clean up the signaled fences to keep the number of open fence FDs in
|
||||||
// this process reasonable.
|
// this process reasonable.
|
||||||
processFences();
|
processFencesLocked();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FrameTracker::clear() {
|
void FrameTracker::clear() {
|
||||||
|
Mutex::Autolock lock(mMutex);
|
||||||
for (size_t i = 0; i < NUM_FRAME_RECORDS; i++) {
|
for (size_t i = 0; i < NUM_FRAME_RECORDS; i++) {
|
||||||
mFrameRecords[i].desiredPresentTime = 0;
|
mFrameRecords[i].desiredPresentTime = 0;
|
||||||
mFrameRecords[i].frameReadyTime = 0;
|
mFrameRecords[i].frameReadyTime = 0;
|
||||||
|
@ -86,9 +93,12 @@ void FrameTracker::clear() {
|
||||||
mFrameRecords[i].actualPresentFence.clear();
|
mFrameRecords[i].actualPresentFence.clear();
|
||||||
}
|
}
|
||||||
mNumFences = 0;
|
mNumFences = 0;
|
||||||
|
mFrameRecords[mOffset].desiredPresentTime = INT64_MAX;
|
||||||
|
mFrameRecords[mOffset].frameReadyTime = INT64_MAX;
|
||||||
|
mFrameRecords[mOffset].actualPresentTime = INT64_MAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FrameTracker::processFences() const {
|
void FrameTracker::processFencesLocked() const {
|
||||||
FrameRecord* records = const_cast<FrameRecord*>(mFrameRecords);
|
FrameRecord* records = const_cast<FrameRecord*>(mFrameRecords);
|
||||||
int& numFences = const_cast<int&>(mNumFences);
|
int& numFences = const_cast<int&>(mNumFences);
|
||||||
|
|
||||||
|
@ -116,7 +126,8 @@ void FrameTracker::processFences() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void FrameTracker::dump(String8& result) const {
|
void FrameTracker::dump(String8& result) const {
|
||||||
processFences();
|
Mutex::Autolock lock(mMutex);
|
||||||
|
processFencesLocked();
|
||||||
|
|
||||||
const size_t o = mOffset;
|
const size_t o = mOffset;
|
||||||
for (size_t i = 1; i < NUM_FRAME_RECORDS; i++) {
|
for (size_t i = 1; i < NUM_FRAME_RECORDS; i++) {
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#include <utils/Mutex.h>
|
||||||
#include <utils/Timers.h>
|
#include <utils/Timers.h>
|
||||||
#include <utils/RefBase.h>
|
#include <utils/RefBase.h>
|
||||||
|
|
||||||
|
@ -96,7 +97,7 @@ private:
|
||||||
// This method is const because although it modifies the frame records it
|
// This method is const because although it modifies the frame records it
|
||||||
// does so in such a way that the information represented should not
|
// does so in such a way that the information represented should not
|
||||||
// change. This allows it to be called from the dump method.
|
// change. This allows it to be called from the dump method.
|
||||||
void processFences() const;
|
void processFencesLocked() const;
|
||||||
|
|
||||||
// mFrameRecords is the circular buffer storing the tracked data for each
|
// mFrameRecords is the circular buffer storing the tracked data for each
|
||||||
// frame.
|
// frame.
|
||||||
|
@ -113,6 +114,9 @@ private:
|
||||||
// The number of fences is tracked so that the run time of processFences
|
// The number of fences is tracked so that the run time of processFences
|
||||||
// doesn't grow with NUM_FRAME_RECORDS.
|
// doesn't grow with NUM_FRAME_RECORDS.
|
||||||
int mNumFences;
|
int mNumFences;
|
||||||
|
|
||||||
|
// mMutex is used to protect access to all member variables.
|
||||||
|
mutable Mutex mMutex;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -536,9 +536,6 @@ void Layer::onPostComposition() {
|
||||||
|
|
||||||
const HWComposer& hwc = mFlinger->getHwComposer();
|
const HWComposer& hwc = mFlinger->getHwComposer();
|
||||||
sp<Fence> presentFence = hwc.getDisplayFence(HWC_DISPLAY_PRIMARY);
|
sp<Fence> presentFence = hwc.getDisplayFence(HWC_DISPLAY_PRIMARY);
|
||||||
// XXX: Temporarily don't use the present fence from HWC to work
|
|
||||||
// around a driver bug.
|
|
||||||
presentFence.clear();
|
|
||||||
if (presentFence != NULL) {
|
if (presentFence != NULL) {
|
||||||
mFrameTracker.setActualPresentFence(presentFence);
|
mFrameTracker.setActualPresentFence(presentFence);
|
||||||
} else {
|
} else {
|
||||||
|
@ -757,9 +754,6 @@ void Layer::dump(String8& result, char* buffer, size_t SIZE) const
|
||||||
void Layer::dumpStats(String8& result, char* buffer, size_t SIZE) const
|
void Layer::dumpStats(String8& result, char* buffer, size_t SIZE) const
|
||||||
{
|
{
|
||||||
LayerBaseClient::dumpStats(result, buffer, SIZE);
|
LayerBaseClient::dumpStats(result, buffer, SIZE);
|
||||||
const nsecs_t period =
|
|
||||||
mFlinger->getHwComposer().getRefreshPeriod(HWC_DISPLAY_PRIMARY);
|
|
||||||
result.appendFormat("%lld\n", period);
|
|
||||||
mFrameTracker.dump(result);
|
mFrameTracker.dump(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -129,6 +129,7 @@ private:
|
||||||
|
|
||||||
// thread-safe
|
// thread-safe
|
||||||
volatile int32_t mQueuedFrames;
|
volatile int32_t mQueuedFrames;
|
||||||
|
FrameTracker mFrameTracker;
|
||||||
|
|
||||||
// main thread
|
// main thread
|
||||||
sp<GraphicBuffer> mActiveBuffer;
|
sp<GraphicBuffer> mActiveBuffer;
|
||||||
|
@ -138,7 +139,6 @@ private:
|
||||||
bool mCurrentOpacity;
|
bool mCurrentOpacity;
|
||||||
bool mRefreshPending;
|
bool mRefreshPending;
|
||||||
bool mFrameLatencyNeeded;
|
bool mFrameLatencyNeeded;
|
||||||
FrameTracker mFrameTracker;
|
|
||||||
|
|
||||||
// constants
|
// constants
|
||||||
PixelFormat mFormat;
|
PixelFormat mFormat;
|
||||||
|
|
|
@ -93,6 +93,7 @@ SurfaceFlinger::SurfaceFlinger()
|
||||||
mBootTime(systemTime()),
|
mBootTime(systemTime()),
|
||||||
mVisibleRegionsDirty(false),
|
mVisibleRegionsDirty(false),
|
||||||
mHwWorkListDirty(false),
|
mHwWorkListDirty(false),
|
||||||
|
mAnimCompositionPending(false),
|
||||||
mDebugRegion(0),
|
mDebugRegion(0),
|
||||||
mDebugDDMS(0),
|
mDebugDDMS(0),
|
||||||
mDebugDisableHWC(0),
|
mDebugDisableHWC(0),
|
||||||
|
@ -885,6 +886,22 @@ void SurfaceFlinger::postComposition()
|
||||||
for (size_t i=0 ; i<count ; i++) {
|
for (size_t i=0 ; i<count ; i++) {
|
||||||
currentLayers[i]->onPostComposition();
|
currentLayers[i]->onPostComposition();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mAnimCompositionPending) {
|
||||||
|
mAnimCompositionPending = false;
|
||||||
|
|
||||||
|
const HWComposer& hwc = getHwComposer();
|
||||||
|
sp<Fence> presentFence = hwc.getDisplayFence(HWC_DISPLAY_PRIMARY);
|
||||||
|
if (presentFence != NULL) {
|
||||||
|
mAnimFrameTracker.setActualPresentFence(presentFence);
|
||||||
|
} else {
|
||||||
|
// The HWC doesn't support present fences, so use the refresh
|
||||||
|
// timestamp instead.
|
||||||
|
nsecs_t presentTime = hwc.getRefreshTimestamp(HWC_DISPLAY_PRIMARY);
|
||||||
|
mAnimFrameTracker.setActualPresentTime(presentTime);
|
||||||
|
}
|
||||||
|
mAnimFrameTracker.advanceFrame();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SurfaceFlinger::rebuildLayerStacks() {
|
void SurfaceFlinger::rebuildLayerStacks() {
|
||||||
|
@ -1301,6 +1318,10 @@ void SurfaceFlinger::commitTransaction()
|
||||||
mLayersPendingRemoval.clear();
|
mLayersPendingRemoval.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If this transaction is part of a window animation then the next frame
|
||||||
|
// we composite should be considered an animation as well.
|
||||||
|
mAnimCompositionPending = mAnimTransactionPending;
|
||||||
|
|
||||||
mDrawingState = mCurrentState;
|
mDrawingState = mCurrentState;
|
||||||
mTransactionPending = false;
|
mTransactionPending = false;
|
||||||
mAnimTransactionPending = false;
|
mAnimTransactionPending = false;
|
||||||
|
@ -2264,22 +2285,26 @@ void SurfaceFlinger::dumpStatsLocked(const Vector<String16>& args, size_t& index
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
|
|
||||||
const LayerVector& currentLayers = mCurrentState.layersSortedByZ;
|
const nsecs_t period =
|
||||||
const size_t count = currentLayers.size();
|
getHwComposer().getRefreshPeriod(HWC_DISPLAY_PRIMARY);
|
||||||
for (size_t i=0 ; i<count ; i++) {
|
result.appendFormat("%lld\n", period);
|
||||||
const sp<LayerBase>& layer(currentLayers[i]);
|
|
||||||
if (name.isEmpty()) {
|
if (name.isEmpty()) {
|
||||||
snprintf(buffer, SIZE, "%s\n", layer->getName().string());
|
mAnimFrameTracker.dump(result);
|
||||||
result.append(buffer);
|
} else {
|
||||||
}
|
const LayerVector& currentLayers = mCurrentState.layersSortedByZ;
|
||||||
if (name.isEmpty() || (name == layer->getName())) {
|
const size_t count = currentLayers.size();
|
||||||
layer->dumpStats(result, buffer, SIZE);
|
for (size_t i=0 ; i<count ; i++) {
|
||||||
|
const sp<LayerBase>& layer(currentLayers[i]);
|
||||||
|
if (name == layer->getName()) {
|
||||||
|
layer->dumpStats(result, buffer, SIZE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SurfaceFlinger::clearStatsLocked(const Vector<String16>& args, size_t& index,
|
void SurfaceFlinger::clearStatsLocked(const Vector<String16>& args, size_t& index,
|
||||||
String8& result, char* buffer, size_t SIZE) const
|
String8& result, char* buffer, size_t SIZE)
|
||||||
{
|
{
|
||||||
String8 name;
|
String8 name;
|
||||||
if (index < args.size()) {
|
if (index < args.size()) {
|
||||||
|
@ -2295,6 +2320,8 @@ void SurfaceFlinger::clearStatsLocked(const Vector<String16>& args, size_t& inde
|
||||||
layer->clearStats();
|
layer->clearStats();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mAnimFrameTracker.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*static*/ void SurfaceFlinger::appendSfConfigString(String8& result)
|
/*static*/ void SurfaceFlinger::appendSfConfigString(String8& result)
|
||||||
|
|
|
@ -45,8 +45,9 @@
|
||||||
#include <private/gui/LayerState.h>
|
#include <private/gui/LayerState.h>
|
||||||
|
|
||||||
#include "Barrier.h"
|
#include "Barrier.h"
|
||||||
#include "MessageQueue.h"
|
|
||||||
#include "DisplayDevice.h"
|
#include "DisplayDevice.h"
|
||||||
|
#include "FrameTracker.h"
|
||||||
|
#include "MessageQueue.h"
|
||||||
|
|
||||||
#include "DisplayHardware/HWComposer.h"
|
#include "DisplayHardware/HWComposer.h"
|
||||||
|
|
||||||
|
@ -390,7 +391,7 @@ private:
|
||||||
void dumpStatsLocked(const Vector<String16>& args, size_t& index,
|
void dumpStatsLocked(const Vector<String16>& args, size_t& index,
|
||||||
String8& result, char* buffer, size_t SIZE) const;
|
String8& result, char* buffer, size_t SIZE) const;
|
||||||
void clearStatsLocked(const Vector<String16>& args, size_t& index,
|
void clearStatsLocked(const Vector<String16>& args, size_t& index,
|
||||||
String8& result, char* buffer, size_t SIZE) const;
|
String8& result, char* buffer, size_t SIZE);
|
||||||
void dumpAllLocked(String8& result, char* buffer, size_t SIZE) const;
|
void dumpAllLocked(String8& result, char* buffer, size_t SIZE) const;
|
||||||
bool startDdmConnection();
|
bool startDdmConnection();
|
||||||
static void appendSfConfigString(String8& result);
|
static void appendSfConfigString(String8& result);
|
||||||
|
@ -432,6 +433,7 @@ private:
|
||||||
State mDrawingState;
|
State mDrawingState;
|
||||||
bool mVisibleRegionsDirty;
|
bool mVisibleRegionsDirty;
|
||||||
bool mHwWorkListDirty;
|
bool mHwWorkListDirty;
|
||||||
|
bool mAnimCompositionPending;
|
||||||
|
|
||||||
// this may only be written from the main thread with mStateLock held
|
// this may only be written from the main thread with mStateLock held
|
||||||
// it may be read from other threads with mStateLock held
|
// it may be read from other threads with mStateLock held
|
||||||
|
@ -451,6 +453,7 @@ private:
|
||||||
// these are thread safe
|
// these are thread safe
|
||||||
mutable MessageQueue mEventQueue;
|
mutable MessageQueue mEventQueue;
|
||||||
mutable Barrier mReadyToRunBarrier;
|
mutable Barrier mReadyToRunBarrier;
|
||||||
|
FrameTracker mAnimFrameTracker;
|
||||||
|
|
||||||
// protected by mDestroyedLayerLock;
|
// protected by mDestroyedLayerLock;
|
||||||
mutable Mutex mDestroyedLayerLock;
|
mutable Mutex mDestroyedLayerLock;
|
||||||
|
|
Loading…
Reference in New Issue