зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
e447b2c7d7
Коммит
e5ff8517e3
|
@ -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
|
||||
*/
|
||||
|
|
Загрузка…
Ссылка в новой задаче