Bug 580531 - Record first paint time and number of images painted in ImageContainer. r=roc

This commit is contained in:
Chris Pearce 2011-03-24 11:28:57 +13:00
Родитель fd6cce5849
Коммит f507197104
6 изменённых файлов: 93 добавлений и 3 удалений

Просмотреть файл

@ -44,6 +44,7 @@
#include "nsThreadUtils.h"
#include "nsCoreAnimationSupport.h"
#include "mozilla/Monitor.h"
#include "mozilla/TimeStamp.h"
namespace mozilla {
namespace layers {
@ -132,7 +133,12 @@ class THEBES_API ImageContainer {
THEBES_INLINE_DECL_THREADSAFE_REFCOUNTING(ImageContainer)
public:
ImageContainer() : mMonitor("ImageContainer") {}
ImageContainer() :
mMonitor("ImageContainer"),
mPaintCount(0),
mPreviousImagePainted(PR_FALSE)
{}
virtual ~ImageContainer() {}
/**
@ -163,6 +169,8 @@ public:
* a reference.
* Can be called on any thread. This method takes mMonitor when accessing
* thread-shared state.
* Implementations must call CurrentImageChanged() while holding mMonitor.
*
*/
virtual already_AddRefed<Image> GetCurrentImage() = 0;
@ -224,6 +232,48 @@ public:
*/
virtual LayerManager::LayersBackend GetBackendType() = 0;
/**
* Returns the time at which the currently contained image was first
* painted. This is reset every time a new image is set as the current
* image. Note this may return a null timestamp if the current image
* has not yet been painted. Can be called from any thread.
*/
TimeStamp GetPaintTime() {
MonitorAutoEnter mon(mMonitor);
return mPaintTime;
}
/**
* Returns the number of images which have been contained in this container
* and painted at least once. Can be called from any thread.
*/
PRUint32 GetPaintCount() {
MonitorAutoEnter mon(mMonitor);
return mPaintCount;
}
/**
* Increments mPaintCount if this is the first time aPainted has been
* painted, and sets mPaintTime if the painted image is the current image.
* current image. Can be called from any thread.
*/
void NotifyPaintedImage(Image* aPainted) {
MonitorAutoEnter mon(mMonitor);
nsRefPtr<Image> current = GetCurrentImage();
if (aPainted == current) {
if (mPaintTime.IsNull()) {
mPaintTime = TimeStamp::Now();
mPaintCount++;
}
} else if (!mPreviousImagePainted) {
// While we were painting this image, the current image changed. We
// still must count it as painted, but can't set mPaintTime, since we're
// no longer the current image.
mPaintCount++;
mPreviousImagePainted = PR_TRUE;
}
}
protected:
typedef mozilla::Monitor Monitor;
LayerManager* mManager;
@ -232,7 +282,33 @@ protected:
// other state which is shared between threads.
Monitor mMonitor;
ImageContainer(LayerManager* aManager) : mManager(aManager), mMonitor("ImageContainer") {}
ImageContainer(LayerManager* aManager) :
mManager(aManager),
mMonitor("ImageContainer"),
mPaintCount(0),
mPreviousImagePainted(PR_FALSE)
{}
// Performs necessary housekeeping to ensure the painted frame statistics
// are accurate. Must be called by SetCurrentImage() implementations with
// mMonitor held.
void CurrentImageChanged() {
mMonitor.AssertCurrentThreadIn();
mPreviousImagePainted = !mPaintTime.IsNull();
mPaintTime = TimeStamp();
}
// Number of contained images that have been painted at least once. It's up
// to the ImageContainer implementation to ensure accesses to this are
// threadsafe.
PRUint32 mPaintCount;
// Time stamp at which the current image was first painted. It's up to the
// ImageContainer implementation to ensure accesses to this are threadsafe.
TimeStamp mPaintTime;
// Denotes whether the previous image was painted.
PRPackedBool mPreviousImagePainted;
};
/**

Просмотреть файл

@ -350,6 +350,7 @@ BasicImageContainer::SetCurrentImage(Image* aImage)
{
MonitorAutoEnter mon(mMonitor);
mImage = aImage;
CurrentImageChanged();
}
already_AddRefed<Image>

Просмотреть файл

@ -750,6 +750,8 @@ BasicImageLayer::GetAndPaintCurrentImage(gfxContext* aContext,
if (!mContainer)
return nsnull;
nsRefPtr<Image> image = mContainer->GetCurrentImage();
nsRefPtr<gfxASurface> surface = mContainer->GetCurrentAsSurface(&mSize);
if (!surface) {
return nsnull;
@ -770,6 +772,9 @@ BasicImageLayer::GetAndPaintCurrentImage(gfxContext* aContext,
tileSrcRect ? GetVisibleRegion() : nsIntRegion(nsIntRect(0, 0, mSize.width, mSize.height)),
tileSrcRect,
aOpacity, aContext);
GetContainer()->NotifyPaintedImage(image);
return pat.forget();
}

Просмотреть файл

@ -124,6 +124,7 @@ ImageContainerD3D10::SetCurrentImage(Image *aImage)
MonitorAutoEnter mon(mMonitor);
mActiveImage = aImage;
CurrentImageChanged();
}
already_AddRefed<Image>
@ -351,6 +352,8 @@ ImageLayerD3D10::RenderLayer()
technique->GetPassByIndex(0)->Apply(0);
device()->Draw(4, 0);
GetContainer()->NotifyPaintedImage(image);
}
PlanarYCbCrImageD3D10::PlanarYCbCrImageD3D10(ID3D10Device1 *aDevice)

Просмотреть файл

@ -159,6 +159,7 @@ ImageContainerD3D9::SetCurrentImage(Image *aImage)
MonitorAutoEnter mon(mMonitor);
mActiveImage = aImage;
CurrentImageChanged();
}
already_AddRefed<Image>
@ -372,6 +373,8 @@ ImageLayerD3D9::RenderLayer()
device()->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
}
}
GetContainer()->NotifyPaintedImage(image);
}
PlanarYCbCrImageD3D9::PlanarYCbCrImageD3D9()

Просмотреть файл

@ -235,6 +235,7 @@ ImageContainerOGL::SetCurrentImage(Image *aImage)
oldImage = mActiveImage.forget();
mActiveImage = aImage;
CurrentImageChanged();
}
// Make sure oldImage is released outside the lock, so it can take our
@ -499,6 +500,7 @@ ImageLayerOGL::RenderLayer(int,
gl()->fBindTexture(LOCAL_GL_TEXTURE_RECTANGLE_ARB, 0);
#endif
}
GetContainer()->NotifyPaintedImage(image);
}
static void