Bug 1549976 - Implement popover render root r=kats,Gijs
authorDoug Thayer <dothayer@mozilla.com>
Fri, 21 Jun 2019 19:15:11 +0100
changeset 543495 5a18f5c929ab13bde25f7fff8ae72f87e8fa379c
parent 543494 6c6b0bbf5885493a0b85cedf1985d6eb3bdbfe6f
child 543496 58831b7309def9465e932ff8a10200faeed2b1d7
push id2131
push userffxbld-merge
push dateMon, 26 Aug 2019 18:30:20 +0000
treeherdermozilla-release@b19ffb3ca153 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskats, Gijs
bugs1549976
milestone69.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 1549976 - Implement popover render root r=kats,Gijs If we decide to just go with an overlay that sits fully over the window (which I don't personally see a perf problem with right now, but correct me if you can think of one), then this should be all we need. Differential Revision: https://phabricator.services.mozilla.com//D33819
browser/base/content/browser.css
browser/base/content/browser.xhtml
browser/base/content/popovers.inc
gfx/layers/ipc/CompositorBridgeParent.cpp
gfx/thebes/gfxUtils.cpp
gfx/webrender_bindings/WebRenderTypes.h
layout/painting/nsDisplayList.cpp
layout/painting/nsDisplayList.h
--- a/browser/base/content/browser.css
+++ b/browser/base/content/browser.css
@@ -911,16 +911,24 @@ window[chromehidden~="toolbar"] toolbar:
 
 /*  Full Screen UI */
 
 #fullscr-toggler {
   height: 1px;
   background: black;
 }
 
