Merge changes Ib6b6da1d,I6d9a466a
* changes: improve SurfaceFlinger dumpsys hack up frame latency measurement
This commit is contained in:
commit
843861643e
@ -477,6 +477,26 @@ EGLBoolean eglQuerySurface( EGLDisplay dpy, EGLSurface surface,
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EGLAPI eglBeginFrame(EGLDisplay dpy, EGLSurface surface) {
|
||||||
|
clearError();
|
||||||
|
|
||||||
|
egl_display_t const * const dp = validate_display(dpy);
|
||||||
|
if (!dp) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SurfaceRef _s(dp, surface);
|
||||||
|
if (!_s.get()) {
|
||||||
|
setError(EGL_BAD_SURFACE, EGL_FALSE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
|
||||||
|
|
||||||
|
egl_surface_t const * const s = get_surface(surface);
|
||||||
|
native_window_set_buffers_timestamp(s->win.get(), timestamp);
|
||||||
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// Contexts
|
// Contexts
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
@ -350,15 +350,28 @@ uint32_t DisplayHardware::getPageFlipCount() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// this needs to be thread safe
|
// this needs to be thread safe
|
||||||
nsecs_t DisplayHardware::waitForVSync() const {
|
nsecs_t DisplayHardware::waitForRefresh() const {
|
||||||
nsecs_t timestamp;
|
nsecs_t timestamp;
|
||||||
if (mVSync.wait(×tamp) < 0) {
|
if (mVSync.wait(×tamp) < 0) {
|
||||||
// vsync not supported!
|
// vsync not supported!
|
||||||
usleep( getDelayToNextVSyncUs(×tamp) );
|
usleep( getDelayToNextVSyncUs(×tamp) );
|
||||||
}
|
}
|
||||||
|
mLastHwVSync = timestamp; // FIXME: Not thread safe
|
||||||
return timestamp;
|
return timestamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsecs_t DisplayHardware::getRefreshTimestamp() const {
|
||||||
|
// this returns the last refresh timestamp.
|
||||||
|
// if the last one is not available, we estimate it based on
|
||||||
|
// the refresh period and whatever closest timestamp we have.
|
||||||
|
nsecs_t now = systemTime();
|
||||||
|
return now - ((now - mLastHwVSync) % mRefreshPeriod);
|
||||||
|
}
|
||||||
|
|
||||||
|
nsecs_t DisplayHardware::getRefreshPeriod() const {
|
||||||
|
return mRefreshPeriod;
|
||||||
|
}
|
||||||
|
|
||||||
int32_t DisplayHardware::getDelayToNextVSyncUs(nsecs_t* timestamp) const {
|
int32_t DisplayHardware::getDelayToNextVSyncUs(nsecs_t* timestamp) const {
|
||||||
Mutex::Autolock _l(mFakeVSyncMutex);
|
Mutex::Autolock _l(mFakeVSyncMutex);
|
||||||
const nsecs_t period = mRefreshPeriod;
|
const nsecs_t period = mRefreshPeriod;
|
||||||
|
@ -76,7 +76,9 @@ public:
|
|||||||
uint32_t getMaxViewportDims() const;
|
uint32_t getMaxViewportDims() const;
|
||||||
|
|
||||||
// waits for the next vsync and returns the timestamp of when it happened
|
// waits for the next vsync and returns the timestamp of when it happened
|
||||||
nsecs_t waitForVSync() const;
|
nsecs_t waitForRefresh() const;
|
||||||
|
nsecs_t getRefreshPeriod() const;
|
||||||
|
nsecs_t getRefreshTimestamp() const;
|
||||||
|
|
||||||
uint32_t getPageFlipCount() const;
|
uint32_t getPageFlipCount() const;
|
||||||
EGLDisplay getEGLDisplay() const { return mDisplay; }
|
EGLDisplay getEGLDisplay() const { return mDisplay; }
|
||||||
@ -119,6 +121,7 @@ private:
|
|||||||
mutable Mutex mFakeVSyncMutex;
|
mutable Mutex mFakeVSyncMutex;
|
||||||
mutable nsecs_t mNextFakeVSync;
|
mutable nsecs_t mNextFakeVSync;
|
||||||
nsecs_t mRefreshPeriod;
|
nsecs_t mRefreshPeriod;
|
||||||
|
mutable nsecs_t mLastHwVSync;
|
||||||
|
|
||||||
HWComposer* mHwc;
|
HWComposer* mHwc;
|
||||||
|
|
||||||
|
@ -129,7 +129,7 @@ bool EventThread::threadLoop() {
|
|||||||
|
|
||||||
// at least one listener requested VSYNC
|
// at least one listener requested VSYNC
|
||||||
mLock.unlock();
|
mLock.unlock();
|
||||||
timestamp = mHw.waitForVSync();
|
timestamp = mHw.waitForRefresh();
|
||||||
mLock.lock();
|
mLock.lock();
|
||||||
mDeliveredEvents++;
|
mDeliveredEvents++;
|
||||||
|
|
||||||
|
@ -38,6 +38,7 @@
|
|||||||
#include "Layer.h"
|
#include "Layer.h"
|
||||||
#include "SurfaceFlinger.h"
|
#include "SurfaceFlinger.h"
|
||||||
#include "SurfaceTextureLayer.h"
|
#include "SurfaceTextureLayer.h"
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
#define DEBUG_RESIZE 0
|
#define DEBUG_RESIZE 0
|
||||||
|
|
||||||
@ -54,6 +55,8 @@ Layer::Layer(SurfaceFlinger* flinger,
|
|||||||
mCurrentTransform(0),
|
mCurrentTransform(0),
|
||||||
mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
|
mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
|
||||||
mCurrentOpacity(true),
|
mCurrentOpacity(true),
|
||||||
|
mFrameLatencyNeeded(false),
|
||||||
|
mFrameLatencyOffset(0),
|
||||||
mFormat(PIXEL_FORMAT_NONE),
|
mFormat(PIXEL_FORMAT_NONE),
|
||||||
mGLExtensions(GLExtensions::getInstance()),
|
mGLExtensions(GLExtensions::getInstance()),
|
||||||
mOpaqueLayer(true),
|
mOpaqueLayer(true),
|
||||||
@ -65,6 +68,17 @@ Layer::Layer(SurfaceFlinger* flinger,
|
|||||||
glGenTextures(1, &mTextureName);
|
glGenTextures(1, &mTextureName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Layer::onLayerDisplayed() {
|
||||||
|
if (mFrameLatencyNeeded) {
|
||||||
|
const DisplayHardware& hw(graphicPlane(0).displayHardware());
|
||||||
|
mFrameStats[mFrameLatencyOffset].timestamp = mSurfaceTexture->getTimestamp();
|
||||||
|
mFrameStats[mFrameLatencyOffset].set = systemTime();
|
||||||
|
mFrameStats[mFrameLatencyOffset].vsync = hw.getRefreshTimestamp();
|
||||||
|
mFrameLatencyOffset = (mFrameLatencyOffset + 1) % 128;
|
||||||
|
mFrameLatencyNeeded = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Layer::onFirstRef()
|
void Layer::onFirstRef()
|
||||||
{
|
{
|
||||||
LayerBaseClient::onFirstRef();
|
LayerBaseClient::onFirstRef();
|
||||||
@ -408,6 +422,7 @@ void Layer::lockPageFlip(bool& recomputeVisibleRegions)
|
|||||||
|
|
||||||
// update the active buffer
|
// update the active buffer
|
||||||
mActiveBuffer = mSurfaceTexture->getCurrentBuffer();
|
mActiveBuffer = mSurfaceTexture->getCurrentBuffer();
|
||||||
|
mFrameLatencyNeeded = true;
|
||||||
|
|
||||||
const Rect crop(mSurfaceTexture->getCurrentCrop());
|
const Rect crop(mSurfaceTexture->getCurrentCrop());
|
||||||
const uint32_t transform(mSurfaceTexture->getCurrentTransform());
|
const uint32_t transform(mSurfaceTexture->getCurrentTransform());
|
||||||
@ -538,11 +553,33 @@ void Layer::dump(String8& result, char* buffer, size_t SIZE) const
|
|||||||
|
|
||||||
result.append(buffer);
|
result.append(buffer);
|
||||||
|
|
||||||
|
LayerBase::dumpStats(result, buffer, SIZE);
|
||||||
|
|
||||||
if (mSurfaceTexture != 0) {
|
if (mSurfaceTexture != 0) {
|
||||||
mSurfaceTexture->dump(result, " ", buffer, SIZE);
|
mSurfaceTexture->dump(result, " ", buffer, SIZE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Layer::dumpStats(String8& result, char* buffer, size_t SIZE) const
|
||||||
|
{
|
||||||
|
LayerBaseClient::dumpStats(result, buffer, SIZE);
|
||||||
|
const size_t o = mFrameLatencyOffset;
|
||||||
|
const DisplayHardware& hw(graphicPlane(0).displayHardware());
|
||||||
|
const nsecs_t period = hw.getRefreshPeriod();
|
||||||
|
result.appendFormat("%lld\n", period);
|
||||||
|
for (size_t i=0 ; i<128 ; i++) {
|
||||||
|
const size_t index = (o+i) % 128;
|
||||||
|
const nsecs_t time_app = mFrameStats[index].timestamp;
|
||||||
|
const nsecs_t time_set = mFrameStats[index].set;
|
||||||
|
const nsecs_t time_vsync = mFrameStats[index].vsync;
|
||||||
|
result.appendFormat("%lld\t%lld\t%lld\n",
|
||||||
|
time_app,
|
||||||
|
time_vsync,
|
||||||
|
time_set);
|
||||||
|
}
|
||||||
|
result.append("\n");
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t Layer::getEffectiveUsage(uint32_t usage) const
|
uint32_t Layer::getEffectiveUsage(uint32_t usage) const
|
||||||
{
|
{
|
||||||
// TODO: should we do something special if mSecure is set?
|
// TODO: should we do something special if mSecure is set?
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
#include "LayerBase.h"
|
#include "LayerBase.h"
|
||||||
#include "SurfaceTextureLayer.h"
|
#include "SurfaceTextureLayer.h"
|
||||||
#include "Transform.h"
|
#include "Transform.h"
|
||||||
|
#include <utils/Timers.h>
|
||||||
|
|
||||||
namespace android {
|
namespace android {
|
||||||
|
|
||||||
@ -78,12 +79,15 @@ public:
|
|||||||
// LayerBaseClient interface
|
// LayerBaseClient interface
|
||||||
virtual wp<IBinder> getSurfaceTextureBinder() const;
|
virtual wp<IBinder> getSurfaceTextureBinder() const;
|
||||||
|
|
||||||
|
virtual void onLayerDisplayed();
|
||||||
|
|
||||||
// only for debugging
|
// only for debugging
|
||||||
inline const sp<GraphicBuffer>& getActiveBuffer() const { return mActiveBuffer; }
|
inline const sp<GraphicBuffer>& getActiveBuffer() const { return mActiveBuffer; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void onFirstRef();
|
virtual void onFirstRef();
|
||||||
virtual void dump(String8& result, char* scratch, size_t size) const;
|
virtual void dump(String8& result, char* scratch, size_t size) const;
|
||||||
|
virtual void dumpStats(String8& result, char* buffer, size_t SIZE) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class SurfaceTextureLayer;
|
friend class SurfaceTextureLayer;
|
||||||
@ -110,6 +114,16 @@ private:
|
|||||||
uint32_t mCurrentTransform;
|
uint32_t mCurrentTransform;
|
||||||
uint32_t mCurrentScalingMode;
|
uint32_t mCurrentScalingMode;
|
||||||
bool mCurrentOpacity;
|
bool mCurrentOpacity;
|
||||||
|
bool mFrameLatencyNeeded;
|
||||||
|
int mFrameLatencyOffset;
|
||||||
|
struct Statistics {
|
||||||
|
Statistics() : timestamp(0), set(0), vsync(0) { }
|
||||||
|
nsecs_t timestamp; // buffer timestamp
|
||||||
|
nsecs_t set; // buffer displayed timestamp
|
||||||
|
nsecs_t vsync; // vsync immediately before set
|
||||||
|
};
|
||||||
|
// protected by mLock
|
||||||
|
Statistics mFrameStats[128];
|
||||||
|
|
||||||
// constants
|
// constants
|
||||||
PixelFormat mFormat;
|
PixelFormat mFormat;
|
||||||
@ -121,9 +135,6 @@ private:
|
|||||||
bool mSecure; // no screenshots
|
bool mSecure; // no screenshots
|
||||||
bool mProtectedByApp; // application requires protected path to external sink
|
bool mProtectedByApp; // application requires protected path to external sink
|
||||||
Region mPostedDirtyRegion;
|
Region mPostedDirtyRegion;
|
||||||
|
|
||||||
// binder thread, transaction thread
|
|
||||||
mutable Mutex mLock;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
@ -471,6 +471,9 @@ void LayerBase::drawWithOpenGL(const Region& clip) const
|
|||||||
void LayerBase::dump(String8& result, char* buffer, size_t SIZE) const
|
void LayerBase::dump(String8& result, char* buffer, size_t SIZE) const
|
||||||
{
|
{
|
||||||
const Layer::State& s(drawingState());
|
const Layer::State& s(drawingState());
|
||||||
|
s.transparentRegion.dump(result, "transparentRegion");
|
||||||
|
transparentRegionScreen.dump(result, "transparentRegionScreen");
|
||||||
|
visibleRegionScreen.dump(result, "visibleRegionScreen");
|
||||||
snprintf(buffer, SIZE,
|
snprintf(buffer, SIZE,
|
||||||
"+ %s %p (%s)\n"
|
"+ %s %p (%s)\n"
|
||||||
" "
|
" "
|
||||||
@ -491,6 +494,9 @@ void LayerBase::shortDump(String8& result, char* scratch, size_t size) const
|
|||||||
LayerBase::dump(result, scratch, size);
|
LayerBase::dump(result, scratch, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LayerBase::dumpStats(String8& result, char* scratch, size_t SIZE) const
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -205,10 +205,13 @@ public:
|
|||||||
/** called with the state lock when the surface is removed from the
|
/** called with the state lock when the surface is removed from the
|
||||||
* current list */
|
* current list */
|
||||||
virtual void onRemoved() { };
|
virtual void onRemoved() { };
|
||||||
|
|
||||||
|
virtual void onLayerDisplayed() { };
|
||||||
|
|
||||||
/** always call base class first */
|
/** always call base class first */
|
||||||
virtual void dump(String8& result, char* scratch, size_t size) const;
|
virtual void dump(String8& result, char* scratch, size_t size) const;
|
||||||
virtual void shortDump(String8& result, char* scratch, size_t size) const;
|
virtual void shortDump(String8& result, char* scratch, size_t size) const;
|
||||||
|
virtual void dumpStats(String8& result, char* buffer, size_t SIZE) const;
|
||||||
|
|
||||||
|
|
||||||
enum { // flags for doTransaction()
|
enum { // flags for doTransaction()
|
||||||
|
@ -431,7 +431,7 @@ bool SurfaceFlinger::threadLoop()
|
|||||||
} else {
|
} else {
|
||||||
// pretend we did the post
|
// pretend we did the post
|
||||||
hw.compositionComplete();
|
hw.compositionComplete();
|
||||||
hw.waitForVSync();
|
hw.waitForRefresh();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -445,6 +445,12 @@ void SurfaceFlinger::postFramebuffer()
|
|||||||
const nsecs_t now = systemTime();
|
const nsecs_t now = systemTime();
|
||||||
mDebugInSwapBuffers = now;
|
mDebugInSwapBuffers = now;
|
||||||
hw.flip(mSwapRegion);
|
hw.flip(mSwapRegion);
|
||||||
|
|
||||||
|
size_t numLayers = mVisibleLayersSortedByZ.size();
|
||||||
|
for (size_t i = 0; i < numLayers; i++) {
|
||||||
|
mVisibleLayersSortedByZ[i]->onLayerDisplayed();
|
||||||
|
}
|
||||||
|
|
||||||
mLastSwapBufferTime = systemTime() - now;
|
mLastSwapBufferTime = systemTime() - now;
|
||||||
mDebugInSwapBuffers = 0;
|
mDebugInSwapBuffers = 0;
|
||||||
mSwapRegion.clear();
|
mSwapRegion.clear();
|
||||||
@ -1463,14 +1469,6 @@ status_t SurfaceFlinger::dump(int fd, const Vector<String16>& args)
|
|||||||
IPCThreadState::self()->getCallingUid());
|
IPCThreadState::self()->getCallingUid());
|
||||||
result.append(buffer);
|
result.append(buffer);
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
// figure out if we're stuck somewhere
|
|
||||||
const nsecs_t now = systemTime();
|
|
||||||
const nsecs_t inSwapBuffers(mDebugInSwapBuffers);
|
|
||||||
const nsecs_t inTransaction(mDebugInTransaction);
|
|
||||||
nsecs_t inSwapBuffersDuration = (inSwapBuffers) ? now-inSwapBuffers : 0;
|
|
||||||
nsecs_t inTransactionDuration = (inTransaction) ? now-inTransaction : 0;
|
|
||||||
|
|
||||||
// Try to get the main lock, but don't insist if we can't
|
// Try to get the main lock, but don't insist if we can't
|
||||||
// (this would indicate SF is stuck, but we want to be able to
|
// (this would indicate SF is stuck, but we want to be able to
|
||||||
// print something in dumpsys).
|
// print something in dumpsys).
|
||||||
@ -1486,111 +1484,20 @@ status_t SurfaceFlinger::dump(int fd, const Vector<String16>& args)
|
|||||||
result.append(buffer);
|
result.append(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
bool dumpAll = true;
|
||||||
* Dump the visible layer list
|
size_t index = 0;
|
||||||
*/
|
if (args.size()) {
|
||||||
const LayerVector& currentLayers = mCurrentState.layersSortedByZ;
|
dumpAll = false;
|
||||||
const size_t count = currentLayers.size();
|
if (args[index] == String16("--latency")) {
|
||||||
snprintf(buffer, SIZE, "Visible layers (count = %d)\n", count);
|
index++;
|
||||||
result.append(buffer);
|
dumpStatsLocked(args, index, result, buffer, SIZE);
|
||||||
for (size_t i=0 ; i<count ; i++) {
|
}
|
||||||
const sp<LayerBase>& layer(currentLayers[i]);
|
|
||||||
layer->dump(result, buffer, SIZE);
|
|
||||||
const Layer::State& s(layer->drawingState());
|
|
||||||
s.transparentRegion.dump(result, "transparentRegion");
|
|
||||||
layer->transparentRegionScreen.dump(result, "transparentRegionScreen");
|
|
||||||
layer->visibleRegionScreen.dump(result, "visibleRegionScreen");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
if (dumpAll) {
|
||||||
* Dump the layers in the purgatory
|
dumpAllLocked(result, buffer, SIZE);
|
||||||
*/
|
|
||||||
|
|
||||||
const size_t purgatorySize = mLayerPurgatory.size();
|
|
||||||
snprintf(buffer, SIZE, "Purgatory state (%d entries)\n", purgatorySize);
|
|
||||||
result.append(buffer);
|
|
||||||
for (size_t i=0 ; i<purgatorySize ; i++) {
|
|
||||||
const sp<LayerBase>& layer(mLayerPurgatory.itemAt(i));
|
|
||||||
layer->shortDump(result, buffer, SIZE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Dump SurfaceFlinger global state
|
|
||||||
*/
|
|
||||||
|
|
||||||
snprintf(buffer, SIZE, "SurfaceFlinger global state:\n");
|
|
||||||
result.append(buffer);
|
|
||||||
|
|
||||||
const GLExtensions& extensions(GLExtensions::getInstance());
|
|
||||||
snprintf(buffer, SIZE, "GLES: %s, %s, %s\n",
|
|
||||||
extensions.getVendor(),
|
|
||||||
extensions.getRenderer(),
|
|
||||||
extensions.getVersion());
|
|
||||||
result.append(buffer);
|
|
||||||
|
|
||||||
snprintf(buffer, SIZE, "EGL : %s\n",
|
|
||||||
eglQueryString(graphicPlane(0).getEGLDisplay(),
|
|
||||||
EGL_VERSION_HW_ANDROID));
|
|
||||||
result.append(buffer);
|
|
||||||
|
|
||||||
snprintf(buffer, SIZE, "EXTS: %s\n", extensions.getExtension());
|
|
||||||
result.append(buffer);
|
|
||||||
|
|
||||||
mWormholeRegion.dump(result, "WormholeRegion");
|
|
||||||
const DisplayHardware& hw(graphicPlane(0).displayHardware());
|
|
||||||
snprintf(buffer, SIZE,
|
|
||||||
" orientation=%d, canDraw=%d\n",
|
|
||||||
mCurrentState.orientation, hw.canDraw());
|
|
||||||
result.append(buffer);
|
|
||||||
snprintf(buffer, SIZE,
|
|
||||||
" last eglSwapBuffers() time: %f us\n"
|
|
||||||
" last transaction time : %f us\n"
|
|
||||||
" refresh-rate : %f fps\n"
|
|
||||||
" x-dpi : %f\n"
|
|
||||||
" y-dpi : %f\n",
|
|
||||||
mLastSwapBufferTime/1000.0,
|
|
||||||
mLastTransactionTime/1000.0,
|
|
||||||
hw.getRefreshRate(),
|
|
||||||
hw.getDpiX(),
|
|
||||||
hw.getDpiY());
|
|
||||||
result.append(buffer);
|
|
||||||
|
|
||||||
if (inSwapBuffersDuration || !locked) {
|
|
||||||
snprintf(buffer, SIZE, " eglSwapBuffers time: %f us\n",
|
|
||||||
inSwapBuffersDuration/1000.0);
|
|
||||||
result.append(buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (inTransactionDuration || !locked) {
|
|
||||||
snprintf(buffer, SIZE, " transaction time: %f us\n",
|
|
||||||
inTransactionDuration/1000.0);
|
|
||||||
result.append(buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* VSYNC state
|
|
||||||
*/
|
|
||||||
mEventThread->dump(result, buffer, SIZE);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Dump HWComposer state
|
|
||||||
*/
|
|
||||||
HWComposer& hwc(hw.getHwComposer());
|
|
||||||
snprintf(buffer, SIZE, "h/w composer state:\n");
|
|
||||||
result.append(buffer);
|
|
||||||
snprintf(buffer, SIZE, " h/w composer %s and %s\n",
|
|
||||||
hwc.initCheck()==NO_ERROR ? "present" : "not present",
|
|
||||||
(mDebugDisableHWC || mDebugRegion) ? "disabled" : "enabled");
|
|
||||||
result.append(buffer);
|
|
||||||
hwc.dump(result, buffer, SIZE, mVisibleLayersSortedByZ);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Dump gralloc state
|
|
||||||
*/
|
|
||||||
const GraphicBufferAllocator& alloc(GraphicBufferAllocator::get());
|
|
||||||
alloc.dump(result);
|
|
||||||
hw.dump(result);
|
|
||||||
|
|
||||||
if (locked) {
|
if (locked) {
|
||||||
mStateLock.unlock();
|
mStateLock.unlock();
|
||||||
}
|
}
|
||||||
@ -1599,6 +1506,137 @@ status_t SurfaceFlinger::dump(int fd, const Vector<String16>& args)
|
|||||||
return NO_ERROR;
|
return NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SurfaceFlinger::dumpStatsLocked(const Vector<String16>& args, size_t& index,
|
||||||
|
String8& result, char* buffer, size_t SIZE) const
|
||||||
|
{
|
||||||
|
String8 name;
|
||||||
|
if (index < args.size()) {
|
||||||
|
name = String8(args[index]);
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
const LayerVector& currentLayers = mCurrentState.layersSortedByZ;
|
||||||
|
const size_t count = currentLayers.size();
|
||||||
|
for (size_t i=0 ; i<count ; i++) {
|
||||||
|
const sp<LayerBase>& layer(currentLayers[i]);
|
||||||
|
if (name.isEmpty()) {
|
||||||
|
snprintf(buffer, SIZE, "%s\n", layer->getName().string());
|
||||||
|
result.append(buffer);
|
||||||
|
}
|
||||||
|
if (name.isEmpty() || (name == layer->getName())) {
|
||||||
|
layer->dumpStats(result, buffer, SIZE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SurfaceFlinger::dumpAllLocked(
|
||||||
|
String8& result, char* buffer, size_t SIZE) const
|
||||||
|
{
|
||||||
|
// figure out if we're stuck somewhere
|
||||||
|
const nsecs_t now = systemTime();
|
||||||
|
const nsecs_t inSwapBuffers(mDebugInSwapBuffers);
|
||||||
|
const nsecs_t inTransaction(mDebugInTransaction);
|
||||||
|
nsecs_t inSwapBuffersDuration = (inSwapBuffers) ? now-inSwapBuffers : 0;
|
||||||
|
nsecs_t inTransactionDuration = (inTransaction) ? now-inTransaction : 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Dump the visible layer list
|
||||||
|
*/
|
||||||
|
const LayerVector& currentLayers = mCurrentState.layersSortedByZ;
|
||||||
|
const size_t count = currentLayers.size();
|
||||||
|
snprintf(buffer, SIZE, "Visible layers (count = %d)\n", count);
|
||||||
|
result.append(buffer);
|
||||||
|
for (size_t i=0 ; i<count ; i++) {
|
||||||
|
const sp<LayerBase>& layer(currentLayers[i]);
|
||||||
|
layer->dump(result, buffer, SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Dump the layers in the purgatory
|
||||||
|
*/
|
||||||
|
|
||||||
|
const size_t purgatorySize = mLayerPurgatory.size();
|
||||||
|
snprintf(buffer, SIZE, "Purgatory state (%d entries)\n", purgatorySize);
|
||||||
|
result.append(buffer);
|
||||||
|
for (size_t i=0 ; i<purgatorySize ; i++) {
|
||||||
|
const sp<LayerBase>& layer(mLayerPurgatory.itemAt(i));
|
||||||
|
layer->shortDump(result, buffer, SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Dump SurfaceFlinger global state
|
||||||
|
*/
|
||||||
|
|
||||||
|
snprintf(buffer, SIZE, "SurfaceFlinger global state:\n");
|
||||||
|
result.append(buffer);
|
||||||
|
|
||||||
|
const GLExtensions& extensions(GLExtensions::getInstance());
|
||||||
|
snprintf(buffer, SIZE, "GLES: %s, %s, %s\n",
|
||||||
|
extensions.getVendor(),
|
||||||
|
extensions.getRenderer(),
|
||||||
|
extensions.getVersion());
|
||||||
|
result.append(buffer);
|
||||||
|
|
||||||
|
snprintf(buffer, SIZE, "EGL : %s\n",
|
||||||
|
eglQueryString(graphicPlane(0).getEGLDisplay(),
|
||||||
|
EGL_VERSION_HW_ANDROID));
|
||||||
|
result.append(buffer);
|
||||||
|
|
||||||
|
snprintf(buffer, SIZE, "EXTS: %s\n", extensions.getExtension());
|
||||||
|
result.append(buffer);
|
||||||
|
|
||||||
|
mWormholeRegion.dump(result, "WormholeRegion");
|
||||||
|
const DisplayHardware& hw(graphicPlane(0).displayHardware());
|
||||||
|
snprintf(buffer, SIZE,
|
||||||
|
" orientation=%d, canDraw=%d\n",
|
||||||
|
mCurrentState.orientation, hw.canDraw());
|
||||||
|
result.append(buffer);
|
||||||
|
snprintf(buffer, SIZE,
|
||||||
|
" last eglSwapBuffers() time: %f us\n"
|
||||||
|
" last transaction time : %f us\n"
|
||||||
|
" refresh-rate : %f fps\n"
|
||||||
|
" x-dpi : %f\n"
|
||||||
|
" y-dpi : %f\n",
|
||||||
|
mLastSwapBufferTime/1000.0,
|
||||||
|
mLastTransactionTime/1000.0,
|
||||||
|
hw.getRefreshRate(),
|
||||||
|
hw.getDpiX(),
|
||||||
|
hw.getDpiY());
|
||||||
|
result.append(buffer);
|
||||||
|
|
||||||
|
snprintf(buffer, SIZE, " eglSwapBuffers time: %f us\n",
|
||||||
|
inSwapBuffersDuration/1000.0);
|
||||||
|
result.append(buffer);
|
||||||
|
|
||||||
|
snprintf(buffer, SIZE, " transaction time: %f us\n",
|
||||||
|
inTransactionDuration/1000.0);
|
||||||
|
result.append(buffer);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* VSYNC state
|
||||||
|
*/
|
||||||
|
mEventThread->dump(result, buffer, SIZE);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Dump HWComposer state
|
||||||
|
*/
|
||||||
|
HWComposer& hwc(hw.getHwComposer());
|
||||||
|
snprintf(buffer, SIZE, "h/w composer state:\n");
|
||||||
|
result.append(buffer);
|
||||||
|
snprintf(buffer, SIZE, " h/w composer %s and %s\n",
|
||||||
|
hwc.initCheck()==NO_ERROR ? "present" : "not present",
|
||||||
|
(mDebugDisableHWC || mDebugRegion) ? "disabled" : "enabled");
|
||||||
|
result.append(buffer);
|
||||||
|
hwc.dump(result, buffer, SIZE, mVisibleLayersSortedByZ);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Dump gralloc state
|
||||||
|
*/
|
||||||
|
const GraphicBufferAllocator& alloc(GraphicBufferAllocator::get());
|
||||||
|
alloc.dump(result);
|
||||||
|
hw.dump(result);
|
||||||
|
}
|
||||||
|
|
||||||
status_t SurfaceFlinger::onTransact(
|
status_t SurfaceFlinger::onTransact(
|
||||||
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
|
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
|
||||||
{
|
{
|
||||||
|
@ -337,6 +337,9 @@ private:
|
|||||||
void debugFlashRegions();
|
void debugFlashRegions();
|
||||||
void drawWormhole() const;
|
void drawWormhole() const;
|
||||||
|
|
||||||
|
void dumpStatsLocked(const Vector<String16>& args, size_t& index,
|
||||||
|
String8& result, char* buffer, size_t SIZE) const;
|
||||||
|
void dumpAllLocked(String8& result, char* buffer, size_t SIZE) const;
|
||||||
|
|
||||||
mutable MessageQueue mEventQueue;
|
mutable MessageQueue mEventQueue;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user