Bug 963821 - Port FPS counter to the Compositor API. r=bas

--HG--
rename : gfx/layers/opengl/FPSCounter.h => gfx/layers/composite/FPSCounter.h
This commit is contained in:
Benoit Girard 2014-02-10 17:14:11 -05:00
parent 64ce5e6697
commit 828b60ea42
12 changed files with 166 additions and 241 deletions

View File

@ -407,13 +407,6 @@ public:
mCompositorID = aID;
}
/**
* Notify the compositor that a layers transaction has occured. This is only
* used for FPS information at the moment.
* XXX: surely there is a better way to do this?
*/
virtual void NotifyLayersTransaction() = 0;
/**
* Notify the compositor that composition is being paused. This allows the
* compositor to temporarily release any resources.
@ -453,6 +446,17 @@ public:
*/
static LayersBackend GetBackend();
size_t GetFillRatio() {
float fillRatio = 0;
if (mPixelsFilled > 0 && mPixelsPerFrame > 0) {
fillRatio = 100.0f * float(mPixelsFilled) / float(mPixelsPerFrame);
if (fillRatio > 999.0f) {
fillRatio = 999.0f;
}
}
return fillRatio;
}
protected:
void DrawDiagnosticsInternal(DiagnosticFlags aFlags,
const gfx::Rect& aVisibleRect,

View File

@ -114,8 +114,6 @@ public:
virtual void PrepareViewport(const gfx::IntSize& aSize,
const gfx::Matrix& aWorldTransform) MOZ_OVERRIDE { }
virtual void NotifyLayersTransaction() MOZ_OVERRIDE { }
virtual const char* Name() const { return "Basic"; }
virtual nsIWidget* GetWidget() const MOZ_OVERRIDE { return mWidget; }

View File

@ -19,6 +19,7 @@ class GLContext;
}
namespace layers {
class DataTextureSource;
class ShaderProgramOGL;
const double kFpsWindowMs = 250.0;
@ -71,18 +72,19 @@ private:
};
struct FPSState {
GLuint mTexture;
FPSCounter mCompositionFps;
FPSCounter mTransactionFps;
gl::VBOArena mVBOs;
FPSState() : mTexture(0) { }
FPSState() {}
void DrawFPS(TimeStamp, unsigned, gl::GLContext*, ShaderProgramOGL*);
void DrawFPS(TimeStamp, unsigned, Compositor* aCompositor);
void NotifyShadowTreeTransaction() {
mTransactionFps.AddFrame(TimeStamp::Now());
}
private:
RefPtr<DataTextureSource> mFPSTextureSource;
};
}

View File

