Bug 1573710 - Trigger composite after SetParent() r=Gankro

The patch permits to resize compositor window's size after ::SetParent() call to prevent a conflict between ::SetParent() and ::SetWindowPos(). Then it triggers a composite after SetParent() call to resize compositor window correctly.

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

--HG--
extra : moz-landing-system : lando
This commit is contained in:
sotaro 2019-10-28 21:33:40 +00:00
Родитель 9df2ccc256
Коммит 16784c5201
15 изменённых файлов: 109 добавлений и 16 удалений

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

@ -1451,8 +1451,6 @@ void CompositorD3D11::PrepareViewport(const gfx::IntSize& aSize,
void CompositorD3D11::EnsureSize() { mSize = mWidget->GetClientSize(); }
bool CompositorD3D11::VerifyBufferSize() {
mWidget->AsWindows()->UpdateCompositorWndSizeIfNecessary();
DXGI_SWAP_CHAIN_DESC swapDesc;
HRESULT hr;

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

@ -380,8 +380,6 @@ void MLGSwapChainD3D11::UpdateBackBufferContents(ID3D11Texture2D* aBack) {
}
bool MLGSwapChainD3D11::ResizeBuffers(const IntSize& aSize) {
mWidget->AsWindows()->UpdateCompositorWndSizeIfNecessary();
// We have to clear all references to the old backbuffer before resizing.
mRT = nullptr;

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

@ -360,6 +360,11 @@ mozilla::ipc::IPCResult CompositorBridgeParent::RecvInitialize(
MOZ_ASSERT(XRE_IsGPUProcess());
mRootLayerTreeID = aRootLayerTreeId;
#ifdef XP_WIN
if (XRE_IsGPUProcess()) {
mWidget->AsWindows()->SetRootLayerTreeID(mRootLayerTreeID);
}
#endif
Initialize();
return IPC_OK();
@ -949,6 +954,13 @@ void CompositorBridgeParent::CompositeToTarget(VsyncId aId, DrawTarget* aTarget,
}
#endif
#ifdef XP_WIN
// Update compositor window's size if it exists.
// It needs to be called here, since OS might update compositor
// window's size at unexpected timing.
mWidget->AsWindows()->UpdateCompositorWndSizeIfNecessary();
#endif
/*
* AutoResolveRefLayers handles two tasks related to Windows and Linux
* plugin window management:
@ -1661,6 +1673,30 @@ void CompositorBridgeParent::NotifyVsync(const VsyncEvent& aVsync,
obs->NotifyVsync(aVsync);
}
/* static */
void CompositorBridgeParent::ScheduleForcedComposition(
const LayersId& aLayersId) {
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_GPU);
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
MonitorAutoLock lock(*sIndirectLayerTreesLock);
auto it = sIndirectLayerTrees.find(aLayersId);
if (it == sIndirectLayerTrees.end()) {
return;
}
CompositorBridgeParent* cbp = it->second.mParent;
if (!cbp || !cbp->mWidget) {
return;
}
if (cbp->mWrBridge) {
cbp->mWrBridge->ScheduleForcedGenerateFrame();
} else if (cbp->CanComposite()) {
cbp->mCompositorScheduler->ScheduleComposition();
}
}
mozilla::ipc::IPCResult CompositorBridgeParent::RecvNotifyChildCreated(
const LayersId& child, CompositorOptions* aOptions) {
MonitorAutoLock lock(*sIndirectLayerTreesLock);

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

@ -477,6 +477,8 @@ class CompositorBridgeParent final : public CompositorBridgeParentBase,
void ScheduleRotationOnCompositorThread(const TargetConfig& aTargetConfig,
bool aIsFirstPaint);
static void ScheduleForcedComposition(const LayersId& aLayersId);
/**
* Returns the unique layer tree identifier that corresponds to the root
* tree of this compositor.

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

@ -44,6 +44,8 @@ class RenderCompositor {
virtual bool WaitForGPU() { return true; }
virtual void Pause() = 0;
virtual bool Resume() = 0;
// Called when WR rendering is skipped
virtual void Update() {}
virtual gl::GLContext* gl() const { return nullptr; }

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

@ -543,6 +543,13 @@ void RenderCompositorANGLE::Pause() {}
bool RenderCompositorANGLE::Resume() { return true; }
void RenderCompositorANGLE::Update() {
// Update compositor window's size if it exists.
// It needs to be called here, since OS might update compositor
// window's size at unexpected timing.
mWidget->AsWindows()->UpdateCompositorWndSizeIfNecessary();
}
bool RenderCompositorANGLE::MakeCurrent() {
gl::GLContextEGL::Cast(gl())->SetEGLSurfaceOverride(mEGLSurface);
return gl()->MakeCurrent();

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

@ -44,6 +44,7 @@ class RenderCompositorANGLE : public RenderCompositor {
bool WaitForGPU() override;
void Pause() override;
bool Resume() override;
void Update() override;
gl::GLContext* gl() const override { return RenderThread::Get()->SharedGL(); }

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

@ -89,6 +89,7 @@ wr::WrExternalImageHandler RendererOGL::GetExternalImageHandler() {
}
void RendererOGL::Update() {
mCompositor->Update();
if (mCompositor->MakeCurrent()) {
wr_renderer_update(mRenderer);
}

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

@ -64,14 +64,17 @@ mozilla::ipc::IPCResult CompositorWidgetChild::RecvUnobserveVsync() {
}
mozilla::ipc::IPCResult CompositorWidgetChild::RecvUpdateCompositorWnd(
const WindowsHandle& aCompositorWnd, const WindowsHandle& aParentWnd) {
const WindowsHandle& aCompositorWnd, const WindowsHandle& aParentWnd,
UpdateCompositorWndResolver&& aResolve) {
MOZ_ASSERT(mParentWnd);
HWND parentWnd = reinterpret_cast<HWND>(aParentWnd);
if (mParentWnd == parentWnd) {
mCompositorWnd = reinterpret_cast<HWND>(aCompositorWnd);
::SetParent(mCompositorWnd, mParentWnd);
aResolve(true);
} else {
aResolve(false);
gfxCriticalNote << "Parent winow does not match";
MOZ_ASSERT_UNREACHABLE("unexpected to happen");
}

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

@ -33,8 +33,8 @@ class CompositorWidgetChild final : public PCompositorWidgetChild,
mozilla::ipc::IPCResult RecvObserveVsync() override;
mozilla::ipc::IPCResult RecvUnobserveVsync() override;
mozilla::ipc::IPCResult RecvUpdateCompositorWnd(
const WindowsHandle& aCompositorWnd,
const WindowsHandle& aParentWnd) override;
const WindowsHandle& aCompositorWnd, const WindowsHandle& aParentWnd,
UpdateCompositorWndResolver&& aResolve) override;
private:
RefPtr<CompositorVsyncDispatcher> mVsyncDispatcher;

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

@ -5,6 +5,8 @@
#include "CompositorWidgetParent.h"
#include "mozilla/layers/CompositorBridgeParent.h"
#include "mozilla/layers/CompositorThread.h"
#include "mozilla/Unused.h"
#include "mozilla/widget/PlatformWidgetTypes.h"
@ -60,9 +62,29 @@ RefPtr<VsyncObserver> CompositorWidgetParent::GetVsyncObserver() const {
void CompositorWidgetParent::UpdateCompositorWnd(const HWND aCompositorWnd,
const HWND aParentWnd) {
Unused << SendUpdateCompositorWnd(
reinterpret_cast<WindowsHandle>(aCompositorWnd),
reinterpret_cast<WindowsHandle>(aParentWnd));
MOZ_ASSERT(layers::CompositorThreadHolder::IsInCompositorThread());
MOZ_ASSERT(mRootLayerTreeID.isSome());
RefPtr<CompositorWidgetParent> self = this;
SendUpdateCompositorWnd(reinterpret_cast<WindowsHandle>(aCompositorWnd),
reinterpret_cast<WindowsHandle>(aParentWnd))
->Then(
layers::CompositorThreadHolder::Loop()->SerialEventTarget(), __func__,
[self](const bool& aSuccess) {
if (aSuccess && self->mRootLayerTreeID.isSome()) {
self->mSetParentCompleted = true;
// Schedule composition after ::SetParent() call in parent
// process.
layers::CompositorBridgeParent::ScheduleForcedComposition(
self->mRootLayerTreeID.ref());
}
},
[self](const mozilla::ipc::ResponseRejectReason&) {});
}
void CompositorWidgetParent::SetRootLayerTreeID(
const layers::LayersId& aRootLayerTreeId) {
mRootLayerTreeID = Some(aRootLayerTreeId);
}
void CompositorWidgetParent::ActorDestroy(ActorDestroyReason aWhy) {}

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

@ -7,6 +7,7 @@
#define widget_windows_CompositorWidgetParent_h
#include "WinCompositorWidget.h"
#include "mozilla/Maybe.h"
#include "mozilla/widget/PCompositorWidgetParent.h"
namespace mozilla {
@ -33,9 +34,11 @@ class CompositorWidgetParent final : public PCompositorWidgetParent,
// PlatformCompositorWidgetDelegate Overrides
void UpdateCompositorWnd(const HWND aCompositorWnd,
const HWND aParentWnd) override;
void SetRootLayerTreeID(const layers::LayersId& aRootLayerTreeId) override;
private:
RefPtr<VsyncObserver> mVsyncObserver;
Maybe<layers::LayersId> mRootLayerTreeID;
};
} // namespace widget

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

@ -27,7 +27,8 @@ parent:
child:
async ObserveVsync();
async UnobserveVsync();
async UpdateCompositorWnd(WindowsHandle aCompositorWnd, WindowsHandle aParentWnd);
async UpdateCompositorWnd(WindowsHandle aCompositorWnd, WindowsHandle aParentWnd)
returns (bool success);
};
} // namespace widget

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

@ -29,6 +29,7 @@ WinCompositorWidget::WinCompositorWidget(
const WinCompositorWidgetInitData& aInitData,
const layers::CompositorOptions& aOptions)
: CompositorWidget(aOptions),
mSetParentCompleted(false),
mWidgetKey(aInitData.widgetKey()),
mWnd(reinterpret_cast<HWND>(aInitData.hWnd())),
mCompositorWnds(nullptr, nullptr),
@ -339,13 +340,26 @@ void WinCompositorWidget::UpdateCompositorWndSizeIfNecessary() {
return;
}
// Force a resize and redraw (but not a move, activate, etc.).
if (!::SetWindowPos(mCompositorWnds.mCompositorWnd, nullptr, 0, 0, size.width,
size.height,
SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOCOPYBITS |
SWP_NOOWNERZORDER | SWP_NOZORDER)) {
// This code is racing with the compositor, which needs to reparent
// the compositor surface to the actual window (mWnd). To avoid racing
// mutations, we refuse to proceed until ::SetParent() is called in parent
// process. After the ::SetParent() call, composition is scheduled in
// CompositorWidgetParent::UpdateCompositorWnd().
if (!mSetParentCompleted) {
// ::SetParent() is not completed yet.
return;
}
MOZ_ASSERT(mWnd == ::GetParent(mCompositorWnds.mCompositorWnd));
// Force a resize and redraw (but not a move, activate, etc.).
if (!::SetWindowPos(
mCompositorWnds.mCompositorWnd, nullptr, 0, 0, size.width,
size.height,
SWP_NOACTIVATE | SWP_NOCOPYBITS | SWP_NOOWNERZORDER | SWP_NOZORDER)) {
return;
}
mLastCompositorWndSize = size;
}

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

@ -11,6 +11,7 @@
#include "mozilla/Atomics.h"
#include "mozilla/gfx/CriticalSection.h"
#include "mozilla/gfx/Point.h"
#include "mozilla/layers/LayersTypes.h"
#include "mozilla/Mutex.h"
#include "mozilla/widget/WinCompositorWindowThread.h"
#include "FxROutputHandler.h"
@ -38,6 +39,7 @@ class PlatformCompositorWidgetDelegate : public CompositorWidgetDelegate {
virtual void SetParentWnd(const HWND aParentWnd) {}
virtual void UpdateCompositorWnd(const HWND aCompositorWnd,
const HWND aParentWnd) {}
virtual void SetRootLayerTreeID(const layers::LayersId& aRootLayerTreeId) {}
// CompositorWidgetDelegate Overrides
@ -119,6 +121,9 @@ class WinCompositorWidget : public CompositorWidget,
void CreateTransparentSurface(const gfx::IntSize& aSize);
protected:
bool mSetParentCompleted;
private:
uintptr_t mWidgetKey;
HWND mWnd;