Bug 830347 - Part 3: Integrate new D3D compositor into widget. r=jmathies
authorBas Schouten <bschouten@mozilla.com>
Fri, 03 May 2013 19:34:33 +0200
changeset 138167 d5a2a23786f57b09c707e17ef29dcca9410d194e
parent 138166 b1a8d467615f2007f6b3faf80a1791b6efc47398
child 138168 5a1d7931af7b25cc3244e5929e9d8631fefef396
push id3752
push userlsblakk@mozilla.com
push dateMon, 13 May 2013 17:21:10 +0000
treeherdermozilla-aurora@1580544aef0b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjmathies
bugs830347
milestone23.0a1
Bug 830347 - Part 3: Integrate new D3D compositor into widget. r=jmathies
widget/windows/nsWindow.cpp
widget/windows/nsWindow.h
widget/windows/nsWindowGfx.cpp
widget/xpwidgets/nsBaseWidget.cpp
widget/xpwidgets/nsBaseWidget.h
--- a/widget/windows/nsWindow.cpp
+++ b/widget/windows/nsWindow.cpp
@@ -3197,23 +3197,16 @@ GetLayerManagerPrefs(LayerManagerPrefs* 
   bool safeMode = false;
   nsCOMPtr<nsIXULRuntime> xr = do_GetService("@mozilla.org/xre/runtime;1");
   if (xr)
     xr->GetInSafeMode(&safeMode);
   aManagerPrefs->mDisableAcceleration =
     aManagerPrefs->mDisableAcceleration || safeMode;
 }
 
-bool
-nsWindow::ShouldUseOffMainThreadCompositing()
-{
-  // OMTC doesn't work on Windows right now.
-  return false;
-}
-
 LayerManager*
 nsWindow::GetLayerManager(PLayerTransactionChild* aShadowManager,
                           LayersBackend aBackendHint,
                           LayerManagerPersistence aPersistence,
                           bool* aAllowRetaining)
 {
   if (aAllowRetaining) {
     *aAllowRetaining = true;
@@ -3235,19 +3228,28 @@ nsWindow::GetLayerManager(PLayerTransact
       }
     }
   }
 #endif
 
   RECT windowRect;
   ::GetClientRect(mWnd, &windowRect);
 
