1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3  * License, v. 2.0. If a copy of the MPL was not distributed with this
4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 
6 #include "WinCompositorWidget.h"
7 
8 #include "mozilla/StaticPrefs_layers.h"
9 #include "mozilla/gfx/DeviceManagerDx.h"
10 #include "mozilla/gfx/Point.h"
11 #include "mozilla/layers/Compositor.h"
12 #include "mozilla/layers/CompositorThread.h"
13 #include "mozilla/webrender/RenderThread.h"
14 #include "mozilla/widget/PlatformWidgetTypes.h"
15 #include "nsWindow.h"
16 #include "VsyncDispatcher.h"
17 #include "WinCompositorWindowThread.h"
18 #include "VRShMem.h"
19 
20 #include <ddraw.h>
21 
22 namespace mozilla {
23 namespace widget {
24 
25 using namespace mozilla::gfx;
26 using namespace mozilla;
27 
WinCompositorWidget(const WinCompositorWidgetInitData & aInitData,const layers::CompositorOptions & aOptions)28 WinCompositorWidget::WinCompositorWidget(
29     const WinCompositorWidgetInitData& aInitData,
30     const layers::CompositorOptions& aOptions)
31     : CompositorWidget(aOptions),
32       mSetParentCompleted(false),
33       mWidgetKey(aInitData.widgetKey()),
34       mWnd(reinterpret_cast<HWND>(aInitData.hWnd())),
35       mCompositorWnds(nullptr, nullptr) {
36   MOZ_ASSERT(mWnd && ::IsWindow(mWnd));
37 }
38 
~WinCompositorWidget()39 WinCompositorWidget::~WinCompositorWidget() { DestroyCompositorWindow(); }
40 
GetWidgetKey()41 uintptr_t WinCompositorWidget::GetWidgetKey() { return mWidgetKey; }
42 
EnsureCompositorWindow()43 void WinCompositorWidget::EnsureCompositorWindow() {
44   if (mCompositorWnds.mCompositorWnd || mCompositorWnds.mInitialParentWnd) {
45     return;
46   }
47 
48   mCompositorWnds = WinCompositorWindowThread::CreateCompositorWindow();
49   UpdateCompositorWnd(mCompositorWnds.mCompositorWnd, mWnd);
50 
51   MOZ_ASSERT(mCompositorWnds.mCompositorWnd);
52   MOZ_ASSERT(mCompositorWnds.mInitialParentWnd);
53 }
54 
DestroyCompositorWindow()55 void WinCompositorWidget::DestroyCompositorWindow() {
56   if (!mCompositorWnds.mCompositorWnd && !mCompositorWnds.mInitialParentWnd) {
57     return;
58   }
59   WinCompositorWindowThread::DestroyCompositorWindow(mCompositorWnds);
60   mCompositorWnds = WinCompositorWnds(nullptr, nullptr);
61 }
62 
UpdateCompositorWndSizeIfNecessary()63 void WinCompositorWidget::UpdateCompositorWndSizeIfNecessary() {
64   if (!mCompositorWnds.mCompositorWnd) {
65     return;
66   }
67 
68   LayoutDeviceIntSize size = GetClientSize();
69   if (mLastCompositorWndSize == size) {
70     return;
71   }
72 
73   // This code is racing with the compositor, which needs to reparent
74   // the compositor surface to the actual window (mWnd). To avoid racing
75   // mutations, we refuse to proceed until ::SetParent() is called in parent
76   // process. After the ::SetParent() call, composition is scheduled in
77   // CompositorWidgetParent::UpdateCompositorWnd().
78   if (!mSetParentCompleted) {
79     // ::SetParent() is not completed yet.
80     return;
81   }
82 
83   MOZ_ASSERT(mWnd == ::GetParent(mCompositorWnds.mCompositorWnd));
84 
85   // Force a resize and redraw (but not a move, activate, etc.).
86   if (!::SetWindowPos(
87           mCompositorWnds.mCompositorWnd, nullptr, 0, 0, size.width,
88           size.height,
89           SWP_NOACTIVATE | SWP_NOCOPYBITS | SWP_NOOWNERZORDER | SWP_NOZORDER)) {
90     return;
91   }
92 
93   mLastCompositorWndSize = size;
94 }
95 
96 // Creates a new instance of FxROutputHandler so that this compositor widget
97 // can send its output to Firefox Reality for Desktop.
RequestFxrOutput()98 void WinCompositorWidget::RequestFxrOutput() {
99   MOZ_ASSERT(mFxrHandler == nullptr);
100 
101   mFxrHandler.reset(new FxROutputHandler());
102 }
103 
104 }  // namespace widget
105 }  // namespace mozilla
106