@ -11,6 +11,7 @@
#include "Composer2D.h" // for Composer2D
#include "CompositableHost.h" // for CompositableHost
#include "ContainerLayerComposite.h" // for ContainerLayerComposite, etc
#include "FPSCounter.h" // for FPSState, FPSCounter
#include "FrameMetrics.h" // for FrameMetrics
#include "GeckoProfiler.h" // for profiler_set_frame_number, etc
#include "ImageLayerComposite.h" // for ImageLayerComposite
@ -302,38 +303,129 @@ LayerManagerComposite::RootLayer() const
return ToLayerComposite(mRoot);
}
// Size of the builtin font.
static const float FontHeight = 7.f;
static const float FontWidth = 4.f;
static const float FontStride = 4.f;
// Scale the font when drawing it to the viewport for better readability.
static const float FontScaleX = 2.f;
static const float FontScaleY = 3.f;
static void DrawDigits(unsigned int aValue,
int aOffsetX, int aOffsetY,
Compositor* aCompositor,
EffectChain& aEffectChain)
{
if (aValue > 999) {
aValue = 999;
}
unsigned int divisor = 100;
float textureWidth = FontWidth * 10;
gfx::Float opacity = 1;
gfx::Matrix4x4 transform;
transform.Scale(FontScaleX, FontScaleY, 1);
for (size_t n = 0; n < 3; ++n) {
unsigned int digit = aValue % (divisor * 10) / divisor;
divisor /= 10;
RefPtr<TexturedEffect> texturedEffect = static_cast<TexturedEffect*>(aEffectChain.mPrimaryEffect.get());
texturedEffect->mTextureCoords = Rect(float(digit * FontWidth) / textureWidth, 0, FontWidth / textureWidth, 1.0f);
Rect drawRect = Rect(aOffsetX + n * FontWidth, aOffsetY, FontWidth, FontHeight);
Rect clipRect = Rect(0, 0, 300, 100);
aCompositor->DrawQuad(drawRect, clipRect,
aEffectChain, opacity, transform);
}
}
void FPSState::DrawFPS(TimeStamp aNow,
unsigned int aFillRatio,
Compositor* aCompositor)
{
if (!mFPSTextureSource) {
const char *text =
" "
" XXX XX XXX XXX X X XXX XXX XXX XXX XXX"
" X X X X X X X X X X X X X X"
" X X X XXX XXX XXX XXX XXX X XXX XXX"
" X X X X X X X X X X X X X"
" XXX XXX XXX XXX X XXX XXX X XXX X"
" ";
// Convert the text encoding above to RGBA.
int w = FontWidth * 10;
int h = FontHeight;
uint32_t* buf = (uint32_t *) malloc(w * h * sizeof(uint32_t));
for (int i = 0; i < h; i++) {
for (int j = 0; j < w; j++) {
uint32_t purple = 0xfff000ff;
uint32_t white = 0xffffffff;
buf[i * w + j] = (text[i * w + j] == ' ') ? purple : white;
}
}
int bytesPerPixel = 4;
RefPtr<DataSourceSurface> fpsSurface = Factory::CreateWrappingDataSourceSurface(
reinterpret_cast<uint8_t*>(buf), w * bytesPerPixel, IntSize(w, h), SurfaceFormat::B8G8R8A8);
mFPSTextureSource = aCompositor->CreateDataTextureSource();
mFPSTextureSource->Update(fpsSurface);
}
EffectChain effectChain;
effectChain.mPrimaryEffect = CreateTexturedEffect(SurfaceFormat::B8G8R8A8, mFPSTextureSource, Filter::POINT);
unsigned int fps = unsigned(mCompositionFps.AddFrameAndGetFps(aNow));
unsigned int txnFps = unsigned(mTransactionFps.GetFpsAt(aNow));
DrawDigits(fps, 0, 0, aCompositor, effectChain);
DrawDigits(txnFps, FontWidth * 4, 0, aCompositor, effectChain);
DrawDigits(aFillRatio, FontWidth * 8, 0, aCompositor, effectChain);
}
static uint16_t sFrameCount = 0;
void
LayerManagerComposite::RenderDebugOverlay(const Rect& aBounds)
{
if (!gfxPlatform::DrawFrameCounter()) {
return;
}
profiler_set_frame_number(sFrameCount);
uint16_t frameNumber = sFrameCount;
const uint16_t bitWidth = 3;
float opacity = 1.0;
gfx::Rect clip(0,0, bitWidth*16, bitWidth);
for (size_t i = 0; i < 16; i++) {
gfx::Color bitColor;
if ((frameNumber >> i) & 0x1) {
bitColor = gfx::Color(0, 0, 0, 1.0);
} else {
bitColor = gfx::Color(1.0, 1.0, 1.0, 1.0);
if (gfxPlatform::GetPrefLayersDrawFPS()) {
if (!mFPS) {
mFPS = new FPSState();
}
EffectChain effects;
effects.mPrimaryEffect = new EffectSolidColor(bitColor);
mCompositor->DrawQuad(gfx::Rect(bitWidth*i, 0, bitWidth, bitWidth),
clip,
effects,
opacity,
gfx::Matrix4x4());
float fillRatio = mCompositor->GetFillRatio();
mFPS->DrawFPS(TimeStamp::Now(), unsigned(fillRatio), mCompositor);
} else {
mFPS = nullptr;
}
if (gfxPlatform::DrawFrameCounter()) {
profiler_set_frame_number(sFrameCount);
uint16_t frameNumber = sFrameCount;
const uint16_t bitWidth = 3;
float opacity = 1.0;
gfx::Rect clip(0,0, bitWidth*16, bitWidth);
for (size_t i = 0; i < 16; i++) {
gfx::Color bitColor;
if ((frameNumber >> i) & 0x1) {
bitColor = gfx::Color(0, 0, 0, 1.0);
} else {
bitColor = gfx::Color(1.0, 1.0, 1.0, 1.0);
}
EffectChain effects;
effects.mPrimaryEffect = new EffectSolidColor(bitColor);
mCompositor->DrawQuad(gfx::Rect(bitWidth*i, 0, bitWidth, bitWidth),
clip,
effects,
opacity,
gfx::Matrix4x4());
}
// We intentionally overflow at 2^16.
sFrameCount++;
}
// We intentionally overflow at 2^16.
sFrameCount++;
}
void
@ -352,7 +444,11 @@ LayerManagerComposite::Render()
/** Our more efficient but less powerful alter ego, if one is available. */
nsRefPtr<Composer2D> composer2D = mCompositor->GetWidget()->GetComposer2D();
if (composer2D && composer2D->TryRender(mRoot, mWorldMatrix)) {
if (mFPS && composer2D && composer2D->TryRender(mRoot, mWorldMatrix)) {
double fps = mFPS->mCompositionFps.AddFrameAndGetFps(TimeStamp::Now());
if (gfxPlatform::GetPrefLayersDrawFPS()) {
printf_stderr("HWComposer: FPS is %g\n", fps);
}
mCompositor->EndFrameForExternalComposition(mWorldMatrix);
return;
}
@ -787,6 +883,14 @@ LayerManagerComposite::CanUseCanvasLayerForSize(const IntSize &aSize)
aSize.height));
}
void
LayerManagerComposite::NotifyShadowTreeTransaction()
{
if (mFPS) {
mFPS->NotifyShadowTreeTransaction();
}
}
#ifndef MOZ_HAVE_PLATFORM_SPECIFIC_LAYER_BUFFERS
/*static*/ bool

