Bug 1591004 - First pass of OS compositor implementation on Windows r=gw

This implementation is off by default (behind gfx.webrender.compositor) until various bugs and inefficiencies are fixed.

Differential Revision: https://phabricator.services.mozilla.com/D51034

--HG--
extra : moz-landing-system : lando
This commit is contained in:
sotaro 2019-10-31 11:59:17 +00:00
Родитель 5125b83ec7
Коммит 4404c0826a
5 изменённых файлов: 455 добавлений и 54 удалений

Просмотреть файл

@ -6,6 +6,8 @@
#include "DCLayerTree.h"
#include "GLContext.h"
#include "GLContextEGL.h"
#include "mozilla/gfx/DeviceManagerDx.h"
#include "mozilla/StaticPrefs_gfx.h"
@ -26,14 +28,17 @@ namespace wr {
#if !defined(__MINGW32__)
/* static */
UniquePtr<DCLayerTree> DCLayerTree::Create(HWND aHwnd) {
UniquePtr<DCLayerTree> DCLayerTree::Create(gl::GLContext* aGL,
EGLConfig aEGLConfig,
ID3D11Device* aDevice, HWND aHwnd) {
RefPtr<IDCompositionDevice2> dCompDevice =
gfx::DeviceManagerDx::Get()->GetDirectCompositionDevice();
if (!dCompDevice) {
return nullptr;
}
auto layerTree = MakeUnique<DCLayerTree>(dCompDevice);
auto layerTree =
MakeUnique<DCLayerTree>(aGL, aEGLConfig, aDevice, dCompDevice);
if (!layerTree->Initialize(aHwnd)) {
return nullptr;
}
@ -41,8 +46,13 @@ UniquePtr<DCLayerTree> DCLayerTree::Create(HWND aHwnd) {
return layerTree;
}
DCLayerTree::DCLayerTree(IDCompositionDevice2* aCompositionDevice)
: mCompositionDevice(aCompositionDevice),
DCLayerTree::DCLayerTree(gl::GLContext* aGL, EGLConfig aEGLConfig,
ID3D11Device* aDevice,
IDCompositionDevice2* aCompositionDevice)
: mGL(aGL),
mEGLConfig(aEGLConfig),
mDevice(aDevice),
mCompositionDevice(aCompositionDevice),
mDebugCounter(false),
mDebugVisualRedrawRegions(false) {}
@ -155,6 +165,235 @@ bool DCLayerTree::MaybeUpdateDebugVisualRedrawRegions() {
return true;
}
void DCLayerTree::CompositorBeginFrame() { mRootVisual->RemoveAllVisuals(); }
void DCLayerTree::CompositorEndFrame() { mCompositionDevice->Commit(); }
void DCLayerTree::Bind(wr::NativeSurfaceId aId, wr::DeviceIntPoint* aOffset,
uint32_t* aFboId, wr::DeviceIntRect aDirtyRect) {
auto it = mDCLayers.find(wr::AsUint64(aId));
MOZ_ASSERT(it != mDCLayers.end());
if (it == mDCLayers.end()) {
return;
}
const auto layer = it->second.get();
layer->CreateEGLSurfaceForCompositionSurface(aOffset);
MOZ_ASSERT(layer->GetEGLSurface() != EGL_NO_SURFACE);
gl::GLContextEGL::Cast(mGL)->SetEGLSurfaceOverride(layer->GetEGLSurface());
mCurrentId = Some(aId);
}
void DCLayerTree::Unbind() {
const auto& gle = gl::GLContextEGL::Cast(mGL);
gle->SetEGLSurfaceOverride(EGL_NO_SURFACE);
if (mCurrentId.isNothing()) {
return;
}
auto it = mDCLayers.find(wr::AsUint64(mCurrentId.ref()));
MOZ_RELEASE_ASSERT(it != mDCLayers.end());
const auto layer = it->second.get();
layer->EndDraw();
mCurrentId = Nothing();
}
void DCLayerTree::CreateSurface(wr::NativeSurfaceId aId,
wr::DeviceIntSize aSize, bool aIsOpaque) {
auto it = mDCLayers.find(wr::AsUint64(aId));
// XXX sometime, the following assert was failed.
// MOZ_RELEASE_ASSERT(it == mDCLayers.end());
MOZ_ASSERT(it == mDCLayers.end());
if (it != mDCLayers.end()) {
// DCLayer already exists.
return;
}
auto layer = MakeUnique<DCLayer>(this);
if (!layer->Initialize(aSize)) {
gfxCriticalNote << "Failed to initialize DCLayer";
return;
}
mDCLayers[wr::AsUint64(aId)] = std::move(layer);
}
void DCLayerTree::DestroySurface(NativeSurfaceId aId) {
auto it = mDCLayers.find(wr::AsUint64(aId));
MOZ_ASSERT(it != mDCLayers.end());
if (it == mDCLayers.end()) {
return;
}
mDCLayers.erase(it);
}
void DCLayerTree::AddSurface(wr::NativeSurfaceId aId,
wr::DeviceIntPoint aPosition,
wr::DeviceIntRect aClipRect) {
auto it = mDCLayers.find(wr::AsUint64(aId));
MOZ_ASSERT(it != mDCLayers.end());
if (it == mDCLayers.end()) {
return;
}
const auto layer = it->second.get();
const auto visual = layer->GetVisual();
// Add this visual as the last element in the visual tree (z-order is
// implicit, based on the order tiles are added).
mRootVisual->AddVisual(visual, FALSE, nullptr);
// Place the visual - this changes frame to frame based on scroll position
// of the slice.
int offset_x = aPosition.x;
int offset_y = aPosition.y;
visual->SetOffsetX(offset_x);
visual->SetOffsetY(offset_y);
// Set the clip rect - converting from world space to the pre-offset space
// that DC requires for rectangle clips.
D2D_RECT_F clip_rect;
clip_rect.left = aClipRect.origin.x - offset_x;
clip_rect.top = aClipRect.origin.y - offset_y;
clip_rect.right = clip_rect.left + aClipRect.size.width;
clip_rect.bottom = clip_rect.top + aClipRect.size.height;
visual->SetClip(clip_rect);
}
DCLayer::DCLayer(DCLayerTree* aDCLayerTree)
: mDCLayerTree(aDCLayerTree), mEGLSurface(EGL_NO_SURFACE) {}
DCLayer::~DCLayer() { DestroyEGLSurface(); }
bool DCLayer::Initialize(wr::DeviceIntSize aSize) {
if (aSize.width <= 0 || aSize.height <= 0) {
return false;
}
mBufferSize = LayoutDeviceIntSize(aSize.width, aSize.height);
HRESULT hr;
const auto dCompDevice = mDCLayerTree->GetCompositionDevice();
hr = dCompDevice->CreateVisual(getter_AddRefs(mVisual));
if (FAILED(hr)) {
gfxCriticalNote << "Failed to create DCompositionVisual: " << gfx::hexa(hr);
return false;
}
// XXX Always request alpha usage. But it could degrade performance.
mCompositionSurface = CreateCompositionSurface(aSize, /* aUseAlpha */ true);
if (!mCompositionSurface) {
return false;
}
hr = mVisual->SetContent(mCompositionSurface);
if (FAILED(hr)) {
gfxCriticalNote << "SetContent failed: " << gfx::hexa(hr);
return false;
}
return true;
}
RefPtr<IDCompositionSurface> DCLayer::CreateCompositionSurface(
wr::DeviceIntSize aSize, bool aUseAlpha) {
HRESULT hr;
const auto dCompDevice = mDCLayerTree->GetCompositionDevice();
const auto alphaMode =
aUseAlpha ? DXGI_ALPHA_MODE_PREMULTIPLIED : DXGI_ALPHA_MODE_IGNORE;
RefPtr<IDCompositionSurface> compositionSurface;
hr = dCompDevice->CreateSurface(aSize.width, aSize.height,
DXGI_FORMAT_B8G8R8A8_UNORM, alphaMode,
getter_AddRefs(compositionSurface));
if (FAILED(hr)) {
gfxCriticalNote << "Failed to create DCompositionSurface: "
<< gfx::hexa(hr);
return nullptr;
}
return compositionSurface;
}
bool DCLayer::CreateEGLSurfaceForCompositionSurface(
wr::DeviceIntPoint* aOffset) {
MOZ_ASSERT(mCompositionSurface.get());
HRESULT hr;
const auto gl = mDCLayerTree->GetGLContext();
const auto config = mDCLayerTree->GetEGLConfig();
RefPtr<ID3D11Texture2D> backBuf;
POINT offset;
hr = mCompositionSurface->BeginDraw(NULL, __uuidof(ID3D11Texture2D),
(void**)getter_AddRefs(backBuf), &offset);
if (FAILED(hr)) {
gfxCriticalNote << "DCompositionSurface::BeginDraw failed: "
<< gfx::hexa(hr);
return false;
}
// Texture size could be diffrent from mBufferSize.
D3D11_TEXTURE2D_DESC desc;
backBuf->GetDesc(&desc);
const EGLint pbuffer_attribs[]{
LOCAL_EGL_WIDTH,
static_cast<EGLint>(desc.Width),
LOCAL_EGL_HEIGHT,
static_cast<EGLint>(desc.Height),
LOCAL_EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE,
LOCAL_EGL_TRUE,
LOCAL_EGL_NONE};
const auto buffer = reinterpret_cast<EGLClientBuffer>(backBuf.get());
const auto& gle = gl::GLContextEGL::Cast(gl);
const auto& egl = gle->mEgl;
const EGLSurface surface = egl->fCreatePbufferFromClientBuffer(
egl->Display(), LOCAL_EGL_D3D_TEXTURE_ANGLE, buffer, config,
pbuffer_attribs);
EGLint err = egl->fGetError();
if (err != LOCAL_EGL_SUCCESS) {
gfxCriticalError() << "Failed to create Pbuffer of back buffer error: "
<< gfx::hexa(err) << " Size : " << mBufferSize
<< " Actual Size : "
<< LayoutDeviceIntSize(desc.Width, desc.Height);
return false;
}
aOffset->x = offset.x;
aOffset->y = offset.y;
mEGLSurface = surface;
return true;
}
void DCLayer::DestroyEGLSurface() {
const auto gl = mDCLayerTree->GetGLContext();
// Release EGLSurface of back buffer before calling ResizeBuffers().
if (mEGLSurface) {
const auto& gle = gl::GLContextEGL::Cast(gl);
const auto& egl = gle->mEgl;
gle->SetEGLSurfaceOverride(EGL_NO_SURFACE);
egl->fDestroySurface(egl->Display(), mEGLSurface);
mEGLSurface = EGL_NO_SURFACE;
}
}
void DCLayer::EndDraw() {
MOZ_ASSERT(mCompositionSurface.get());
if (!mCompositionSurface) {
return;
}
mCompositionSurface->EndDraw();
DestroyEGLSurface();
}
#endif
} // namespace wr
} // namespace mozilla

Просмотреть файл

@ -7,41 +7,82 @@
#ifndef MOZILLA_GFX_DCLAYER_TREE_H
#define MOZILLA_GFX_DCLAYER_TREE_H
#include <unordered_map>
#include <windows.h>
#include "GLTypes.h"
#include "mozilla/Maybe.h"
#include "mozilla/RefPtr.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/webrender/WebRenderTypes.h"
struct ID3D11Device;
struct ID3D11DeviceContext;
struct IDCompositionDevice2;
struct IDCompositionSurface;
struct IDCompositionTarget;
struct IDCompositionVisual2;
struct IDXGISwapChain1;
namespace mozilla {
namespace gl {
class GLContext;
}
namespace wr {
// Currently, MinGW build environment does not handle IDCompositionDesktopDevice
// and IDCompositionDevice2
#if !defined(__MINGW32__)
class DCLayer;
/**
* DCLayerTree manages direct composition layers.
* It does not manage gecko's layers::Layer.
*/
class DCLayerTree {
public:
static UniquePtr<DCLayerTree> Create(HWND aHwnd);
explicit DCLayerTree(IDCompositionDevice2* aCompositionDevice);
static UniquePtr<DCLayerTree> Create(gl::GLContext* aGL, EGLConfig aEGLConfig,
ID3D11Device* aDevice, HWND aHwnd);
explicit DCLayerTree(gl::GLContext* aGL, EGLConfig aEGLConfig,
ID3D11Device* aDevice,
IDCompositionDevice2* aCompositionDevice);
~DCLayerTree();
void SetDefaultSwapChain(IDXGISwapChain1* aSwapChain);
void MaybeUpdateDebug();
// Interface for wr::Compositor
void CompositorBeginFrame();
void CompositorEndFrame();
void Bind(wr::NativeSurfaceId aId, wr::DeviceIntPoint* aOffset,
uint32_t* aFboId, wr::DeviceIntRect aDirtyRect);
void Unbind();
void CreateSurface(wr::NativeSurfaceId aId, wr::DeviceIntSize aSize,
bool aIsOpaque);
void DestroySurface(NativeSurfaceId aId);
void AddSurface(wr::NativeSurfaceId aId, wr::DeviceIntPoint aPosition,
wr::DeviceIntRect aClipRect);
gl::GLContext* GetGLContext() const { return mGL; }
EGLConfig GetEGLConfig() const { return mEGLConfig; }
ID3D11Device* GetDevice() const { return mDevice; }
IDCompositionDevice2* GetCompositionDevice() const {
return mCompositionDevice;
}
protected:
bool Initialize(HWND aHwnd);
bool MaybeUpdateDebugCounter();
bool MaybeUpdateDebugVisualRedrawRegions();
RefPtr<gl::GLContext> mGL;
EGLConfig mEGLConfig;
RefPtr<ID3D11Device> mDevice;
RefPtr<IDCompositionDevice2> mCompositionDevice;
RefPtr<IDCompositionTarget> mCompositionTarget;
RefPtr<IDCompositionVisual2> mRootVisual;
@ -49,13 +90,63 @@ class DCLayerTree {
bool mDebugCounter;
bool mDebugVisualRedrawRegions;
Maybe<wr::NativeSurfaceId> mCurrentId;
std::unordered_map<uint64_t, UniquePtr<DCLayer>> mDCLayers;
};
class DCLayer {
public:
explicit DCLayer(DCLayerTree* aDCLayerTree);
~DCLayer();
bool Initialize(wr::DeviceIntSize aSize);
bool CreateEGLSurfaceForCompositionSurface(wr::DeviceIntPoint* aOffset);
void EndDraw();
IDCompositionSurface* GetCompositionSurface() const {
return mCompositionSurface;
}
EGLSurface GetEGLSurface() const { return mEGLSurface; }
IDCompositionVisual2* GetVisual() const { return mVisual; }
protected:
RefPtr<IDCompositionSurface> CreateCompositionSurface(wr::DeviceIntSize aSize,
bool aUseAlpha);
void DestroyEGLSurface();
protected:
DCLayerTree* mDCLayerTree;
RefPtr<IDCompositionSurface> mCompositionSurface;
LayoutDeviceIntSize mBufferSize;
EGLSurface mEGLSurface;
RefPtr<IDCompositionVisual2> mVisual;
};
#else
class DCLayerTree {
public:
static UniquePtr<DCLayerTree> Create(HWND aHwnd) { return nullptr; }
static UniquePtr<DCLayerTree> Create(gl::GLContext* aGL, EGLConfig aEGLConfig,
ID3D11Device* aDevice, HWND aHwnd) {
return nullptr;
}
void SetDefaultSwapChain(IDXGISwapChain1* aSwapChain) {}
void MaybeUpdateDebug() {}
// Interface for wr::Compositor
void CompositorBeginFrame() {}
void CompositorEndFrame() {}
void Bind(wr::NativeSurfaceId aId, wr::DeviceIntPoint* aOffset,
uint32_t* aFboId, wr::DeviceIntRect aDirtyRect) {}
void Unbind() {}
void CreateSurface(wr::NativeSurfaceId aId, wr::DeviceIntSize aSize,
bool aIsOpaque) {}
void DestroySurface(NativeSurfaceId aId) {}
void AddSurface(wr::NativeSurfaceId aId, wr::DeviceIntPoint aPosition,
wr::DeviceIntRect aClipRect) {}
};
#endif

Просмотреть файл

@ -76,8 +76,6 @@ class RenderCompositor {
virtual void AddSurface(wr::NativeSurfaceId aId, wr::DeviceIntPoint aPosition,
wr::DeviceIntRect aClipRect) {}
void wr_compositor_unbind(void* aCompositor) {}
// Whether the surface contents are flipped vertically
virtual bool SurfaceIsYFlipped() { return false; }

Просмотреть файл

@ -14,6 +14,7 @@
#include "mozilla/gfx/Logging.h"
#include "mozilla/layers/HelpersD3D11.h"
#include "mozilla/layers/SyncObject.h"
#include "mozilla/StaticPrefs_gfx.h"
#include "mozilla/webrender/DCLayerTree.h"
#include "mozilla/webrender/RenderThread.h"
#include "mozilla/widget/CompositorWidget.h"
@ -124,6 +125,16 @@ bool RenderCompositorANGLE::Initialize() {
return false;
}
// Force enable alpha channel to make sure ANGLE use correct framebuffer
// formart
const auto& gle = gl::GLContextEGL::Cast(gl);
const auto& egl = gle->mEgl;
if (!gl::CreateConfig(egl, &mEGLConfig, /* bpp */ 32,
/* enableDepthBuffer */ true)) {
gfxCriticalNote << "Failed to create EGLConfig for WebRender";
}
MOZ_ASSERT(mEGLConfig);
mDevice = GetDeviceOfEGLDisplay();
if (!mDevice) {
@ -237,18 +248,10 @@ bool RenderCompositorANGLE::Initialize() {
return false;
}
// Force enable alpha channel to make sure ANGLE use correct framebuffer
// formart
const auto& gle = gl::GLContextEGL::Cast(gl);
const auto& egl = gle->mEgl;
if (!gl::CreateConfig(egl, &mEGLConfig, /* bpp */ 32,
/* enableDepthBuffer */ true)) {
gfxCriticalNote << "Failed to create EGLConfig for WebRender";
}
MOZ_ASSERT(mEGLConfig);
if (!ResizeBufferIfNeeded()) {
return false;
if (!UseCompositor()) {
if (!ResizeBufferIfNeeded()) {
return false;
}
}
return true;
@ -266,13 +269,16 @@ void RenderCompositorANGLE::CreateSwapChainForDCompIfPossible(
return;
}
mDCLayerTree = DCLayerTree::Create(hwnd);
mDCLayerTree = DCLayerTree::Create(gl(), mEGLConfig, mDevice, hwnd);
if (!mDCLayerTree) {
return;
}
MOZ_ASSERT(XRE_IsGPUProcess());
bool useTripleBuffering = gfx::gfxVars::UseWebRenderTripleBufferingWin();
// When compositor is enabled, CompositionSurface is used for rendering.
// It does not support triple buffering.
bool useTripleBuffering =
gfx::gfxVars::UseWebRenderTripleBufferingWin() && !UseCompositor();
// Non Glass window is common since Windows 10.
bool useAlpha = false;
RefPtr<IDXGISwapChain1> swapChain1 =
@ -352,29 +358,32 @@ RefPtr<IDXGISwapChain1> RenderCompositorANGLE::CreateSwapChainForDComp(
bool RenderCompositorANGLE::BeginFrame() {
mWidget->AsWindows()->UpdateCompositorWndSizeIfNecessary();
if (mDCLayerTree) {
bool useAlpha = mWidget->AsWindows()->HasGlass();
// When Alpha usage is changed, SwapChain needs to be recreatd.
if (useAlpha != mUseAlpha) {
DestroyEGLSurface();
mBufferSize.reset();
if (!UseCompositor()) {
if (mDCLayerTree) {
bool useAlpha = mWidget->AsWindows()->HasGlass();
// When Alpha usage is changed, SwapChain needs to be recreatd.
if (useAlpha != mUseAlpha) {
DestroyEGLSurface();
mBufferSize.reset();
RefPtr<IDXGISwapChain1> swapChain1 =
CreateSwapChainForDComp(mUseTripleBuffering, useAlpha);
if (swapChain1) {
mSwapChain = swapChain1;
mUseAlpha = useAlpha;
mDCLayerTree->SetDefaultSwapChain(swapChain1);
} else {
gfxCriticalNote << "Failed to re-create SwapChain";
RenderThread::Get()->HandleWebRenderError(WebRenderError::NEW_SURFACE);
return false;
RefPtr<IDXGISwapChain1> swapChain1 =
CreateSwapChainForDComp(mUseTripleBuffering, useAlpha);
if (swapChain1) {
mSwapChain = swapChain1;
mUseAlpha = useAlpha;
mDCLayerTree->SetDefaultSwapChain(swapChain1);
} else {
gfxCriticalNote << "Failed to re-create SwapChain";
RenderThread::Get()->HandleWebRenderError(
WebRenderError::NEW_SURFACE);
return false;
}
}
}
}
if (!ResizeBufferIfNeeded()) {
return false;
if (!ResizeBufferIfNeeded()) {
return false;
}
}
if (!MakeCurrent()) {
@ -395,17 +404,19 @@ bool RenderCompositorANGLE::BeginFrame() {
void RenderCompositorANGLE::EndFrame() {
InsertPresentWaitQuery();
if (mWidget->AsWindows()->HasFxrOutputHandler()) {
// There is a Firefox Reality handler for this swapchain. Update this
// window's contents to the VR window.
FxROutputHandler* fxrHandler = mWidget->AsWindows()->GetFxrOutputHandler();
if (fxrHandler->TryInitialize(mSwapChain, mDevice)) {
fxrHandler->UpdateOutput(mCtx);
if (!UseCompositor()) {
if (mWidget->AsWindows()->HasFxrOutputHandler()) {
// There is a Firefox Reality handler for this swapchain. Update this
// window's contents to the VR window.
FxROutputHandler* fxrHandler =
mWidget->AsWindows()->GetFxrOutputHandler();
if (fxrHandler->TryInitialize(mSwapChain, mDevice)) {
fxrHandler->UpdateOutput(mCtx);
}
}
mSwapChain->Present(0, 0);
}
mSwapChain->Present(0, 0);
if (mDCLayerTree) {
mDCLayerTree->MaybeUpdateDebug();
}
@ -548,11 +559,15 @@ bool RenderCompositorANGLE::MakeCurrent() {
}
LayoutDeviceIntSize RenderCompositorANGLE::GetBufferSize() {
MOZ_ASSERT(mBufferSize.isSome());
if (mBufferSize.isNothing()) {
return LayoutDeviceIntSize();
if (!UseCompositor()) {
MOZ_ASSERT(mBufferSize.isSome());
if (mBufferSize.isNothing()) {
return LayoutDeviceIntSize();
}
return mBufferSize.ref();
} else {
return mWidget->GetClientSize();
}
return mBufferSize.ref();
}
RefPtr<ID3D11Query> RenderCompositorANGLE::GetD3D11Query() {
@ -610,5 +625,48 @@ bool RenderCompositorANGLE::IsContextLost() {
return false;
}
bool RenderCompositorANGLE::UseCompositor() {
if (!mDCLayerTree || !StaticPrefs::gfx_webrender_compositor_AtStartup()) {
return false;
}
return true;
}
bool RenderCompositorANGLE::ShouldUseNativeCompositor() {
return UseCompositor();
}
void RenderCompositorANGLE::CompositorBeginFrame() {
mDCLayerTree->CompositorBeginFrame();
}
void RenderCompositorANGLE::CompositorEndFrame() {
mDCLayerTree->CompositorEndFrame();
}
void RenderCompositorANGLE::Bind(wr::NativeSurfaceId aId,
wr::DeviceIntPoint* aOffset, uint32_t* aFboId,
wr::DeviceIntRect aDirtyRect) {
mDCLayerTree->Bind(aId, aOffset, aFboId, aDirtyRect);
}
void RenderCompositorANGLE::Unbind() { mDCLayerTree->Unbind(); }
void RenderCompositorANGLE::CreateSurface(wr::NativeSurfaceId aId,
wr::DeviceIntSize aSize,
bool aIsOpaque) {
mDCLayerTree->CreateSurface(aId, aSize, aIsOpaque);
}
void RenderCompositorANGLE::DestroySurface(NativeSurfaceId aId) {
mDCLayerTree->DestroySurface(aId);
}
void RenderCompositorANGLE::AddSurface(wr::NativeSurfaceId aId,
wr::DeviceIntPoint aPosition,
wr::DeviceIntRect aClipRect) {
mDCLayerTree->AddSurface(aId, aPosition, aClipRect);
}
} // namespace wr
} // namespace mozilla

Просмотреть файл

@ -61,7 +61,22 @@ class RenderCompositorANGLE : public RenderCompositor {
bool SurfaceIsYFlipped() override { return true; }
bool ShouldUseNativeCompositor() override;
// Interface for wr::Compositor
void CompositorBeginFrame() override;
void CompositorEndFrame() override;
void Bind(wr::NativeSurfaceId aId, wr::DeviceIntPoint* aOffset,
uint32_t* aFboId, wr::DeviceIntRect aDirtyRect) override;
void Unbind() override;
void CreateSurface(wr::NativeSurfaceId aId, wr::DeviceIntSize aSize,
bool aIsOpaque) override;
void DestroySurface(NativeSurfaceId aId) override;
void AddSurface(wr::NativeSurfaceId aId, wr::DeviceIntPoint aPosition,
wr::DeviceIntRect aClipRect) override;
protected:
bool UseCompositor();
void InsertPresentWaitQuery();
bool WaitForPreviousPresentQuery();
bool ResizeBufferIfNeeded();