Bug 944866 - Part 2: Add layers.scroll-graph. r=gal

--HG--
extra : rebase_source : b517f110b09056b3037f9bfae609ff14e6af3859
This commit is contained in:
Benoit Girard 2013-12-03 10:49:46 -05:00
parent 965870498a
commit cb5d1145f7
7 changed files with 156 additions and 0 deletions

View File

@ -32,6 +32,7 @@
#include "nsRegion.h" // for nsIntRegion
#include "nsTArray.h" // for nsAutoTArray
#include "nsTraceRefcnt.h" // for MOZ_COUNT_CTOR, etc
#include <vector>
namespace mozilla {
namespace layers {
@ -79,6 +80,126 @@ GetOpaqueRect(Layer* aLayer)
return result;
}
struct LayerVelocityUserData : public LayerUserData {
public:
LayerVelocityUserData() {
MOZ_COUNT_CTOR(LayerVelocityUserData);
}
~LayerVelocityUserData() {
MOZ_COUNT_DTOR(LayerVelocityUserData);
}
struct VelocityData {
VelocityData(TimeStamp frameTime, int scrollX, int scrollY)
: mFrameTime(frameTime)
, mPoint(scrollX, scrollY)
{}
TimeStamp mFrameTime;
Point mPoint;
};
std::vector<VelocityData> mData;
};
static void DrawVelGraph(const nsIntRect& aClipRect,
LayerManagerComposite* aManager,
Layer* aLayer) {
static char sLayerVelocityUserDataKey;
Compositor* compositor = aManager->GetCompositor();
gfx::Rect clipRect(aClipRect.x, aClipRect.y,
aClipRect.width, aClipRect.height);
TimeStamp now = TimeStamp::Now();
void* key = reinterpret_cast<void*>(&sLayerVelocityUserDataKey);
if (!aLayer->HasUserData(key)) {
aLayer->SetUserData(key, new LayerVelocityUserData());
}
LayerVelocityUserData* velocityData =
static_cast<LayerVelocityUserData*>(aLayer->GetUserData(key));
if (velocityData->mData.size() >= 1 &&
now > velocityData->mData[velocityData->mData.size() - 1].mFrameTime +
TimeDuration::FromMilliseconds(200)) {
// clear stale data
velocityData->mData.clear();
}
nsIntPoint scrollOffset =
aLayer->GetEffectiveVisibleRegion().GetBounds().TopLeft();
velocityData->mData.push_back(
LayerVelocityUserData::VelocityData(now, scrollOffset.x, scrollOffset.y));
// XXX: Uncomment these lines to enable ScrollGraph logging. This is
// useful for HVGA phones or to output the data to accurate
// graphing software.
//printf_stderr("ScrollGraph (%p): %i, %i\n",
// aLayer, scrollOffset.x, scrollOffset.y);
// Keep a circular buffer of 100.
size_t circularBufferSize = 100;
if (velocityData->mData.size() > circularBufferSize) {
velocityData->mData.erase(velocityData->mData.begin());
}
if (velocityData->mData.size() == 1) {
return;
}
// Clear and disable the graph when it's flat
for (size_t i = 1; i < velocityData->mData.size(); i++) {
if (velocityData->mData[i - 1].mPoint != velocityData->mData[i].mPoint) {
break;
}
if (i == velocityData->mData.size() - 1) {
velocityData->mData.clear();
return;
}
}
if (aLayer->GetEffectiveVisibleRegion().GetBounds().width < 300 ||
aLayer->GetEffectiveVisibleRegion().GetBounds().height < 300) {
// Don't want a graph for smaller layers
return;
}
aManager->SetDebugOverlayWantsNextFrame(true);
gfx::Matrix4x4 transform;
ToMatrix4x4(aLayer->GetEffectiveTransform(), transform);
nsIntRect bounds = aLayer->GetEffectiveVisibleRegion().GetBounds();
gfx::Rect graphBounds = gfx::Rect(bounds.x, bounds.y,
bounds.width, bounds.height);
gfx::Rect graphRect = gfx::Rect(bounds.x, bounds.y, 200, 100);
float opacity = 1.0;
EffectChain effects;
effects.mPrimaryEffect = new EffectSolidColor(gfx::Color(0.2,0,0,1));
compositor->DrawQuad(graphRect,
clipRect,
effects,
opacity,
transform);
std::vector<gfx::Point> graph;
int yScaleFactor = 3;
for (int32_t i = (int32_t)velocityData->mData.size() - 2; i >= 0; i--) {
const Point& p1 = velocityData->mData[i+1].mPoint;
const Point& p2 = velocityData->mData[i].mPoint;
int vel = sqrt((p1.x - p2.x) * (p1.x - p2.x) +
(p1.y - p2.y) * (p1.y - p2.y));
graph.push_back(
gfx::Point(bounds.x + graphRect.width / circularBufferSize * i,
graphBounds.y + graphRect.height - vel/yScaleFactor));
}
compositor->DrawLines(graph, clipRect, gfx::Color(0,1,0,1),
opacity, transform);
}
template<class ContainerT> void
ContainerRender(ContainerT* aContainer,
LayerManagerComposite* aManager,
@ -200,6 +321,10 @@ ContainerRender(ContainerT* aContainer,
} else {
layerToRender->RenderLayer(clipRect);
}
if (gfxPlatform::GetPrefLayersScrollGraph()) {
DrawVelGraph(clipRect, aManager, layerToRender->GetLayer());
}
// invariant: our GL context should be current here, I don't think we can
// assert it though
}

View File

@ -103,6 +103,7 @@ LayerManagerComposite::LayerManagerComposite(Compositor* aCompositor)
: mCompositor(aCompositor)
, mInTransaction(false)
, mIsCompositorReady(false)
, mDebugOverlayWantsNextFrame(false)
{
MOZ_ASSERT(aCompositor);
}

View File

@ -241,6 +241,14 @@ public:
bool PlatformDestroySharedSurface(SurfaceDescriptor* aSurface);
/**
* LayerManagerComposite provides sophisticated debug overlays
* that can request a next frame.
*/
bool DebugOverlayWantsNextFrame() { return mDebugOverlayWantsNextFrame; }
void SetDebugOverlayWantsNextFrame(bool aVal)
{ mDebugOverlayWantsNextFrame = aVal; }
private:
/** Region we're clipping our current drawing to. */
nsIntRegion mClippingRegion;
@ -287,6 +295,7 @@ private:
bool mIsCompositorReady;
nsIntRegion mInvalidRegion;
nsAutoPtr<LayerProperties> mClonedLayerTreeProperties;
bool mDebugOverlayWantsNextFrame;
};
/**

View File

@ -559,6 +559,7 @@ CompositorParent::CompositeInTransaction()
NS_ABORT_IF_FALSE(CompositorThreadID() == PlatformThread::CurrentId(),
"Composite can only be called on the compositor thread");
mCurrentCompositeTask = nullptr;
mLayerManager->SetDebugOverlayWantsNextFrame(false);
mLastCompose = TimeStamp::Now();
@ -595,6 +596,10 @@ CompositorParent::CompositeInTransaction()
#endif
mLayerManager->EndEmptyTransaction();
if (mLayerManager->DebugOverlayWantsNextFrame()) {
ScheduleComposition();
}
#ifdef COMPOSITOR_PERFORMANCE_WARNING
if (mExpectedComposeTime + TimeDuration::FromMilliseconds(15) < TimeStamp::Now()) {
printf_stderr("Compositor: Composite took %i ms.\n",

View File

@ -2037,6 +2037,7 @@ static bool sPrefLayersAccelerationDisabled = false;
static bool sPrefLayersPreferOpenGL = false;
static bool sPrefLayersPreferD3D9 = false;
static bool sPrefLayersDump = false;
static bool sPrefLayersScrollGraph = false;
static bool sLayersSupportsD3D9 = false;
static int sPrefLayoutFrameRate = -1;
static bool sBufferRotationEnabled = false;
@ -2064,6 +2065,7 @@ InitLayersAccelerationPrefs()
sPrefLayersPreferOpenGL = Preferences::GetBool("layers.prefer-opengl", false);
sPrefLayersPreferD3D9 = Preferences::GetBool("layers.prefer-d3d9", false);
sPrefLayersDump = Preferences::GetBool("layers.dump", false);
sPrefLayersScrollGraph = Preferences::GetBool("layers.scroll-graph", false);
sPrefLayoutFrameRate = Preferences::GetInt("layout.frame_rate", -1);
sBufferRotationEnabled = Preferences::GetBool("layers.bufferrotation.enabled", true);
sComponentAlphaEnabled = Preferences::GetBool("layers.componentalpha.enabled", true);
@ -2168,6 +2170,15 @@ gfxPlatform::GetPrefLayersDump()
return sPrefLayersDump;
}
bool
gfxPlatform::GetPrefLayersScrollGraph()
{
// this function is called from the compositor thread, so it is not
// safe to init the prefs etc. from here.
MOZ_ASSERT(sLayersAccelerationPrefsInitialized);
return sPrefLayersScrollGraph;
}
bool
gfxPlatform::BufferRotationEnabled()
{

View File

@ -506,6 +506,7 @@ public:
static bool CanUseDirect3D9();
static int GetPrefLayoutFrameRate();
static bool GetPrefLayersDump();
static bool GetPrefLayersScrollGraph();
static bool OffMainThreadCompositionRequired();

View File

@ -4243,6 +4243,10 @@ pref("layers.draw-bigimage-borders", false);
pref("layers.frame-counter", false);
// Max number of layers per container. See Overwrite in mobile prefs.
pref("layers.max-active", -1);
// When a layer is moving it will add a scroll graph to measure the smoothness
// of the movement. NOTE: This pref triggers composites to refresh
// the graph.
pref("layers.scroll-graph", false);
// Set the default values, and then override per-platform as needed
pref("layers.offmainthreadcomposition.enabled", false);