Bug 1368846 - Display the window buttons when webrender is used. r?mattwoodrow, r?kats draft
authorMarkus Stange <mstange@themasta.com>
Wed, 21 Jun 2017 18:58:41 -0400
changeset 598632 49445bf17da2eed74abcbc440f7389d883023785
parent 598532 50487f4f4373d21ca5d9a3e8a8c1e48428746c1a
child 634527 e2f9596a32ef5b0caa67357a4a931a8cbe5b562f
push id65262
push userbmo:mstange@themasta.com
push dateWed, 21 Jun 2017 23:02:07 +0000
reviewersmattwoodrow, kats
bugs1368846
milestone56.0a1
Bug 1368846 - Display the window buttons when webrender is used. r?mattwoodrow, r?kats MozReview-Commit-ID: Ki4ONGxtzyO
gfx/layers/wr/WebRenderBridgeChild.h
gfx/layers/wr/WebRenderLayerManager.cpp
gfx/webrender_bindings/RendererOGL.cpp
widget/cocoa/nsChildView.h
widget/cocoa/nsChildView.mm
widget/nsIWidget.h
--- a/gfx/layers/wr/WebRenderBridgeChild.h
+++ b/gfx/layers/wr/WebRenderBridgeChild.h
@@ -91,16 +91,21 @@ public:
 
   uint32_t GetNextResourceId() { return ++mResourceId; }
   uint32_t GetNamespace() { return mIdNamespace; }
   void SetNamespace(uint32_t aIdNamespace)
   {
     mIdNamespace = aIdNamespace;
   }
 
+  WrImageKey GetNextImageKey()
+  {
+    return WrImageKey{ GetNamespace(), GetNextResourceId() };
+  }
+
   void PushGlyphs(wr::DisplayListBuilder& aBuilder, const nsTArray<GlyphArray>& aGlyphs,
                   gfx::ScaledFont* aFont, const StackingContextHelper& aSc,
                   const LayerRect& aBounds, const LayerRect& aClip);
 
   wr::FontKey GetFontKeyForScaledFont(gfx::ScaledFont* aScaledFont);
 
   void RemoveExpiredFontKeys();
   void ClearReadLocks();