View File

@ -61,6 +61,7 @@ class RefLayerComposite;
class SurfaceDescriptor;
class ThebesLayerComposite;
class TiledLayerComposer;
struct FPSState;
class LayerManagerComposite : public LayerManager
{
@ -224,6 +225,8 @@ public:
void SetDebugOverlayWantsNextFrame(bool aVal)
{ mDebugOverlayWantsNextFrame = aVal; }
void NotifyShadowTreeTransaction();
private:
/** Region we're clipping our current drawing to. */
nsIntRegion mClippingRegion;
@ -256,13 +259,14 @@ private:
void WorldTransformRect(nsIntRect& aRect);
RefPtr<Compositor> mCompositor;
nsAutoPtr<LayerProperties> mClonedLayerTreeProperties;
gfx::Matrix mWorldMatrix;
nsIntRegion mInvalidRegion;
nsAutoPtr<FPSState> mFPS;
bool mInTransaction;
bool mIsCompositorReady;
nsIntRegion mInvalidRegion;
nsAutoPtr<LayerProperties> mClonedLayerTreeProperties;
bool mDebugOverlayWantsNextFrame;
};

View File

@ -136,8 +136,6 @@ public:
virtual const char* Name() const MOZ_OVERRIDE { return "Direct3D 11"; }
#endif
virtual void NotifyLayersTransaction() MOZ_OVERRIDE { }
virtual nsIWidget* GetWidget() const MOZ_OVERRIDE { return mWidget; }
ID3D11Device* GetDevice() { return mDevice; }

View File

@ -83,8 +83,6 @@ public:
virtual const char* Name() const MOZ_OVERRIDE { return "Direct3D9"; }
#endif
virtual void NotifyLayersTransaction() MOZ_OVERRIDE {}
virtual nsIWidget* GetWidget() const MOZ_OVERRIDE { return mWidget; }
IDirect3DDevice9* device() const

View File

