summaryrefslogtreecommitdiffstats
path: root/widget/windows/WinCompositorWidget.cpp
blob: 3f0dc92a5b5f4d626e22a9e2353a8f8b596f7032 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
/* -*- 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 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