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