зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
5125b83ec7
Коммит
4404c0826a
|
@ -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();
|
||||
|
|
Загрузка…
Ссылка в новой задаче