gecko-dev/widget/CompositorWidget.h

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

309 строки
9.7 KiB
C
Исходник Обычный вид История

/* 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 http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_widget_CompositorWidget_h__
#define mozilla_widget_CompositorWidget_h__
#include "nsISupports.h"
#include "mozilla/RefPtr.h"
#include "Units.h"
#include "mozilla/gfx/2D.h"
#include "mozilla/layers/CompositorOptions.h"
#include "mozilla/layers/LayersTypes.h"
#include "mozilla/layers/NativeLayer.h"
class nsIWidget;
class nsBaseWidget;
namespace mozilla {
class VsyncObserver;
namespace gl {
class GLContext;
} // namespace gl
namespace layers {
class Compositor;
class LayerManager;
class LayerManagerComposite;
class Compositor;
} // namespace layers
namespace gfx {
class DrawTarget;
class SourceSurface;
} // namespace gfx
namespace widget {
class WinCompositorWidget;
class GtkCompositorWidget;
class AndroidCompositorWidget;
class CompositorWidgetInitData;
// Gecko widgets usually need to communicate with the CompositorWidget with
// platform-specific messages (for example to update the window size or
// transparency). This functionality is controlled through a "host". Since
// this functionality is platform-dependent, it is only forward declared
// here.
Bug 1373739 - Make headless compositing Windows-compatible, in addition to Linux. r=dvander To make the HeadlessCompositorWidget work under Windows as well as Linux, I had to change the way that I hooked it into the existing CompositorWidget system. Under GTK, the CompositorWidgetInitData and CompositorWidgetDelegate types provided the information needed by the headless compositor widget already (the widget client size). On Windows, however, the definitions of these types differ, and the client size information is simply retrieved from the platform APIs when needed. After this patch, CompositorWidgetDelegate is renamed to PlatformCompositorWidgetDelegate, and a new base class called CompositorWidgetDelegate is added with "AsPlatformSpecificDelegate()" and "AsHeadlessCompositorWidget()" methods. In non-headless mode, widgets use AsPlatformSpecificDelegate() to access the Windows- and GTK-specific delegate APIs. In headless mode, AsHeadlessCompositorWidget() is used to access the singular CompositorWidget implementation for headless. Meanwhile, the CompositorWidgetInitData IPDL type is made into a union which always contains a headless-specific HeadlessCompositorWidgetInitData struct and under GTK and Windows also contains an {X11,Win}CompositorWidgetInitData struct. This also includes a small patch to ensure that the GPU process and hardware-accelerated compositing are always disabled under headless mode. These features weren't activated by default in the Linux environments I tested in, but did end up activating (and then promptly crashing Firefox) when I tested on Windows. MozReview-Commit-ID: CocPoHBDV7H --HG-- extra : rebase_source : 4581fa63aa3a9f32a8dc2672015a35b9be01b20f
2017-07-07 03:45:34 +03:00
class PlatformCompositorWidgetDelegate;
// Headless mode uses its own, singular CompositorWidget implementation.
class HeadlessCompositorWidget;
class CompositorWidgetDelegate {
public:
virtual PlatformCompositorWidgetDelegate* AsPlatformSpecificDelegate() {
return nullptr;
}
virtual HeadlessCompositorWidget* AsHeadlessCompositorWidget() {
return nullptr;
}
};
// Platforms that support out-of-process widgets.
#if defined(XP_WIN) || defined(MOZ_X11)
// CompositorWidgetParent should implement CompositorWidget and
// PCompositorWidgetParent.
class CompositorWidgetParent;
// CompositorWidgetChild should implement CompositorWidgetDelegate and
// PCompositorWidgetChild.
class CompositorWidgetChild;
# define MOZ_WIDGET_SUPPORTS_OOP_COMPOSITING
#endif
class WidgetRenderingContext {
public:
#if defined(XP_MACOSX)
WidgetRenderingContext() : mLayerManager(nullptr), mGL(nullptr) {}
layers::LayerManagerComposite* mLayerManager;
gl::GLContext* mGL;
#elif defined(MOZ_WIDGET_ANDROID)
WidgetRenderingContext() : mCompositor(nullptr) {}
layers::Compositor* mCompositor;
#endif
};
/**
* Access to a widget from the compositor is restricted to these methods.
*/
class CompositorWidget {
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(mozilla::widget::CompositorWidget)
/**
* Create an in-process compositor widget. aWidget may be ignored if the
* platform does not require it.
*/
static RefPtr<CompositorWidget> CreateLocal(
const CompositorWidgetInitData& aInitData,
const layers::CompositorOptions& aOptions, nsIWidget* aWidget);
/**
* Called before rendering using OMTC. Returns false when the widget is
* not ready to be rendered (for example while the window is closed).
*
* Always called from the compositing thread, which may be the main-thread if
* OMTC is not enabled.
*/
virtual bool PreRender(WidgetRenderingContext* aContext) { return true; }
/**
* Called after rendering using OMTC. Not called when rendering was
* cancelled by a negative return value from PreRender.
*
* Always called from the compositing thread, which may be the main-thread if
* OMTC is not enabled.
*/
virtual void PostRender(WidgetRenderingContext* aContext) {}
/**
* Called before the first composite. If the result is non-null, one or more
* native layers will be placed on the window and used for compositing.
* When native layers are used, StartRemoteDrawing(InRegion) and
* EndRemoteDrawing(InRegion) will not be called.
*/
virtual RefPtr<layers::NativeLayerRoot> GetNativeLayerRoot() {
return nullptr;
}
/**
* Called after the LayerManager draws the layer tree
*
* Always called from the compositing thread.
*/
virtual void DrawWindowOverlay(WidgetRenderingContext* aContext,
LayoutDeviceIntRect aRect) {}
/**
* Return a DrawTarget for the window which can be composited into.
*
* Only called if GetNativeLayerRoot() returns nullptr.
* Called by BasicCompositor on the compositor thread for OMTC drawing
* before each composition (unless there's a native layer root).
*
* The window may specify its buffer mode. If unspecified, it is assumed
* to require double-buffering.
*/
virtual already_AddRefed<gfx::DrawTarget> StartRemoteDrawing();
virtual already_AddRefed<gfx::DrawTarget> StartRemoteDrawingInRegion(
LayoutDeviceIntRegion& aInvalidRegion, layers::BufferMode* aBufferMode) {
return StartRemoteDrawing();
}
/**
* Ensure that what was painted into the DrawTarget returned from
* StartRemoteDrawing reaches the screen.
*
* Called by BasicCompositor on the compositor thread for OMTC drawing
* after each composition for which StartRemoteDrawing(InRegion) was called.
*/
virtual void EndRemoteDrawing() {}
virtual void EndRemoteDrawingInRegion(
gfx::DrawTarget* aDrawTarget,
const LayoutDeviceIntRegion& aInvalidRegion) {
EndRemoteDrawing();
}
/**
* Return true when it is better to defer EndRemoteDrawing().
*
* Called by BasicCompositor on the compositor thread for OMTC drawing
* after each composition.
*/
virtual bool NeedsToDeferEndRemoteDrawing() { return false; }
/**
* Called when shutting down the LayerManager to clean-up any cached
* resources.
*
* Always called from the compositing thread.
*/
virtual void CleanupWindowEffects() {}
/**
* A hook for the widget to prepare a Compositor, during the latter's
* initialization.
*
* If this method returns true, it means that the widget will be able to
* present frames from the compoositor.
*
* Returning false will cause the compositor's initialization to fail, and
* a different compositor backend will be used (if any).
*/
virtual bool InitCompositor(layers::Compositor* aCompositor) { return true; }
/**
* Return the size of the drawable area of the widget.
*/
virtual LayoutDeviceIntSize GetClientSize() = 0;
/**
* Return the internal format of the default framebuffer for this
* widget.
*/
virtual uint32_t GetGLFrameBufferFormat();
/*
* Access the underlying nsIWidget. This method will be removed when the
* compositor no longer depends on nsIWidget on any platform.
*/
virtual nsIWidget* RealWidget() = 0;
/**
* Clean up any resources used by Start/EndRemoteDrawing.
*
* Called by BasicCompositor on the compositor thread for OMTC drawing
* when the compositor is destroyed.
*/
virtual void CleanupRemoteDrawing();
/**
* Return a key that can represent the widget object round-trip across the
* CompositorBridge channel. This only needs to be implemented on GTK and
* Windows.
*
* The key must be the nsIWidget pointer cast to a uintptr_t. See
* CompositorBridgeChild::RecvHideAllPlugins and
* CompositorBridgeParent::SendHideAllPlugins.
*/
virtual uintptr_t GetWidgetKey() { return 0; }
/**
* Create a backbuffer for the software compositor.
*/
virtual already_AddRefed<gfx::DrawTarget> GetBackBufferDrawTarget(
gfx::DrawTarget* aScreenTarget, const gfx::IntRect& aRect,
bool* aOutIsCleared);
/**
* Ensure end of composition to back buffer.
*
* Called by BasicCompositor on the compositor thread for OMTC drawing
* after each composition to back buffer.
*/
virtual already_AddRefed<gfx::SourceSurface> EndBackBufferDrawing();
#ifdef XP_MACOSX
/**
* Return the opaque region of the widget. This is racy and can only be used
* on macOS, where the widget works around the raciness.
* Bug 1576491 tracks fixing this properly.
* The problem with this method is that it can return values "from the future"
* - the compositor might be working on frame N but the widget will return its
* opaque region from frame N + 1.
* It is believed that this won't lead to visible glitches on macOS due to the
* SuspendAsyncCATransactions call when the vibrant region changes or when the
* window resizes. Whenever the compositor uses an opaque region that's a
* frame ahead, the result it renders won't be shown on the screen; instead,
* the next composite will happen with the correct display list, and that's
* what's shown on the screen once the FlushRendering call completes.
*/
virtual LayoutDeviceIntRegion GetOpaqueWidgetRegion() { return {}; }
#endif
/**
* Observe or unobserve vsync.
*/
virtual void ObserveVsync(VsyncObserver* aObserver) = 0;
/**
* Get the compositor options for the compositor associated with this
* CompositorWidget.
*/
const layers::CompositorOptions& GetCompositorOptions() { return mOptions; }
/**
* Return true if the window is hidden and should not be composited.
*/
virtual bool IsHidden() const { return false; }
/**
* This is only used by out-of-process compositors.
*/
virtual RefPtr<VsyncObserver> GetVsyncObserver() const;
virtual WinCompositorWidget* AsWindows() { return nullptr; }
virtual GtkCompositorWidget* AsX11() { return nullptr; }
virtual AndroidCompositorWidget* AsAndroid() { return nullptr; }
/**
* Return the platform-specific delegate for the widget, if any.
*/
virtual CompositorWidgetDelegate* AsDelegate() { return nullptr; }
protected:
explicit CompositorWidget(const layers::CompositorOptions& aOptions);
virtual ~CompositorWidget();
// Back buffer of BasicCompositor
RefPtr<gfx::DrawTarget> mLastBackBuffer;
layers::CompositorOptions mOptions;
};
} // namespace widget
} // namespace mozilla
#endif