+  // Try OMTC first.
+  if (!mLayerManager && ShouldUseOffMainThreadCompositing()) {
+    // e10s uses the parameter to pass in the shadow manager from the TabChild
+    // so we don't expect to see it there since this doesn't support e10s.
+    NS_ASSERTION(aShadowManager == nullptr, "Async Compositor not supported with e10s");
+    CreateCompositor();
+  }
+
   if (!mLayerManager ||
       (!sAllowD3D9 && aPersistence == LAYER_MANAGER_PERSISTENT &&
-        mLayerManager->GetBackendType() == LAYERS_BASIC)) {
+        mLayerManager->GetBackendType() == LAYERS_BASIC &&
+        !ShouldUseOffMainThreadCompositing())) {
     // If D3D9 is not currently allowed but the permanent manager is required,
     // -and- we're currently using basic layers, run through this check.
     LayerManagerPrefs prefs;
     GetLayerManagerPrefs(&prefs);
 
     /* We don't currently support using an accelerated layer manager with
      * transparent windows so don't even try. I'm also not sure if we even
      * want to support this case. See bug #593471 */
@@ -7264,26 +7266,26 @@ bool nsWindow::OnHotKey(WPARAM wParam, L
 bool nsWindow::AutoErase(HDC dc)
 {
   return false;
 }
 
 void
 nsWindow::AllowD3D9Callback(nsWindow *aWindow)
 {
-  if (aWindow->mLayerManager) {
+  if (aWindow->mLayerManager && !aWindow->ShouldUseOffMainThreadCompositing()) {
     aWindow->mLayerManager->Destroy();
     aWindow->mLayerManager = NULL;
   }
 }
 
 void
 nsWindow::AllowD3D9WithReinitializeCallback(nsWindow *aWindow)
 {
-  if (aWindow->mLayerManager) {
+  if (aWindow->mLayerManager && !aWindow->ShouldUseOffMainThreadCompositing()) {
     aWindow->mLayerManager->Destroy();
     aWindow->mLayerManager = NULL;
     (void) aWindow->GetLayerManager();
   }
 }
 
 void
 nsWindow::StartAllowingD3D9(bool aReinitialize)
@@ -7293,17 +7295,19 @@ nsWindow::StartAllowingD3D9(bool aReinit
   LayerManagerPrefs prefs;
   GetLayerManagerPrefs(&prefs);
   if (prefs.mDisableAcceleration) {
     // The guarantee here is, if there's *any* chance that after we
     // throw out our layer managers we'd create at least one new,
     // accelerated one, we *will* throw out all the current layer
     // managers.  We early-return here because currently, if
     // |disableAcceleration|, we will always use basic managers and
-    // it's a waste to recreate them.
+    // it's a waste to recreate them. If we're using OMTC we don't want to
+    // recreate out layer manager and its compositor either. This is even
+    // more wasteful.
     //
     // NB: the above implies that it's eminently possible for us to
     // skip this early return but still recreate basic managers.
     // That's OK.  It's *not* OK to take this early return when we
     // *might* have created an accelerated manager.
     return;
   }
 
--- a/widget/windows/nsWindow.h
+++ b/widget/windows/nsWindow.h
@@ -276,17 +276,18 @@ public:
   // Open file picker tracking
   void                    PickerOpen();
   void                    PickerClosed();
 
   bool                    const DestroyCalled() { return mDestroyCalled; }
 
   static void             SetupKeyModifiersSequence(nsTArray<KeyPair>* aArray, uint32_t aModifiers);
 
-  virtual bool            ShouldUseOffMainThreadCompositing();
+  virtual mozilla::layers::LayersBackend GetPreferredCompositorBackend() { return mozilla::layers::LAYERS_D3D11; }
+
 protected:
 
   // A magic number to identify the FAKETRACKPOINTSCROLLABLE window created
   // when the trackpoint hack is enabled.
   enum { eFakeTrackPointScrollableID = 0x46545053 };
 
   /**
    * Callbacks
--- a/widget/windows/nsWindowGfx.cpp
+++ b/widget/windows/nsWindowGfx.cpp
@@ -540,16 +540,20 @@ bool nsWindow::OnPaint(HDC aDC, uint32_t
           if (layerManagerD3D10->device() != gfxWindowsPlatform::GetPlatform()->GetD3D10Device()) {
             Invalidate();
           } else {
             result = listener->PaintWindow(this, region, 0);
           }
         }
         break;
 #endif
+      case LAYERS_CLIENT:
+        // Do nothing, the compositor will handle drawing.
+        break;
+
       default:
         NS_ERROR("Unknown layers backend used!");
         break;
     }
   }
 
   if (!aDC) {
     ::EndPaint(mWnd, &ps);
--- a/widget/xpwidgets/nsBaseWidget.cpp
+++ b/widget/xpwidgets/nsBaseWidget.cpp
@@ -872,52 +872,53 @@ void nsBaseWidget::CreateCompositor()
 {
   nsIntRect rect;
   GetBounds(rect);
   CreateCompositor(rect.width, rect.height);
 }
 
 void nsBaseWidget::CreateCompositor(int aWidth, int aHeight)
 {
+  // Recreating this is tricky, as we may still have an old and we need
+  // to make sure it's properly destroyed by calling DestroyCompositor!
+
   mCompositorParent = NewCompositorParent(aWidth, aHeight);
   AsyncChannel *parentChannel = mCompositorParent->GetIPCChannel();
   LayerManager* lm = new ClientLayerManager(this);
   MessageLoop *childMessageLoop = CompositorParent::CompositorLoop();
   mCompositorChild = new CompositorChild(lm);
   AsyncChannel::Side childSide = mozilla::ipc::AsyncChannel::Child;
   mCompositorChild->Open(parentChannel, childMessageLoop, childSide);
 
   TextureFactoryIdentifier textureFactoryIdentifier;
   PLayerTransactionChild* shadowManager;
-  mozilla::layers::LayersBackend backendHint;
-  if (mUseLayersAcceleration) {
-    backendHint = mozilla::layers::LAYERS_OPENGL;
-  } else {
-    backendHint = mozilla::layers::LAYERS_BASIC;
-  }
+  mozilla::layers::LayersBackend backendHint = GetPreferredCompositorBackend();
+
   shadowManager = mCompositorChild->SendPLayerTransactionConstructor(
     backendHint, 0, &textureFactoryIdentifier);
 
   if (shadowManager) {
     ShadowLayerForwarder* lf = lm->AsShadowForwarder();
     if (!lf) {
       delete lm;
       mCompositorChild = nullptr;
       return;
     }
     lf->SetShadowManager(shadowManager);
     lf->IdentifyTextureHost(textureFactoryIdentifier);
 
     mLayerManager = lm;
-  } else {
-    // We don't currently want to support not having a LayersChild
-    NS_RUNTIMEABORT("failed to construct LayersChild");
-    delete lm;
-    mCompositorChild = nullptr;
+    return;
   }
+
+  // Failed to create a compositor!
+  NS_WARNING("Failed to create an OMT compositor.");
+  DestroyCompositor();
+  // Compositor child had the only reference to LayerManager and will have
+  // deallocated it when being freed.
 }
 
 bool nsBaseWidget::ShouldUseOffMainThreadCompositing()
 {
   bool isSmallPopup = ((mWindowType == eWindowType_popup) &&
                       (mPopupType != ePopupTypePanel)) || (mWindowType == eWindowType_invisible);
   return CompositorParent::CompositorLoop() && !isSmallPopup;
 }
--- a/widget/xpwidgets/nsBaseWidget.h
+++ b/widget/xpwidgets/nsBaseWidget.h
@@ -331,16 +331,19 @@ protected:
     *aWidth = std::max(mSizeConstraints.mMinSize.width,
                      std::min(mSizeConstraints.mMaxSize.width, *aWidth));
     *aHeight = std::max(mSizeConstraints.mMinSize.height,
                       std::min(mSizeConstraints.mMaxSize.height, *aHeight));
   }
 
   virtual CompositorChild* GetRemoteRenderer() MOZ_OVERRIDE;
 
+  virtual mozilla::layers::LayersBackend GetPreferredCompositorBackend()
+  { return mUseLayersAcceleration ? mozilla::layers::LAYERS_OPENGL : mozilla::layers::LAYERS_BASIC; }
+
 protected:
   /**
    * Starts the OMTC compositor destruction sequence.
    *
    * When this function returns, the compositor should not be 
    * able to access the opengl context anymore.
    * It is safe to call it several times if platform implementations
    * require the compositor to be destroyed before ~nsBaseWidget is