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 142101 6f52629c9d085c42878ad6ffce414df1b35957e2
parent 142100 478c8b6a97364acfa1f03ea4d001efbbe5099d74
child 142102 f2ac70bee1e0447a2764551040cbdd476580829d
child 142240 24d361942d24229dd9fdebbe2f5cdb2fcb908881
push id2579
push userakeybl@mozilla.com
push dateMon, 24 Jun 2013 18:52:47 +0000
treeherdermozilla-beta@b69b7de8a05a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjmathies
bugs830347
milestone23.0a1
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 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