Bug 564991. Part 25: Introduce a 'has active layers' flag on frames, which times out, and use it for 'opacity'. r=mats,sr=dbaron

This commit is contained in:
Robert O'Callahan 2010-07-16 09:08:06 +12:00
Родитель e447b2c7d7
Коммит e5ff8517e3
6 изменённых файлов: 103 добавлений и 1 удалений

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

@ -120,6 +120,7 @@
#include "nsTArray.h"
#include "nsGenericDOMDataNode.h"
#include "mozilla/dom/Element.h"
#include "FrameLayerBuilder.h"
#ifdef MOZ_XUL
#include "nsIRootBox.h"
@ -7671,6 +7672,7 @@ DoApplyRenderingChangeToTree(nsIFrame* aFrame,
}
}
if (aChange & nsChangeHint_UpdateOpacityLayer) {
aFrame->MarkLayersActive();
aFrame->InvalidateLayer(aFrame->GetOverflowRectRelativeToSelf(),
nsDisplayItem::TYPE_OPACITY);
}

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

@ -1137,7 +1137,8 @@ nsDisplayOpacity::BuildLayer(nsDisplayListBuilder* aBuilder,
nsDisplayItem::LayerState
nsDisplayOpacity::GetLayerState(nsDisplayListBuilder* aBuilder,
LayerManager* aManager) {
// XXX fix this to detect animated opacity
if (mFrame->AreLayersMarkedActive())
return LAYER_ACTIVE;
nsIFrame* activeScrolledRoot =
nsLayoutUtils::GetActiveScrolledRootFor(mFrame, nsnull, nsnull);
return !ChildrenCanBeInactive(aBuilder, aManager, mList, activeScrolledRoot)

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

@ -316,6 +316,7 @@ nsLayoutStatics::Shutdown()
nsFrame::DisplayReflowShutdown();
#endif
nsCellMap::Shutdown();
nsFrame::ShutdownLayerActivityTimer();
#ifdef MOZ_SVG
nsSVGUtils::Shutdown();

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

@ -121,6 +121,7 @@
#include "nsBlockFrame.h"
#include "nsDisplayList.h"
#include "nsIObjectLoadingContent.h"
#include "nsExpirationTracker.h"
#ifdef MOZ_SVG
#include "nsSVGIntegrationUtils.h"
#include "nsSVGEffects.h"
@ -3692,6 +3693,88 @@ nsIFrame::InvalidateLayer(const nsRect& aDamageRect, PRUint32 aDisplayItemKey)
InvalidateWithFlags(aDamageRect, INVALIDATE_NO_THEBES_LAYERS);
}
class LayerActivity {
public:
LayerActivity(nsIFrame* aFrame) : mFrame(aFrame) {}
~LayerActivity();
nsExpirationState* GetExpirationState() { return &mState; }
nsIFrame* mFrame;
nsExpirationState mState;
};
class LayerActivityTracker : public nsExpirationTracker<LayerActivity,4> {
public:
// 75-100ms is a good timeout period. We use 4 generations of 25ms each.
enum { GENERATION_MS = 100 };
LayerActivityTracker()
: nsExpirationTracker<LayerActivity,4>(GENERATION_MS) {}
~LayerActivityTracker() {
AgeAllGenerations();
}
virtual void NotifyExpired(LayerActivity* aObject);
};
static LayerActivityTracker* gLayerActivityTracker = nsnull;
LayerActivity::~LayerActivity()
{
if (mFrame) {
NS_ASSERTION(gLayerActivityTracker, "Should still have a tracker");
gLayerActivityTracker->RemoveObject(this);
}
}
static void DestroyLayerActivity(void* aPropertyValue)
{
delete static_cast<LayerActivity*>(aPropertyValue);
}
NS_DECLARE_FRAME_PROPERTY(LayerActivityProperty, DestroyLayerActivity)
void
LayerActivityTracker::NotifyExpired(LayerActivity* aObject)
{
RemoveObject(aObject);
nsIFrame* f = aObject->mFrame;
aObject->mFrame = nsnull;
f->Properties().Delete(LayerActivityProperty());
f->InvalidateOverflowRect();
}
void
nsIFrame::MarkLayersActive()
{
FrameProperties properties = Properties();
LayerActivity* layerActivity =
static_cast<LayerActivity*>(properties.Get(LayerActivityProperty()));
if (layerActivity) {
gLayerActivityTracker->MarkUsed(layerActivity);
} else {
if (!gLayerActivityTracker) {
gLayerActivityTracker = new LayerActivityTracker();
}
layerActivity = new LayerActivity(this);
gLayerActivityTracker->AddObject(layerActivity);
properties.Set(LayerActivityProperty(), layerActivity);
}
}
PRBool
nsIFrame::AreLayersMarkedActive()
{
return Properties().Get(LayerActivityProperty()) != nsnull;
}
/* static */ void
nsFrame::ShutdownLayerActivityTimer()
{
delete gLayerActivityTracker;
gLayerActivityTracker = nsnull;
}
void
nsIFrame::InvalidateWithFlags(const nsRect& aDamageRect, PRUint32 aFlags)
{

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

@ -488,6 +488,8 @@ public:
static void DisplayReflowShutdown();
#endif
static void ShutdownLayerActivityTimer();
/**
* Adds display item for standard CSS background if necessary.
* Does not check IsVisibleForPainting.

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

@ -1817,6 +1817,19 @@ public:
*/
void EndDeferringInvalidatesForDisplayRoot();
/**
* Mark this frame as using active layers. This marking will time out
* after a short period. This call does no immediate invalidation,
* but when the mark times out, we'll invalidate the frame's overflow
* area.
*/
void MarkLayersActive();
/**
* Return true if this frame is marked as needing active layers.
*/
PRBool AreLayersMarkedActive();
/**
* @param aFlags see InvalidateInternal below
*/