+html|*#fullscreen-and-pointerlock-wrapper {
+  position: fixed;
+  width: 100vw;
+  height: 100vh;
+  top: 0;
+  pointer-events: none;
+}
+
 html|*.pointerlockfswarning {
   position: fixed;
   z-index: 2147483647 !important;
   visibility: visible;
   transition: transform 300ms ease-in;
   /* To center the warning box horizontally,
      we use left: 50% with translateX(-50%). */
   top: 0; left: 50%;
--- a/browser/base/content/browser.xhtml
+++ b/browser/base/content/browser.xhtml
@@ -1333,42 +1333,17 @@
     </vbox>
     <vbox id="browser-border-end" hidden="true" layer="true"/>
   </hbox>
 
   <box id="customization-container" flex="1" renderroot="content" hidden="true"><![CDATA[
 #include ../../components/customizableui/content/customizeMode.inc.xul
   ]]></box>
 
-  <html:div id="fullscreen-warning" class="pointerlockfswarning" hidden="true" renderroot="content">
-    <html:div class="pointerlockfswarning-domain-text">
-      &fullscreenWarning.beforeDomain.label;
-      <html:span class="pointerlockfswarning-domain"/>
-      &fullscreenWarning.afterDomain.label;
-    </html:div>
-    <html:div class="pointerlockfswarning-generic-text">
-      &fullscreenWarning.generic.label;
-    </html:div>
-    <html:button id="fullscreen-exit-button"
-                 onclick="FullScreen.exitDomFullScreen();">
-#ifdef XP_MACOSX
-            &exitDOMFullscreenMac.button;
-#else
-            &exitDOMFullscreen.button;
-#endif
-    </html:button>
-  </html:div>
-
-  <html:div id="pointerlock-warning" class="pointerlockfswarning" hidden="true" renderroot="content">
-    <html:div class="pointerlockfswarning-domain-text">
-      &pointerlockWarning.beforeDomain.label;
-      <html:span class="pointerlockfswarning-domain"/>
-      &pointerlockWarning.afterDomain.label;
-    </html:div>
-    <html:div class="pointerlockfswarning-generic-text">
-      &pointerlockWarning.generic.label;
-    </html:div>
-  </html:div>
+# Everything that needs to straddle the line between chrome and content, without being
+# its own widget-level window, needs to go in here, and set the renderroot="popover"
+# attribute, or it will fail to render properly in WebRender.
+#include popovers.inc
 
   <vbox id="browser-bottombox" layer="true" renderroot="content">
     <!-- gNotificationBox will be added here lazily. -->
   </vbox>
 </window>
new file mode 100644
--- /dev/null
+++ b/browser/base/content/popovers.inc
@@ -0,0 +1,34 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at https://mozilla.org/MPL/2.0/.
+<html:div id="fullscreen-and-pointerlock-wrapper" renderroot="popover">
+  <html:div id="fullscreen-warning" class="pointerlockfswarning" hidden="true">
+    <html:div class="pointerlockfswarning-domain-text">
+      &fullscreenWarning.beforeDomain.label;
+      <html:span class="pointerlockfswarning-domain"/>
+      &fullscreenWarning.afterDomain.label;
+    </html:div>
+    <html:div class="pointerlockfswarning-generic-text">
+      &fullscreenWarning.generic.label;
+    </html:div>
+    <html:button id="fullscreen-exit-button"
+                 onclick="FullScreen.exitDomFullScreen();">
+#ifdef XP_MACOSX
+            &exitDOMFullscreenMac.button;
+#else
+            &exitDOMFullscreen.button;
+#endif
+    </html:button>
+  </html:div>
+
+  <html:div id="pointerlock-warning" class="pointerlockfswarning" hidden="true">
+    <html:div class="pointerlockfswarning-domain-text">
+      &pointerlockWarning.beforeDomain.label;
+      <html:span class="pointerlockfswarning-domain"/>
+      &pointerlockWarning.afterDomain.label;
+    </html:div>
+    <html:div class="pointerlockfswarning-generic-text">
+      &pointerlockWarning.generic.label;
+    </html:div>
+  </html:div>
+</html:div>
--- a/gfx/layers/ipc/CompositorBridgeParent.cpp
+++ b/gfx/layers/ipc/CompositorBridgeParent.cpp
@@ -1791,16 +1791,18 @@ PWebRenderBridgeParent* CompositorBridge
     mWrBridge = WebRenderBridgeParent::CreateDestroyed(aPipelineId);
     mWrBridge.get()->AddRef();  // IPDL reference
     return mWrBridge;
   }
 
   if (StaticPrefs::gfx_webrender_split_render_roots()) {
     apis.AppendElement(
         apis[0]->CreateDocument(aSize, 1, wr::RenderRoot::Content));
+    apis.AppendElement(
+        apis[0]->CreateDocument(aSize, 2, wr::RenderRoot::Popover));
   }
 
   InfallibleTArray<RefPtr<wr::WebRenderAPI>> clonedApis;
   for (auto& api : apis) {
     wr::TransactionBuilder txn;
     txn.SetRootPipeline(aPipelineId);
     api->SendTransaction(txn);
     clonedApis.AppendElement(api->Clone());
--- a/gfx/thebes/gfxUtils.cpp
+++ b/gfx/thebes/gfxUtils.cpp
@@ -1494,23 +1494,24 @@ Maybe<wr::RenderRoot> gfxUtils::GetRende
     const dom::Element* aElement) {
   if (!aElement) {
     return Nothing();
   }
   if (!gfxVars::UseWebRender() ||
       !StaticPrefs::gfx_webrender_split_render_roots()) {
     return Nothing();
   }
-  if (!aElement->IsXULElement()) {
-    return Nothing();
-  }
   if (aElement->AttrValueIs(kNameSpaceID_None, nsGkAtoms::renderroot,
                             NS_LITERAL_STRING("content"), eCaseMatters)) {
     return Some(wr::RenderRoot::Content);
   }
+  if (aElement->AttrValueIs(kNameSpaceID_None, nsGkAtoms::renderroot,
+                            NS_LITERAL_STRING("popover"), eCaseMatters)) {
+    return Some(wr::RenderRoot::Popover);
+  }
   return Nothing();
 }
 
 wr::RenderRoot gfxUtils::RecursivelyGetRenderRootForFrame(
     const nsIFrame* aFrame) {
   if (!gfxVars::UseWebRender() ||
       !StaticPrefs::gfx_webrender_split_render_roots()) {
     return wr::RenderRoot::Default;
--- a/gfx/webrender_bindings/WebRenderTypes.h
+++ b/gfx/webrender_bindings/WebRenderTypes.h
@@ -72,26 +72,32 @@ MOZ_DEFINE_ENUM_CLASS_WITH_BASE(
         // RenderRoot::Content (or whatever value is appropriate)
         Default,
 
         // Everything below the chrome - even if it is not coming from a content
         // process. For example. the devtools, sidebars, and status panel are
         // traditionally part of the "chrome," but are assigned a renderroot of
         // RenderRoot::Content because they occupy screen space in the "content"
         // area of the browser (visually situated below the "chrome" area).
-        Content));
+        Content,
+
+        // Currently used for the pointerlock and fullscreen warnings. This is
+        // intended to overlay both the Content and Default render roots when
+        // we need a piece of UI that straddles their border.
+        Popover));
 
 typedef EnumSet<RenderRoot, uint8_t> RenderRootSet;
 
 // For simple iteration of all render roots
 const Array<RenderRoot, kRenderRootCount> kRenderRoots(RenderRoot::Default,
-                                                       RenderRoot::Content);
+                                                       RenderRoot::Content,
+                                                       RenderRoot::Popover);
 
 const Array<RenderRoot, kRenderRootCount - 1> kNonDefaultRenderRoots(
-    RenderRoot::Content);
+    RenderRoot::Content, RenderRoot::Popover);
 
 template <typename T>
 class RenderRootArray : public Array<T, kRenderRootCount> {
   typedef Array<T, kRenderRootCount> Super;
 
  public:
   RenderRootArray() {
     if (IsPod<T>::value) {
--- a/layout/painting/nsDisplayList.cpp
+++ b/layout/painting/nsDisplayList.cpp
@@ -3823,16 +3823,21 @@ bool nsDisplaySolidColor::CreateWebRende
     nsDisplayListBuilder* aDisplayListBuilder) {
   LayoutDeviceRect bounds = LayoutDeviceRect::FromAppUnits(
       mBounds, mFrame->PresContext()->AppUnitsPerDevPixel());
 
   // There is one big solid color behind everything - just split it out if it
   // intersects multiple render roots
   if (aBuilder.GetRenderRoot() == wr::RenderRoot::Default) {
     for (auto renderRoot : wr::kRenderRoots) {
+      // Skip the popover render root, as it's intended to overlay the others
+      // and be at least partially transparent.
+      if (renderRoot == wr::RenderRoot::Popover) {
+        continue;
+      }
       if (aBuilder.HasSubBuilder(renderRoot)) {
         LayoutDeviceRect renderRootRect =
             aDisplayListBuilder->GetRenderRootRect(renderRoot);
         wr::LayoutRect intersection =
             wr::ToRoundedLayoutRect(bounds.Intersect(renderRootRect));
         aBuilder.SubBuilder(renderRoot)
             .PushRect(intersection, intersection, !BackfaceIsHidden(),
                       wr::ToColorF(ToDeviceColor(mColor)));
@@ -7061,16 +7066,19 @@ bool nsDisplayRenderRoot::CreateWebRende
     }
     mBuiltWRCommands = true;
   }
   return true;
 }
 
 void nsDisplayRenderRoot::ExpandDisplayListBuilderRenderRootRect(
     nsDisplayListBuilder* aBuilder) {
+  if (mFrame->GetRect().IsEmpty()) {
+    return;
+  }
   mozilla::LayoutDeviceRect rect = mozilla::LayoutDeviceRect::FromAppUnits(
       mFrame->GetRectRelativeToSelf() + ToReferenceFrame(),
       mFrame->PresContext()->AppUnitsPerDevPixel());
   aBuilder->ExpandRenderRootRect(rect, mRenderRoot);
 }
 
 nsDisplaySubDocument::nsDisplaySubDocument(nsDisplayListBuilder* aBuilder,
                                            nsIFrame* aFrame,
--- a/layout/painting/nsDisplayList.h
+++ b/layout/painting/nsDisplayList.h
@@ -930,20 +930,18 @@ class nsDisplayListBuilder {
     return mNeedsDisplayListBuild[aRenderRoot];
   }
 
   void ComputeDefaultRenderRootRect(LayoutDeviceIntSize aClientSize) {
     nsRegion cutout;
     nsRect clientRect(nsPoint(),
                       mozilla::LayoutDevicePixel::ToAppUnits(aClientSize, 1));
     cutout.OrWith(clientRect);
-    for (auto renderRoot : mozilla::wr::kRenderRoots) {
-      cutout.SubWith(mozilla::LayoutDevicePixel::ToAppUnits(
-          mRenderRootRects[renderRoot], 1));
-    }
+    cutout.SubWith(mozilla::LayoutDevicePixel::ToAppUnits(
+        mRenderRootRects[mozilla::wr::RenderRoot::Content], 1));
 
     mRenderRootRects[mozilla::wr::RenderRoot::Default] =
         mozilla::LayoutDevicePixel::FromAppUnits(cutout.GetBounds(), 1);
   }
 
   LayoutDeviceRect GetRenderRootRect(mozilla::wr::RenderRoot aRenderRoot) {
     return mRenderRootRects[aRenderRoot];
   }