@ -515,7 +515,7 @@ CompositorParent::NotifyShadowTreeTransaction(uint64_t aId, bool aIsFirstPaint,
AutoResolveRefLayers resolve(mCompositionManager);
mApzcTreeManager->UpdatePanZoomControllerTree(this, mLayerManager->GetRoot(), aIsFirstPaint, aId);
mCompositor->NotifyLayersTransaction();
mLayerManager->NotifyShadowTreeTransaction();
}
if (aScheduleComposite) {
ScheduleComposition();
@ -731,7 +731,7 @@ CompositorParent::ShadowLayersUpdated(LayerTransactionParent* aLayerTree,
if (aScheduleComposite) {
ScheduleComposition();
}
mCompositor->NotifyLayersTransaction();
mLayerManager->NotifyShadowTreeTransaction();
}
void

View File

@ -7,7 +7,6 @@
#include <stddef.h> // for size_t
#include <stdint.h> // for uint32_t, uint8_t
#include <stdlib.h> // for free, malloc
#include "FPSCounter.h" // for FPSState, FPSCounter
#include "GLContextProvider.h" // for GLContextProvider
#include "GLContext.h" // for GLContext
#include "GLUploadHelpers.h"
@ -135,112 +134,6 @@ DrawQuads(GLContext *aGLContext,
aGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0);
}
// Size of the builtin font.
static const float FontHeight = 7.f;
static const float FontWidth = 5.f;
static const float FontStride = 4.f;
// Scale the font when drawing it to the viewport for better readability.
static const float FontScaleX = 2.f;
static const float FontScaleY = 3.f;
// Size of the font texture (POT).
static const size_t FontTextureWidth = 64;
static const size_t FontTextureHeight = 8;
static void
AddDigits(RectTriangles &aRects,
const gfx::IntSize aViewportSize,
unsigned int aOffset,
unsigned int aValue)
{
unsigned int divisor = 100;
for (size_t n = 0; n < 3; ++n) {
gfxRect d(aOffset * FontWidth, 0.f, FontWidth, FontHeight);
d.Scale(FontScaleX / aViewportSize.width, FontScaleY / aViewportSize.height);
unsigned int digit = aValue % (divisor * 10) / divisor;
gfxRect t(digit * FontStride, 0.f, FontWidth, FontHeight);
t.Scale(1.f / FontTextureWidth, 1.f / FontTextureHeight);
aRects.addRect(d.x, d.y, d.x + d.width, d.y + d.height,
t.x, t.y, t.x + t.width, t.y + t.height,
false);
divisor /= 10;
++aOffset;
}
}
void
FPSState::DrawFPS(TimeStamp aNow,
unsigned int aFillRatio,
GLContext* aContext,
ShaderProgramOGL* aProgram)
{
if (!mTexture) {
// Bind the number of textures we need, in this case one.
aContext->fGenTextures(1, &mTexture);
aContext->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture);
aContext->fTexParameteri(LOCAL_GL_TEXTURE_2D,LOCAL_GL_TEXTURE_MIN_FILTER,LOCAL_GL_NEAREST);
aContext->fTexParameteri(LOCAL_GL_TEXTURE_2D,LOCAL_GL_TEXTURE_MAG_FILTER,LOCAL_GL_NEAREST);
const char *text =
" "
" XXX XX XXX XXX X X XXX XXX XXX XXX XXX "
" X X X X X X X X X X X X X X "
" X X X XXX XXX XXX XXX XXX X XXX XXX "
" X X X X X X X X X X X X X "
" XXX XXX XXX XXX X XXX XXX X XXX X "
" ";
// Convert the text encoding above to RGBA.
uint32_t* buf = (uint32_t *) malloc(64 * 8 * sizeof(uint32_t));
for (int i = 0; i < 7; i++) {
for (int j = 0; j < 41; j++) {
uint32_t purple = 0xfff000ff;
uint32_t white = 0xffffffff;
buf[i * 64 + j] = (text[i * 41 + j] == ' ') ? purple : white;
}
}
aContext->fTexImage2D(LOCAL_GL_TEXTURE_2D, 0, LOCAL_GL_RGBA, 64, 8, 0, LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE, buf);
free(buf);
}
mVBOs.Reset();
GLint viewport[4];
aContext->fGetIntegerv(LOCAL_GL_VIEWPORT, viewport);
gfx::IntSize viewportSize(viewport[2], viewport[3]);
unsigned int fps = unsigned(mCompositionFps.AddFrameAndGetFps(aNow));
unsigned int txnFps = unsigned(mTransactionFps.GetFpsAt(aNow));
RectTriangles rects;
AddDigits(rects, viewportSize, 0, fps);
AddDigits(rects, viewportSize, 4, txnFps);
AddDigits(rects, viewportSize, 8, aFillRatio);
// Turn necessary features on
aContext->fEnable(LOCAL_GL_BLEND);
aContext->fBlendFunc(LOCAL_GL_ONE, LOCAL_GL_SRC_COLOR);
aContext->fActiveTexture(LOCAL_GL_TEXTURE0);
aContext->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture);
aProgram->Activate();
aProgram->SetTextureUnit(0);
aProgram->SetLayerQuadRect(gfx::Rect(0.f, 0.f, viewport[2], viewport[3]));
aProgram->SetLayerOpacity(1.f);
aProgram->SetTextureTransform(Matrix4x4());
aProgram->SetLayerTransform(Matrix4x4());
aProgram->SetRenderOffset(0, 0);
aContext->fBlendFuncSeparate(LOCAL_GL_ONE, LOCAL_GL_ZERO,
LOCAL_GL_ONE, LOCAL_GL_ZERO);
DrawQuads(aContext, mVBOs, aProgram, rects);
}
CompositorOGL::CompositorOGL(nsIWidget *aWidget, int aSurfaceWidth,
int aSurfaceHeight, bool aUseExternalSurfaceSize)
: mWidget(aWidget)
@ -327,11 +220,6 @@ CompositorOGL::Destroy()
gl()->fDeleteTextures(mTextures.Length(), &mTextures[0]);
}
mVBOs.Flush(gl());
if (mFPS) {
if (mFPS->mTexture > 0)
gl()->fDeleteTextures(1, &mFPS->mTexture);
mFPS->mVBOs.Flush(gl());
}
}
mTextures.SetLength(0);
if (!mDestroyed) {
@ -369,15 +257,6 @@ CompositorOGL::CleanupResources()
mGLContext = nullptr;
}
// Impl of a a helper-runnable's "Run" method, used in Initialize()
NS_IMETHODIMP
CompositorOGL::ReadDrawFPSPref::Run()
{
// NOTE: This must match the code in Initialize()'s NS_IsMainThread check.
Preferences::AddBoolVarCache(&sDrawFPS, "layers.acceleration.draw-fps");
return NS_OK;
}
bool
CompositorOGL::Initialize()
{
@ -545,14 +424,6 @@ CompositorOGL::Initialize()
console->LogStringMessage(msg.get());
}
if (NS_IsMainThread()) {
// NOTE: This must match the code in ReadDrawFPSPref::Run().
Preferences::AddBoolVarCache(&sDrawFPS, "layers.acceleration.draw-fps");
} else {
// We have to dispatch an event to the main thread to read the pref.
NS_DispatchToMainThread(new ReadDrawFPSPref());
}
reporter.SetSuccessful();
return true;
}
@ -756,8 +627,6 @@ GetFrameBufferInternalFormat(GLContext* gl,
return LOCAL_GL_RGBA;
}
bool CompositorOGL::sDrawFPS = false;
/*
* Returns a size that is larger than and closest to aSize where both
* width and height are powers of two.
@ -1425,22 +1294,6 @@ CompositorOGL::EndFrame()
mCurrentRenderTarget = nullptr;
if (sDrawFPS && !mFPS) {
mFPS = new FPSState();
} else if (!sDrawFPS && mFPS) {
mFPS = nullptr;
}
if (mFPS) {
float fillRatio = 0;
if (mPixelsFilled > 0 && mPixelsPerFrame > 0) {
fillRatio = 100.0f * float(mPixelsFilled) / float(mPixelsPerFrame);
if (fillRatio > 999.0f)
fillRatio = 999.0f;
}
mFPS->DrawFPS(TimeStamp::Now(), unsigned(fillRatio), mGLContext, GetProgram(RGBXLayerProgramType));
}
mGLContext->SwapBuffers();
mGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0);
}
@ -1448,14 +1301,6 @@ CompositorOGL::EndFrame()
void
CompositorOGL::EndFrameForExternalComposition(const gfx::Matrix& aTransform)
{
if (sDrawFPS) {
if (!mFPS) {
mFPS = new FPSState();
}
double fps = mFPS->mCompositionFps.AddFrameAndGetFps(TimeStamp::Now());
printf_stderr("HWComposer: FPS is %g\n", fps);
}
// This lets us reftest and screenshot content rendered externally
if (mTarget) {
MakeCurrent();
@ -1532,29 +1377,6 @@ CompositorOGL::CopyToTarget(DrawTarget *aTarget, const gfx::Matrix& aTransform)
aTarget->Flush();
}
double
CompositorOGL::AddFrameAndGetFps(const TimeStamp& timestamp)
{
if (sDrawFPS) {
if (!mFPS) {
mFPS = new FPSState();
}
double fps = mFPS->mCompositionFps.AddFrameAndGetFps(timestamp);
return fps;
}
return 0.;
}
void
CompositorOGL::NotifyLayersTransaction()
{
if (mFPS) {
mFPS->NotifyShadowTreeTransaction();
}
}
void
CompositorOGL::Pause()
{

View File

@ -51,7 +51,6 @@ class GLManagerCompositor;
class TextureSource;
struct Effect;
struct EffectChain;
struct FPSState;
class CompositorOGL : public Compositor
{
@ -151,8 +150,6 @@ public:
virtual const char* Name() const MOZ_OVERRIDE { return "OGL"; }
#endif // MOZ_DUMP_PAINTING
virtual void NotifyLayersTransaction() MOZ_OVERRIDE;
virtual void Pause() MOZ_OVERRIDE;
virtual bool Resume() MOZ_OVERRIDE;
@ -197,12 +194,6 @@ private:
ScreenPoint mRenderOffset;
/** Helper-class used by Initialize **/
class ReadDrawFPSPref MOZ_FINAL : public nsRunnable {
public:
NS_IMETHOD Run() MOZ_OVERRIDE;
};
already_AddRefed<mozilla::gl::GLContext> CreateContext();
/** Shader Programs */
@ -325,11 +316,6 @@ private:
*/
void CopyToTarget(gfx::DrawTarget* aTarget, const gfx::Matrix& aWorldMatrix);
/**
* Records the passed frame timestamp and returns the current estimated FPS.
*/
double AddFrameAndGetFps(const TimeStamp& timestamp);
/**
* Implements the flipping of the y-axis to convert from layers/compositor
* coordinates to OpenGL coordinates.
@ -343,7 +329,6 @@ private:
bool mDestroyed;
nsAutoPtr<FPSState> mFPS;
// Textures used for direct texturing of buffers like gralloc.
// The index of the texture in this array must correspond to the texture unit.
nsTArray<GLuint> mTextures;

View File

@ -2063,6 +2063,7 @@ static bool sPrefLayersAccelerationForceEnabled = false;
static bool sPrefLayersAccelerationDisabled = false;
static bool sPrefLayersPreferOpenGL = false;
static bool sPrefLayersPreferD3D9 = false;
static bool sPrefLayersDrawFPS = false;
static bool sPrefLayersDump = false;
static bool sPrefLayersScrollGraph = false;
static bool sPrefLayersEnableTiles = false;
@ -2093,6 +2094,7 @@ InitLayersAccelerationPrefs()
sPrefLayersAccelerationDisabled = Preferences::GetBool("layers.acceleration.disabled", false);
sPrefLayersPreferOpenGL = Preferences::GetBool("layers.prefer-opengl", false);
sPrefLayersPreferD3D9 = Preferences::GetBool("layers.prefer-d3d9", false);
sPrefLayersDrawFPS = Preferences::GetBool("layers.acceleration.draw-fps", false);
sPrefLayersDump = Preferences::GetBool("layers.dump", false);
sPrefLayersScrollGraph = Preferences::GetBool("layers.scroll-graph", false);
sPrefLayersEnableTiles = Preferences::GetBool("layers.enable-tiles", false);
@ -2178,6 +2180,13 @@ gfxPlatform::GetPrefLayersPreferD3D9()
return sPrefLayersPreferD3D9;
}
bool
gfxPlatform::GetPrefLayersDrawFPS()
{
InitLayersAccelerationPrefs();
return sPrefLayersDrawFPS;
}
bool
gfxPlatform::CanUseDirect3D9()
{

View File

@ -513,6 +513,7 @@ public:
static bool GetPrefLayersDump();
static bool GetPrefLayersScrollGraph();
static bool GetPrefLayersEnableTiles();
static bool GetPrefLayersDrawFPS();
static bool OffMainThreadCompositionRequired();