Bug 626962. Part 0: Don't do empty transactions when painting to a widget's non-retaining layer manager. r=tnikkel,a=blocker
authorRobert O'Callahan <robert@ocallahan.org>
Thu, 03 Feb 2011 21:45:23 +1300
changeset 61835 b4e9a17e7fe2f98f46c528af4ead056527e1d7b7
parent 61834 e1d2e090c9a6aa796f2bc4aff97a8e497ee81d4d
child 61836 2a13f323dfa05b3a249110a06e0ff219c795c982
push id18515
push userrocallahan@mozilla.com
push dateThu, 03 Feb 2011 08:59:03 +0000
treeherdermozilla-central@274e546e9da9 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstnikkel, blocker
bugs626962
milestone2.0b12pre
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 626962. Part 0: Don't do empty transactions when painting to a widget's non-retaining layer manager. r=tnikkel,a=blocker
layout/base/nsLayoutUtils.cpp
layout/base/nsPresShell.cpp
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -1382,17 +1382,17 @@ nsLayoutUtils::PaintFrame(nsIRenderingCo
 		                       !(aFlags & PAINT_HIDE_CARET));
   nsDisplayList list;
   if (aFlags & PAINT_IN_TRANSFORM) {
     builder.SetInTransform(PR_TRUE);
   }
   if (aFlags & PAINT_SYNC_DECODE_IMAGES) {
     builder.SetSyncDecodeImages(PR_TRUE);
   }
-  if (aFlags & PAINT_WIDGET_LAYERS || aFlags & PAINT_TO_WINDOW) {
+  if (aFlags & (PAINT_WIDGET_LAYERS | PAINT_TO_WINDOW)) {
     builder.SetPaintingToWindow(PR_TRUE);
   }
   if (aFlags & PAINT_IGNORE_SUPPRESSION) {
     builder.IgnorePaintSuppression();
   }
   if (aRenderingContext &&
       aRenderingContext->ThebesContext()->GetFlags() & gfxContext::FLAG_DISABLE_SNAPPING) {
     builder.SetSnappingEnabled(PR_FALSE);
--- a/layout/base/nsPresShell.cpp
+++ b/layout/base/nsPresShell.cpp
@@ -6133,32 +6133,43 @@ PresShell::Paint(nsIView*           aDis
   NS_ASSERTION(aWidgetToPaint, "Can't paint without a widget");
 
   nsPresContext* presContext = GetPresContext();
   AUTO_LAYOUT_PHASE_ENTRY_POINT(presContext, Paint);
 
   nsIFrame* frame = aPaintDefaultBackground
       ? nsnull : static_cast<nsIFrame*>(aDisplayRoot->GetClientData());
 
-  LayerManager* layerManager = aWidgetToPaint->GetLayerManager();
+  bool isRetainingManager;
+  LayerManager* layerManager =
+    aWidgetToPaint->GetLayerManager(&isRetainingManager);
   NS_ASSERTION(layerManager, "Must be in paint event");
   layerManager->BeginTransaction();
 
-  if (frame) {
+  if (frame && isRetainingManager) {
+    // Try to do an empty transaction, if the frame tree does not
+    // need to be updated. Do not try to do an empty transaction on
+    // a non-retained layer manager (like the BasicLayerManager that
+    // draws the window title bar on Mac), because a) it won't work
+    // and b) below we don't want to clear NS_FRAME_UPDATE_LAYER_TREE,
+    // that will cause us to forget to update the real layer manager!
     if (!(frame->GetStateBits() & NS_FRAME_UPDATE_LAYER_TREE)) {
       if (layerManager->EndEmptyTransaction()) {
         frame->UpdatePaintCountForPaintedPresShells();
         presContext->NotifyDidPaintForSubtree();
         
         return NS_OK;
       }
     }
     
+
+    frame->RemoveStateBits(NS_FRAME_UPDATE_LAYER_TREE);
+  }
+  if (frame) {
     frame->ClearPresShellsFromLastPaint();
-    frame->RemoveStateBits(NS_FRAME_UPDATE_LAYER_TREE);
   }
 
   nscolor bgcolor = ComputeBackstopColor(aDisplayRoot);
 
   if (frame && aViewToPaint == aDisplayRoot) {
     // Defer invalidates that are triggered during painting, and discard
     // invalidates of areas that are already being repainted.
     // The layer system can trigger invalidates during painting