gecko-dev/widget/windows/WinCompositorWidget.cpp
Ray Kraesig f3d76a51df Bug 1820066 [2/3] - Allow in-process use of the compositor window r=sotaro
The in-process compositor assumes that no compositor window was present.
This is not guaranteed to be true if, for example, the preference
`gfx.webrender.flip-sequential` is set.

Make the in-process compositor more closely mirror the out-of-process
compositor. (At present this effectively just means calling ::SetParent
on the compositor window.)

Differential Revision: https://phabricator.services.mozilla.com/D172733
2023-03-27 16:54:13 +00:00

106 lines
3.3 KiB
C++

/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
#include "WinCompositorWidget.h"
#include "mozilla/StaticPrefs_layers.h"
#include "mozilla/gfx/DeviceManagerDx.h"
#include "mozilla/gfx/Point.h"
#include "mozilla/layers/Compositor.h"
#include "mozilla/layers/CompositorThread.h"
#include "mozilla/webrender/RenderThread.h"
#include "mozilla/widget/PlatformWidgetTypes.h"
#include "nsWindow.h"
#include "VsyncDispatcher.h"
#include "WinCompositorWindowThread.h"
#include "VRShMem.h"
#include <ddraw.h>
namespace mozilla {
namespace widget {
using namespace mozilla::gfx;
using namespace mozilla;
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) {
MOZ_ASSERT(mWnd && ::IsWindow(mWnd));
}
WinCompositorWidget::~WinCompositorWidget() { DestroyCompositorWindow(); }
uintptr_t WinCompositorWidget::GetWidgetKey() { return mWidgetKey; }
void WinCompositorWidget::EnsureCompositorWindow() {
if (mCompositorWnds.mCompositorWnd || mCompositorWnds.mInitialParentWnd) {
return;
}
mCompositorWnds = WinCompositorWindowThread::CreateCompositorWindow();
UpdateCompositorWnd(mCompositorWnds.mCompositorWnd, mWnd);
MOZ_ASSERT(mCompositorWnds.mCompositorWnd);
MOZ_ASSERT(mCompositorWnds.mInitialParentWnd);
}
void WinCompositorWidget::DestroyCompositorWindow() {
if (!mCompositorWnds.mCompositorWnd && !mCompositorWnds.mInitialParentWnd) {
return;
}
WinCompositorWindowThread::DestroyCompositorWindow(mCompositorWnds);
mCompositorWnds = WinCompositorWnds(nullptr, nullptr);
}
void WinCompositorWidget::UpdateCompositorWndSizeIfNecessary() {
if (!mCompositorWnds.mCompositorWnd) {
return;
}
LayoutDeviceIntSize size = GetClientSize();
if (mLastCompositorWndSize == size) {
return;
}
// 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 the 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;
}
// Creates a new instance of FxROutputHandler so that this compositor widget
// can send its output to Firefox Reality for Desktop.
void WinCompositorWidget::RequestFxrOutput() {
MOZ_ASSERT(mFxrHandler == nullptr);
mFxrHandler.reset(new FxROutputHandler());
}
} // namespace widget
} // namespace mozilla