Bug 780342 - Don't allow compositor-driven animation of frames that are not prerendered, provide diagnostics for when that happens r=cjones

This commit is contained in:
David Zbarsky 2012-08-06 16:33:23 -04:00
Родитель a2ebf3852f
Коммит a66260e4cc
5 изменённых файлов: 51 добавлений и 18 удалений

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

@ -326,12 +326,13 @@ AddAnimationsForProperty(nsIFrame* aFrame, nsCSSProperty aProperty,
}
static void
AddAnimationsAndTransitionsToLayer(Layer* aLayer, nsDisplayItem* aItem,
nsCSSProperty aProperty)
AddAnimationsAndTransitionsToLayer(Layer* aLayer, nsDisplayListBuilder* aBuilder,
nsDisplayItem* aItem, nsCSSProperty aProperty)
{
aLayer->ClearAnimations();
nsIFrame* frame = aItem->GetUnderlyingFrame();
nsIContent* aContent = frame->GetContent();
ElementTransitions* et =
nsTransitionManager::GetTransitionsForCompositor(aContent, aProperty);
@ -343,6 +344,23 @@ AddAnimationsAndTransitionsToLayer(Layer* aLayer, nsDisplayItem* aItem,
return;
}
// If the frame is not prerendered, bail out. Layout will still perform the
// animation.
if (!nsDisplayTransform::ShouldPrerenderTransformedContent(aBuilder, frame)) {
if (nsLayoutUtils::IsAnimationLoggingEnabled()) {
nsIContent* aContent = frame->GetContent();
printf_stderr("Performance warning: Async animation disabled because the frame for element '%s'",
nsAtomCString(aContent->Tag()).get());
nsIAtom* id = aContent->GetID();
if (id) {
printf_stderr(" with id '%s'",
nsAtomCString(aContent->GetID()).get());
}
printf_stderr(" is not prerendered\n");
}
return;
}
mozilla::TimeStamp currentTime =
frame->PresContext()->RefreshDriver()->MostRecentRefresh();
AnimationData data;
@ -2352,7 +2370,8 @@ nsDisplayOpacity::BuildLayer(nsDisplayListBuilder* aBuilder,
return nullptr;
container->SetOpacity(mFrame->GetStyleDisplay()->mOpacity);
AddAnimationsAndTransitionsToLayer(container, this, eCSSProperty_opacity);
AddAnimationsAndTransitionsToLayer(container, aBuilder,
this, eCSSProperty_opacity);
return container.forget();
}
@ -3364,7 +3383,8 @@ already_AddRefed<Layer> nsDisplayTransform::BuildLayer(nsDisplayListBuilder *aBu
container->SetContentFlags(container->GetContentFlags() | Layer::CONTENT_PRESERVE_3D);
}
AddAnimationsAndTransitionsToLayer(container, this, eCSSProperty_transform);
AddAnimationsAndTransitionsToLayer(container, aBuilder,
this, eCSSProperty_transform);
return container.forget();
}

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

@ -188,6 +188,21 @@ nsLayoutUtils::AreTransformAnimationsEnabled()
return sAreTransformAnimationsEnabled && CompositorParent::CompositorLoop();
}
bool
nsLayoutUtils::IsAnimationLoggingEnabled()
{
static bool sShouldLog;
static bool sShouldLogPrefCached;
if (!sShouldLogPrefCached) {
sShouldLogPrefCached = true;
Preferences::AddBoolVarCache(&sShouldLog,
"layers.offmainthreadcomposition.log-animations");
}
return sShouldLog;
}
bool
nsLayoutUtils::UseBackgroundNearestFiltering()
{

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

@ -1515,6 +1515,11 @@ public:
static bool AreOpacityAnimationsEnabled();
static bool AreTransformAnimationsEnabled();
/**
* Checks if we should warn about animations that can't be async
*/
static bool IsAnimationLoggingEnabled();
/**
* Checks if we should forcibly use nearest pixel filtering for the
* background.

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

@ -220,22 +220,14 @@ bool
CommonElementAnimationData::CanAnimatePropertyOnCompositor(const dom::Element *aElement,
nsCSSProperty aProperty)
{
static bool sShouldLog;
static bool sShouldLogPrefCached;
if (!sShouldLogPrefCached) {
sShouldLogPrefCached = true;
Preferences::AddBoolVarCache(&sShouldLog,
"layers.offmainthreadcomposition.log-animations");
}
bool shouldLog = nsLayoutUtils::IsAnimationLoggingEnabled();
nsIFrame* frame = aElement->GetPrimaryFrame();
if (aProperty == eCSSProperty_visibility) {
return true;
}
if (aProperty == eCSSProperty_opacity) {
bool enabled = nsLayoutUtils::AreOpacityAnimationsEnabled();
if (!enabled && sShouldLog) {
if (!enabled && shouldLog) {
printf_stderr("Performance warning: Async animation of 'opacity' is disabled\n");
}
return enabled;
@ -244,24 +236,24 @@ CommonElementAnimationData::CanAnimatePropertyOnCompositor(const dom::Element *a
if (frame &&
frame->Preserves3D() &&
frame->Preserves3DChildren()) {
if (sShouldLog) {
if (shouldLog) {
printf_stderr("Gecko bug: Async animation of 'preserve-3d' transforms is not supported. See bug 779598\n");
}
return false;
}
if (frame && frame->IsSVGTransformed()) {
if (sShouldLog) {
if (shouldLog) {
printf_stderr("Gecko bug: Async 'transform' animations of frames with SVG transforms is not supported. See bug 779599\n");
}
return false;
}
bool enabled = nsLayoutUtils::AreTransformAnimationsEnabled();
if (!enabled && sShouldLog) {
if (!enabled && shouldLog) {
printf_stderr("Performance warning: Async animation of 'transform' is disabled\n");
}
return enabled;
}
if (sShouldLog) {
if (shouldLog) {
const nsAFlatCString propName = nsCSSProps::GetStringValue(aProperty);
printf_stderr("Performance warning: Async animation cancelled because of unsupported property '%s'\n", propName.get());
}

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

@ -3522,6 +3522,7 @@ pref("layers.acceleration.draw-fps", false);
// Whether to animate simple opacity and transforms on the compositor
pref("layers.offmainthreadcomposition.animate-opacity", false);
pref("layers.offmainthreadcomposition.animate-transform", false);
pref("layers.offmainthreadcomposition.log-animations", false);
#ifdef MOZ_X11
#ifdef MOZ_WIDGET_GTK2