--- a/gfx/layers/wr/WebRenderLayerManager.cpp
+++ b/gfx/layers/wr/WebRenderLayerManager.cpp
@@ -69,16 +69,18 @@ WebRenderLayerManager::Initialize(PCompo
 
 void
 WebRenderLayerManager::Destroy()
 {
   if (IsDestroyed()) {
     return;
   }
 
+  mWidget->CleanupWebRenderWindowOverlay(WrBridge());
+
   LayerManager::Destroy();
   DiscardImages();
   DiscardCompositorAnimations();
   WrBridge()->Destroy();
 
   if (mTransactionIdAllocator) {
     // Make sure to notify the refresh driver just in case it's waiting on a
     // pending transaction. Do this at the top of the event loop so we don't
@@ -198,16 +200,17 @@ WebRenderLayerManager::EndTransactionInt
   }
   DiscardCompositorAnimations();
   mRoot->StartPendingAnimations(mAnimationReadyTime);
 
   StackingContextHelper sc;
   WrSize contentSize { (float)size.width, (float)size.height };
   wr::DisplayListBuilder builder(WrBridge()->GetPipeline(), contentSize);
   WebRenderLayer::ToWebRenderLayer(mRoot)->RenderLayer(builder, sc);
+  mWidget->AddWindowOverlayWebRenderCommands(WrBridge(), builder);
   WrBridge()->ClearReadLocks();
 
   // We can't finish this transaction so return. This usually
   // happens in an empty transaction where we can't repaint a painted layer.
   // In this case, leave the transaction open and let a full transaction happen.
   if (mTransactionIncomplete) {
     DiscardLocalImages();
     WrBridge()->ProcessWebRenderParentCommands();
--- a/gfx/webrender_bindings/RendererOGL.cpp
+++ b/gfx/webrender_bindings/RendererOGL.cpp
@@ -116,24 +116,21 @@ RendererOGL::Render()
 //#elif defined(MOZ_WIDGET_ANDROID)
 //  widgetContext.mCompositor = mCompositor;
 #endif
 
   if (!mWidget->PreRender(&widgetContext)) {
     return false;
   }
   // XXX set clear color if MOZ_WIDGET_ANDROID is defined.
-  // XXX pass the actual render bounds instead of an empty rect.
-  mWidget->DrawWindowUnderlay(&widgetContext, LayoutDeviceIntRect());
 
   auto size = mWidget->GetClientSize();
   wr_renderer_render(mWrRenderer, size.width, size.height);
 
   mGL->SwapBuffers();
-  mWidget->DrawWindowOverlay(&widgetContext, LayoutDeviceIntRect());
   mWidget->PostRender(&widgetContext);
 
   // TODO: Flush pending actions such as texture deletions/unlocks and
   //       textureHosts recycling.
 
   return true;
 }
 
--- a/widget/cocoa/nsChildView.h
+++ b/widget/cocoa/nsChildView.h
@@ -19,16 +19,17 @@
 #include "TextInputHandler.h"
 #include "nsCocoaUtils.h"
 #include "gfxQuartzSurface.h"
 #include "GLContextTypes.h"
 #include "mozilla/Mutex.h"
 #include "nsRegion.h"
 #include "mozilla/MouseEvents.h"
 #include "mozilla/UniquePtr.h"
+#include "mozilla/webrender/WebRenderTypes.h"
 
 #include "nsString.h"
 #include "nsIDragService.h"
 #include "ViewRegion.h"
 
 #import <Carbon/Carbon.h>
 #import <Cocoa/Cocoa.h>
 #import <AppKit/NSOpenGL.h>
@@ -446,16 +447,22 @@ public:
 
 #ifdef ACCESSIBILITY
   already_AddRefed<mozilla::a11y::Accessible> GetDocumentAccessible();
 #endif
 
   virtual void CreateCompositor() override;
   virtual void PrepareWindowEffects() override;
   virtual void CleanupWindowEffects() override;
+
+  virtual void AddWindowOverlayWebRenderCommands(mozilla::layers::WebRenderBridgeChild* aWrBridge,
+                                                  mozilla::wr::DisplayListBuilder& aBuilder) override;
+
+  virtual void CleanupWebRenderWindowOverlay(mozilla::layers::WebRenderBridgeChild* aWrBridge) override;
+
   virtual bool PreRender(mozilla::widget::WidgetRenderingContext* aContext) override;
   virtual void PostRender(mozilla::widget::WidgetRenderingContext* aContext) override;
   virtual void DrawWindowOverlay(mozilla::widget::WidgetRenderingContext* aManager,
                                  LayoutDeviceIntRect aRect) override;
 
   virtual void UpdateThemeGeometries(const nsTArray<ThemeGeometry>& aThemeGeometries) override;
 
   virtual void UpdateWindowDraggingRegion(const LayoutDeviceIntRegion& aRegion) override;
@@ -621,16 +628,19 @@ protected:
   CGContextRef mTitlebarCGContext;
 
   // Compositor thread only
   mozilla::UniquePtr<mozilla::widget::RectTextureImage> mResizerImage;
   mozilla::UniquePtr<mozilla::widget::RectTextureImage> mCornerMaskImage;
   mozilla::UniquePtr<mozilla::widget::RectTextureImage> mTitlebarImage;
   mozilla::UniquePtr<mozilla::widget::RectTextureImage> mBasicCompositorImage;
 
+  // Main thread + webrender only
+  mozilla::Maybe<mozilla::wr::ImageKey> mTitlebarImageKey;
+
   // The area of mTitlebarCGContext that has changed and needs to be
   // uploaded to to mTitlebarImage. Main thread only.
   nsIntRegion           mDirtyTitlebarRegion;
 
   mozilla::ViewRegion   mNonDraggableRegion;
 
   // Cached value of [mView backingScaleFactor], to avoid sending two obj-c
   // messages (respondsToSelector, backingScaleFactor) every time we need to
--- a/widget/cocoa/nsChildView.mm
+++ b/widget/cocoa/nsChildView.mm
@@ -63,16 +63,18 @@
 #include "HeapCopyOfStackArray.h"
 #include "mozilla/layers/IAPZCTreeManager.h"
 #include "mozilla/layers/APZThreadUtils.h"
 #include "mozilla/layers/GLManager.h"
 #include "mozilla/layers/CompositorOGL.h"
 #include "mozilla/layers/CompositorBridgeParent.h"
 #include "mozilla/layers/BasicCompositor.h"
 #include "mozilla/layers/InputAPZContext.h"
+#include "mozilla/layers/WebRenderBridgeChild.h"
+#include "mozilla/webrender/WebRenderAPI.h"
 #include "mozilla/widget/CompositorWidget.h"
 #include "gfxUtils.h"
 #include "gfxPrefs.h"
 #include "mozilla/gfx/2D.h"
 #include "mozilla/gfx/BorrowedContext.h"
 #include "mozilla/gfx/MacIOSurface.h"
 #ifdef ACCESSIBILITY
 #include "nsAccessibilityService.h"
@@ -2069,16 +2071,62 @@ nsChildView::PrepareWindowEffects()
 void
 nsChildView::CleanupWindowEffects()
 {
   mResizerImage = nullptr;
   mCornerMaskImage = nullptr;
   mTitlebarImage = nullptr;
 }
 
+void
+nsChildView::AddWindowOverlayWebRenderCommands(layers::WebRenderBridgeChild* aWrBridge,
+                                               wr::DisplayListBuilder& aBuilder)
+{
+  PrepareWindowEffects();
+
+  LayoutDeviceIntRegion updatedTitlebarRegion;
+  updatedTitlebarRegion.And(mUpdatedTitlebarRegion, mTitlebarRect);
+  mUpdatedTitlebarRegion.SetEmpty();
+
+  if (mTitlebarCGContext) {
+    gfx::IntSize size(CGBitmapContextGetWidth(mTitlebarCGContext),
+                      CGBitmapContextGetHeight(mTitlebarCGContext));
+    size_t stride = CGBitmapContextGetBytesPerRow(mTitlebarCGContext);
+    size_t titlebarCGContextDataLength = stride * size.height;
+    gfx::SurfaceFormat format = gfx::SurfaceFormat::B8G8R8A8;
+    wr::ByteBuffer buffer(
+      titlebarCGContextDataLength,
+      static_cast<uint8_t *>(CGBitmapContextGetData(mTitlebarCGContext)));
+
+    if (!mTitlebarImageKey) {
+      mTitlebarImageKey = Some(aWrBridge->GetNextImageKey());
+      aWrBridge->SendAddImage(*mTitlebarImageKey, size, stride, format, buffer);
+      updatedTitlebarRegion.SetEmpty();
+    }
+
+    if (!updatedTitlebarRegion.IsEmpty()) {
+      aWrBridge->SendUpdateImage(*mTitlebarImageKey, size, format, buffer);
+    }
+
+    WrRect rect = wr::ToWrRect(mTitlebarRect);
+    WrClipRegionToken clip = aBuilder.PushClipRegion(rect, nullptr);
+    aBuilder.PushImage(WrRect{ 0, 0, float(size.width), float(size.height) },
+                       clip, wr::ImageRendering::Auto, *mTitlebarImageKey);
+  }
+}
+
+void
+nsChildView::CleanupWebRenderWindowOverlay(layers::WebRenderBridgeChild* aWrBridge)
+{
+  if (mTitlebarImageKey) {
+    aWrBridge->SendDeleteImage(*mTitlebarImageKey);
+    mTitlebarImageKey = Nothing();
+  }
+}
+
 bool
 nsChildView::PreRender(WidgetRenderingContext* aContext)
 {
   UniquePtr<GLManager> manager(GLManager::CreateGLManager(aContext->mLayerManager));
   gl::GLContext* gl = manager ? manager->gl() : aContext->mGL;
   if (!gl) {
     return true;
   }
--- a/widget/nsIWidget.h
+++ b/widget/nsIWidget.h
@@ -56,28 +56,32 @@ class PluginWidgetChild;
 } // namespace plugins
 namespace layers {
 class AsyncDragMetrics;
 class Compositor;
 class CompositorBridgeChild;
 class LayerManager;
 class LayerManagerComposite;
 class PLayerTransactionChild;
+class WebRenderBridgeChild;
 struct ScrollableLayerGuid;
 } // namespace layers
 namespace gfx {
 class DrawTarget;
 class SourceSurface;
 } // namespace gfx
 namespace widget {
 class TextEventDispatcher;
 class TextEventDispatcherListener;
 class CompositorWidget;
 class CompositorWidgetInitData;
 } // namespace widget
+namespace wr {
+class DisplayListBuilder;
+} // namespace wr
 } // namespace mozilla
 
 /**
  * Callback function that processes events.
  *
  * The argument is actually a subtype (subclass) of WidgetEvent which carries
  * platform specific information about the event. Platform specific code
  * knows how to deal with it.
@@ -1270,16 +1274,28 @@ class nsIWidget : public nsISupports
      * Called before each layer manager transaction to allow any preparation
      * for DrawWindowUnderlay/Overlay that needs to be on the main thread.
      *
      * Always called on the main thread.
      */
     virtual void PrepareWindowEffects() = 0;
 
     /**
+     * Called on the main thread at the end of WebRender display list building.
+     */
+    virtual void AddWindowOverlayWebRenderCommands(mozilla::layers::WebRenderBridgeChild* aWrBridge,
+                                                   mozilla::wr::DisplayListBuilder& aBuilder) {}
+
+    /**
+     * Called on the main thread when WebRender resources used for
+     * AddWindowOverlayWebRenderCommands need to be destroyed.
+     */
+    virtual void CleanupWebRenderWindowOverlay(mozilla::layers::WebRenderBridgeChild* aWrBridge) {}
+
+    /**
      * Called when Gecko knows which themed widgets exist in this window.
      * The passed array contains an entry for every themed widget of the right
      * type (currently only NS_THEME_TOOLBAR) within the window, except for
      * themed widgets which are transformed or have effects applied to them
      * (e.g. CSS opacity or filters).
      * This could sometimes be called during display list construction
      * outside of painting.
      * If called during painting, it will be called before we actually